@farming-labs/docs 0.2.61 → 0.2.62

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 (58) hide show
  1. package/package.json +1 -1
  2. package/dist/agent-DFHlw_JC.mjs +0 -624
  3. package/dist/agent-Fl0pjVNF.mjs +0 -4352
  4. package/dist/agent-evals-f4_OL10T.mjs +0 -2144
  5. package/dist/agent-export-D0zQhasD.mjs +0 -910
  6. package/dist/agent-scope-C_U--OZ7.mjs +0 -283
  7. package/dist/agent-skills-bundle.d.mts +0 -13
  8. package/dist/agent-skills-bundle.mjs +0 -12
  9. package/dist/agent-skills-server-CIeBszxp.mjs +0 -263
  10. package/dist/agent-skills-server-CKq3_jMj.d.mts +0 -12
  11. package/dist/agent-skills-vite.d.mts +0 -31
  12. package/dist/agent-skills-vite.mjs +0 -70
  13. package/dist/agents-ibnXrWyp.mjs +0 -221
  14. package/dist/analytics-Bx44lg6d.mjs +0 -177
  15. package/dist/cli/index.d.mts +0 -15
  16. package/dist/cli/index.mjs +0 -452
  17. package/dist/client/react.d.mts +0 -45
  18. package/dist/client/react.mjs +0 -223
  19. package/dist/cloud-analytics-CSyFE6SS.mjs +0 -132
  20. package/dist/cloud-ask-ai-D7ZgF47y.d.mts +0 -23
  21. package/dist/cloud-ask-ai-sbpjOR2K.mjs +0 -382
  22. package/dist/cloud-pdNC-tyj.mjs +0 -1615
  23. package/dist/code-blocks-DnNVNK2M.mjs +0 -871
  24. package/dist/codeblocks-CFuurVIH.mjs +0 -250
  25. package/dist/config-Wcdj-D0a.mjs +0 -369
  26. package/dist/dev-Cmy6DtdF.mjs +0 -1333
  27. package/dist/docs-cloud-server.d.mts +0 -70
  28. package/dist/docs-cloud-server.mjs +0 -310
  29. package/dist/doctor-CXostbsI.mjs +0 -2036
  30. package/dist/downgrade-w7e6Se0L.mjs +0 -184
  31. package/dist/errors-DbOhkE1h.mjs +0 -20
  32. package/dist/golden-evaluations-CBZ_JZjf.mjs +0 -1498
  33. package/dist/i18n-CCaFUnAN.mjs +0 -40
  34. package/dist/index.d.mts +0 -1141
  35. package/dist/index.mjs +0 -10
  36. package/dist/init-CQY0Woe3.mjs +0 -1264
  37. package/dist/mcp-DyPcoLwm.mjs +0 -156
  38. package/dist/mcp.d.mts +0 -298
  39. package/dist/mcp.mjs +0 -4426
  40. package/dist/metadata-Dv1ah0Aj.mjs +0 -237
  41. package/dist/package-version-n5AFur8a.mjs +0 -128
  42. package/dist/reading-time-C-SAhQT9.mjs +0 -742
  43. package/dist/review-D2UBrxFq.mjs +0 -673
  44. package/dist/robots-5Yqz9mz7.mjs +0 -179
  45. package/dist/robots-C08kDLsz.mjs +0 -201
  46. package/dist/search-9OnMGMvt.mjs +0 -1758
  47. package/dist/search-C6heDO8h.d.mts +0 -274
  48. package/dist/search-CNsRpz90.mjs +0 -104
  49. package/dist/server.d.mts +0 -342
  50. package/dist/server.mjs +0 -13
  51. package/dist/sitemap-BpYnSsfJ.mjs +0 -249
  52. package/dist/sitemap-server-D_0Kzanj.mjs +0 -1137
  53. package/dist/standards-discovery-C4HUqMd2.d.mts +0 -227
  54. package/dist/standards-discovery-C54V_aJH.mjs +0 -510
  55. package/dist/templates-Bq_P7ctv.mjs +0 -2465
  56. package/dist/types-EhFhYGfr.d.mts +0 -3305
  57. package/dist/upgrade-oz-GChgt.mjs +0 -56
  58. package/dist/utils-DpiIioYb.mjs +0 -225
@@ -1,250 +0,0 @@
1
- import { a as validateCodeBlocks, r as resolveDocsCodeBlocksValidateConfig } from "./code-blocks-DnNVNK2M.mjs";
2
- import { _ as resolveDocsContentDir, a as loadDocsConfigModule, f as readNumberProperty, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-Wcdj-D0a.mjs";
3
- import { existsSync, readFileSync } from "node:fs";
4
- import pc from "picocolors";
5
-
6
- //#region src/cli/codeblocks.ts
7
- function parseInlineFlag(arg) {
8
- const [rawKey, value] = arg.slice(2).split("=", 2);
9
- return {
10
- key: rawKey.trim(),
11
- value
12
- };
13
- }
14
- function parseCodeBlocksValidateArgs(argv) {
15
- const parsed = {};
16
- for (let index = 0; index < argv.length; index += 1) {
17
- const arg = argv[index];
18
- if (arg === "--help" || arg === "-h") {
19
- parsed.help = true;
20
- continue;
21
- }
22
- if (arg === "--json") {
23
- parsed.json = true;
24
- continue;
25
- }
26
- if (arg === "--plan") {
27
- parsed.plan = true;
28
- continue;
29
- }
30
- if (arg === "--run") {
31
- parsed.run = true;
32
- continue;
33
- }
34
- if (arg.startsWith("--config=")) {
35
- const value = parseInlineFlag(arg).value;
36
- if (!value) throw new Error("Missing value for --config.");
37
- parsed.configPath = value;
38
- continue;
39
- }
40
- if (arg === "--config") {
41
- const value = argv[index + 1];
42
- if (!value || value.startsWith("--")) throw new Error("Missing value for --config.");
43
- parsed.configPath = value;
44
- index += 1;
45
- continue;
46
- }
47
- throw new Error(`Unknown codeblocks validate flag: ${arg}.`);
48
- }
49
- return parsed;
50
- }
51
- function printCodeBlocksValidateHelp() {
52
- console.log(`
53
- ${pc.bold("@farming-labs/docs codeblocks validate")}
54
-
55
- ${pc.dim("Usage:")}
56
- pnpm exec docs codeblocks validate
57
- pnpm exec docs codeblocks validate --plan
58
- pnpm exec docs codeblocks validate --json
59
- pnpm exec docs codeblocks validate --config docs.config.ts
60
-
61
- ${pc.dim("Options:")}
62
- ${pc.cyan("--plan")} Build the execution plan without running code
63
- ${pc.cyan("--run")} Force execution even when config mode is ${pc.dim("\"plan\"")}
64
- ${pc.cyan("--json")} Print machine-readable output
65
- ${pc.cyan("--config <path>")} Use a custom docs config path instead of ${pc.dim("docs.config.ts[x]")}
66
- ${pc.cyan("-h, --help")} Show this help message
67
- `);
68
- }
69
- async function runCodeBlocksValidate(options = {}) {
70
- const rootDir = process.cwd();
71
- const loaded = await loadDocsConfigModule(rootDir, options.configPath, { silent: options.json });
72
- const configPath = loaded?.path ?? resolveDocsConfigPath(rootDir, options.configPath);
73
- const configContent = existsSync(configPath) ? readFileSync(configPath, "utf-8") : "";
74
- const entry = loaded?.config.entry ?? readTopLevelStringProperty(configContent, "entry") ?? "docs";
75
- const contentDir = loaded?.config.contentDir ?? resolveDocsContentDir(rootDir, configContent, entry);
76
- const config = resolveDocsCodeBlocksValidateConfig(loaded?.config.codeBlocks?.validate ?? readStaticCodeBlocksValidateConfig(configContent));
77
- if (!config.enabled) {
78
- const disabledReport = {
79
- summary: {
80
- total: 0,
81
- planned: 0,
82
- pass: 0,
83
- skip: 0,
84
- fail: 0
85
- },
86
- config,
87
- targets: [],
88
- plans: [],
89
- results: []
90
- };
91
- if (options.json) console.log(JSON.stringify(redactReport(disabledReport), null, 2));
92
- else console.log(pc.yellow("codeBlocks.validate is disabled. Add `codeBlocks: { validate: true }` to docs.config.ts."));
93
- return disabledReport;
94
- }
95
- const effectiveConfig = {
96
- ...config,
97
- mode: options.run ? "report" : config.mode
98
- };
99
- const planOnly = options.plan === true || effectiveConfig.mode === "plan";
100
- const report = await validateCodeBlocks({
101
- rootDir,
102
- contentDir,
103
- config: effectiveConfig,
104
- planOnly: options.plan
105
- });
106
- if (options.json) console.log(JSON.stringify(redactReport(report), null, 2));
107
- else printCodeBlocksReport(report, planOnly);
108
- if (!options.plan && report.summary.fail > 0) process.exitCode = 1;
109
- return report;
110
- }
111
- function readStaticCodeBlocksValidateConfig(content) {
112
- const block = extractNestedObjectLiteral(content, ["codeBlocks"]);
113
- if (!block) return void 0;
114
- if (/\bvalidate\s*:\s*true\b/.test(block)) return true;
115
- if (/\bvalidate\s*:\s*false\b/.test(block)) return false;
116
- const validateBlock = extractNestedObjectLiteral(content, ["codeBlocks", "validate"]);
117
- if (validateBlock) {
118
- const config = {};
119
- const enabled = readBooleanProperty(validateBlock, "enabled");
120
- const mode = readStringProperty(validateBlock, "mode");
121
- const missingEnv = readStringProperty(validateBlock, "missingEnv");
122
- const unsupportedLanguage = readStringProperty(validateBlock, "unsupportedLanguage");
123
- const envFile = readStringArrayProperty(validateBlock, "envFile");
124
- if (enabled !== void 0) config.enabled = enabled;
125
- if (mode === "plan" || mode === "report") config.mode = mode;
126
- if (missingEnv === "skip" || missingEnv === "warn" || missingEnv === "error") config.missingEnv = missingEnv;
127
- if (unsupportedLanguage === "skip" || unsupportedLanguage === "warn" || unsupportedLanguage === "error") config.unsupportedLanguage = unsupportedLanguage;
128
- if (envFile) config.envFile = envFile;
129
- const planner = readStaticPlannerConfig(extractNestedObjectLiteral(content, [
130
- "codeBlocks",
131
- "validate",
132
- "planner"
133
- ]));
134
- if (planner) config.planner = planner;
135
- const runner = readStaticRunnerConfig(extractNestedObjectLiteral(content, [
136
- "codeBlocks",
137
- "validate",
138
- "runner"
139
- ]));
140
- if (runner) config.runner = runner;
141
- const env = readStringRecord(extractNestedObjectLiteral(content, [
142
- "codeBlocks",
143
- "validate",
144
- "env"
145
- ]));
146
- if (env && Object.keys(env).length > 0) config.env = env;
147
- return config;
148
- }
149
- if (/\bvalidate\s*:\s*\{/.test(block)) return true;
150
- }
151
- function readStaticPlannerConfig(block) {
152
- if (!block) return void 0;
153
- const provider = readStringProperty(block, "provider");
154
- const model = readStringProperty(block, "model");
155
- const baseUrl = readStringProperty(block, "baseUrl");
156
- const baseUrlEnv = readStringProperty(block, "baseUrlEnv");
157
- const apiKeyEnv = readStringProperty(block, "apiKeyEnv");
158
- if (provider !== "metadata" && provider !== "openai" && provider !== "openai-compatible" && provider !== "cloud") return;
159
- return {
160
- provider,
161
- ...model ? { model } : {},
162
- ...baseUrl ? { baseUrl } : {},
163
- ...baseUrlEnv ? { baseUrlEnv } : {},
164
- ...apiKeyEnv ? { apiKeyEnv } : {}
165
- };
166
- }
167
- function readStaticRunnerConfig(block) {
168
- if (!block) return void 0;
169
- const provider = readStringProperty(block, "provider");
170
- const tokenEnv = readStringProperty(block, "tokenEnv");
171
- const projectIdEnv = readStringProperty(block, "projectIdEnv");
172
- const teamIdEnv = readStringProperty(block, "teamIdEnv");
173
- const projectJson = readStringProperty(block, "projectJson");
174
- const runtime = readStringProperty(block, "runtime");
175
- const apiUrlEnv = readStringProperty(block, "apiUrlEnv");
176
- const targetEnv = readStringProperty(block, "targetEnv");
177
- const timeoutMs = readNumberProperty(block, "timeoutMs");
178
- if (provider !== "local" && provider !== "vercel-sandbox" && provider !== "e2b" && provider !== "daytona" && provider !== "cloud") return;
179
- return {
180
- provider,
181
- ...tokenEnv ? { tokenEnv } : {},
182
- ...projectIdEnv ? { projectIdEnv } : {},
183
- ...teamIdEnv ? { teamIdEnv } : {},
184
- ...projectJson ? { projectJson } : {},
185
- ...runtime === "node24" || runtime === "node22" || runtime === "python3.13" ? { runtime } : {},
186
- ...apiUrlEnv ? { apiUrlEnv } : {},
187
- ...targetEnv ? { targetEnv } : {},
188
- ...timeoutMs !== void 0 ? { timeoutMs } : {}
189
- };
190
- }
191
- function readStringArrayProperty(content, key) {
192
- const single = readStringProperty(content, key);
193
- if (single) return [single];
194
- const match = content.match(new RegExp(`\\b${key}\\b\\s*:\\s*\\[([\\s\\S]*?)\\]`));
195
- if (!match) return void 0;
196
- const values = [...match[1].matchAll(/["']([^"']+)["']/g)].map((item) => item[1]);
197
- return values.length > 0 ? values : void 0;
198
- }
199
- function readStringRecord(block) {
200
- if (!block) return void 0;
201
- const record = {};
202
- for (const pattern of [/(?:^|,)\s*([A-Za-z_$][\w$]*)\s*:\s*["']([^"']+)["']/g, /(?:^|,)\s*["']([^"']+)["']\s*:\s*["']([^"']+)["']/g]) {
203
- let match;
204
- while (match = pattern.exec(block)) record[match[1]] = match[2];
205
- }
206
- return record;
207
- }
208
- function printCodeBlocksReport(report, planOnly) {
209
- const label = planOnly ? "Code block plan" : "Code block validation";
210
- console.log(pc.bold(label));
211
- console.log([
212
- ...report.summary.planned > 0 ? [`${pc.cyan(`${report.summary.planned} planned`)}`] : [],
213
- `${pc.green(`${report.summary.pass} pass`)}`,
214
- `${pc.yellow(`${report.summary.skip} skip`)}`,
215
- `${report.summary.fail > 0 ? pc.red(`${report.summary.fail} fail`) : pc.dim("0 fail")}`,
216
- `${report.targets.length} code blocks`
217
- ].join(pc.dim(" • ")));
218
- if (report.results.length === 0) return;
219
- console.log();
220
- for (const result of report.results) {
221
- const status = result.status === "PLAN" ? pc.cyan(result.status) : result.status === "PASS" ? pc.green(result.status) : result.status === "FAIL" ? pc.red(result.status) : pc.yellow(result.status);
222
- const location = `${result.target.relativePath}:${result.target.lineStart}`;
223
- const detail = result.reason ?? result.plan.reason ?? result.plan.template;
224
- console.log(`${status} ${pc.cyan(location)} ${pc.dim(detail)}`);
225
- }
226
- }
227
- function redactReport(report) {
228
- return {
229
- ...report,
230
- config: {
231
- ...report.config,
232
- planner: {
233
- ...report.config.planner,
234
- apiKey: report.config.planner.apiKey ? "[REDACTED]" : void 0
235
- }
236
- },
237
- results: report.results.map((result) => ({
238
- ...result,
239
- stdout: trimOutput(result.stdout),
240
- stderr: trimOutput(result.stderr)
241
- }))
242
- };
243
- }
244
- function trimOutput(value) {
245
- if (!value) return value;
246
- return value.length > 4e3 ? `${value.slice(0, 4e3)}...` : value;
247
- }
248
-
249
- //#endregion
250
- export { parseCodeBlocksValidateArgs, printCodeBlocksValidateHelp, runCodeBlocksValidate };
@@ -1,369 +0,0 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { dirname, join, relative, resolve, sep } from "node:path";
3
-
4
- //#region src/cli/config.ts
5
- const FILE_EXTS = [
6
- "tsx",
7
- "ts",
8
- "jsx",
9
- "js"
10
- ];
11
- function escapeRegExp(value) {
12
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
13
- }
14
- function createPropertyPattern(key, valuePattern) {
15
- return new RegExp(`\\b${escapeRegExp(key)}\\b\\s*:\\s*${valuePattern}`);
16
- }
17
- function findBalancedBraceEnd(content, braceStart) {
18
- let depth = 0;
19
- let stringQuote = null;
20
- let escaped = false;
21
- let lineComment = false;
22
- let blockComment = false;
23
- for (let index = braceStart; index < content.length; index += 1) {
24
- const char = content[index];
25
- const next = content[index + 1];
26
- if (lineComment) {
27
- if (char === "\n") lineComment = false;
28
- continue;
29
- }
30
- if (blockComment) {
31
- if (char === "*" && next === "/") {
32
- blockComment = false;
33
- index += 1;
34
- }
35
- continue;
36
- }
37
- if (stringQuote) {
38
- if (escaped) {
39
- escaped = false;
40
- continue;
41
- }
42
- if (char === "\\") {
43
- escaped = true;
44
- continue;
45
- }
46
- if (char === stringQuote) stringQuote = null;
47
- continue;
48
- }
49
- if (char === "/" && next === "/") {
50
- lineComment = true;
51
- index += 1;
52
- continue;
53
- }
54
- if (char === "/" && next === "*") {
55
- blockComment = true;
56
- index += 1;
57
- continue;
58
- }
59
- if (char === "\"" || char === "'" || char === "`") {
60
- stringQuote = char;
61
- continue;
62
- }
63
- if (char === "{") {
64
- depth += 1;
65
- continue;
66
- }
67
- if (char !== "}") continue;
68
- depth -= 1;
69
- if (depth === 0) return index;
70
- }
71
- return -1;
72
- }
73
- function resolveDocsConfigPath(rootDir, explicitPath) {
74
- if (explicitPath) {
75
- const resolvedPath = resolve(rootDir, explicitPath);
76
- if (!existsSync(resolvedPath)) throw new Error(`Could not find docs config at ${explicitPath}.`);
77
- return resolvedPath;
78
- }
79
- for (const ext of FILE_EXTS) {
80
- const configPath = join(rootDir, `docs.config.${ext}`);
81
- if (existsSync(configPath)) return configPath;
82
- }
83
- throw new Error("Could not find docs.config.ts or docs.config.tsx in the current project. Use --config to point at a custom path.");
84
- }
85
- function readStringProperty(content, key) {
86
- return content.match(createPropertyPattern(key, `["']([^"']+)["']`))?.[1];
87
- }
88
- function readEnvReferenceProperty(content, key) {
89
- const patterns = [
90
- createPropertyPattern(key, `process\\.env\\.([A-Za-z_$][\\w$]*)`),
91
- createPropertyPattern(key, `process\\.env\\[['"]([^"'\\]]+)['"]\\]`),
92
- createPropertyPattern(key, `import\\.meta\\.env\\.([A-Za-z_$][\\w$]*)`),
93
- createPropertyPattern(key, `import\\.meta\\.env\\[['"]([^"'\\]]+)['"]\\]`)
94
- ];
95
- for (const pattern of patterns) {
96
- const match = content.match(pattern);
97
- if (match?.[1]) return match[1];
98
- }
99
- }
100
- function readBooleanProperty(content, key) {
101
- const match = content.match(createPropertyPattern(key, "(true|false)"));
102
- return match ? match[1] === "true" : void 0;
103
- }
104
- function readNumberProperty(content, key) {
105
- const match = content.match(createPropertyPattern(key, "(-?\\d+(?:\\.\\d+)?)"));
106
- if (!match) return void 0;
107
- const parsed = Number.parseFloat(match[1]);
108
- return Number.isFinite(parsed) ? parsed : void 0;
109
- }
110
- function extractObjectLiteral(content, key) {
111
- const keyIndex = content.search(new RegExp(`${key}\\s*:\\s*\\{`));
112
- if (keyIndex === -1) return void 0;
113
- const braceStart = content.indexOf("{", keyIndex);
114
- if (braceStart === -1) return void 0;
115
- const braceEnd = findBalancedBraceEnd(content, braceStart);
116
- return braceEnd === -1 ? void 0 : content.slice(braceStart + 1, braceEnd);
117
- }
118
- function stripLeadingPropertyTrivia(content) {
119
- let current = content;
120
- while (true) {
121
- const trimmed = current.replace(/^\s+/, "");
122
- if (trimmed.startsWith("//")) {
123
- const lineEnd = trimmed.indexOf("\n");
124
- current = lineEnd === -1 ? "" : trimmed.slice(lineEnd + 1);
125
- continue;
126
- }
127
- if (trimmed.startsWith("/*")) {
128
- const blockEnd = trimmed.indexOf("*/");
129
- current = blockEnd === -1 ? trimmed : trimmed.slice(blockEnd + 2);
130
- continue;
131
- }
132
- return trimmed;
133
- }
134
- }
135
- function extractTopLevelObjectLiteral(content, key) {
136
- const propertyPattern = new RegExp(`^${escapeRegExp(key)}\\s*:\\s*\\{`);
137
- for (const property of splitTopLevelProperties(content)) {
138
- const normalizedProperty = stripLeadingPropertyTrivia(property);
139
- if (!propertyPattern.test(normalizedProperty)) continue;
140
- const braceStart = normalizedProperty.indexOf("{");
141
- if (braceStart === -1) return void 0;
142
- const braceEnd = findBalancedBraceEnd(normalizedProperty, braceStart);
143
- return braceEnd === -1 ? void 0 : normalizedProperty.slice(braceStart + 1, braceEnd);
144
- }
145
- }
146
- /** Return whether an object-literal body declares a direct property with this name. */
147
- function hasTopLevelProperty(content, key) {
148
- const escaped = escapeRegExp(key);
149
- const propertyPattern = new RegExp(`^(?:${escaped}|["']${escaped}["'])\\s*:`);
150
- return splitTopLevelProperties(content).some((property) => propertyPattern.test(stripLeadingPropertyTrivia(property)));
151
- }
152
- function extractTopLevelConfigObject(content) {
153
- for (const marker of ["defineDocs(", "export default"]) {
154
- const markerIndex = content.indexOf(marker);
155
- if (markerIndex === -1) continue;
156
- const braceStart = content.indexOf("{", markerIndex);
157
- if (braceStart === -1) continue;
158
- const braceEnd = findBalancedBraceEnd(content, braceStart);
159
- if (braceEnd !== -1) return content.slice(braceStart + 1, braceEnd);
160
- }
161
- }
162
- function extractNestedObjectLiteral(content, keys) {
163
- if (keys.length === 0) return void 0;
164
- let current = extractTopLevelConfigObject(content) ?? content;
165
- for (const key of keys) {
166
- const next = extractTopLevelObjectLiteral(current, key);
167
- if (!next) return void 0;
168
- current = next;
169
- }
170
- return current;
171
- }
172
- function splitTopLevelProperties(content) {
173
- const properties = [];
174
- let start = 0;
175
- let stringQuote = null;
176
- let escaped = false;
177
- let braceDepth = 0;
178
- let bracketDepth = 0;
179
- let parenDepth = 0;
180
- for (let index = 0; index < content.length; index += 1) {
181
- const char = content[index];
182
- if (stringQuote) {
183
- if (escaped) {
184
- escaped = false;
185
- continue;
186
- }
187
- if (char === "\\") {
188
- escaped = true;
189
- continue;
190
- }
191
- if (char === stringQuote) stringQuote = null;
192
- continue;
193
- }
194
- if (char === "\"" || char === "'" || char === "`") {
195
- stringQuote = char;
196
- continue;
197
- }
198
- if (char === "{") {
199
- braceDepth += 1;
200
- continue;
201
- }
202
- if (char === "}") {
203
- braceDepth = Math.max(0, braceDepth - 1);
204
- continue;
205
- }
206
- if (char === "[") {
207
- bracketDepth += 1;
208
- continue;
209
- }
210
- if (char === "]") {
211
- bracketDepth = Math.max(0, bracketDepth - 1);
212
- continue;
213
- }
214
- if (char === "(") {
215
- parenDepth += 1;
216
- continue;
217
- }
218
- if (char === ")") {
219
- parenDepth = Math.max(0, parenDepth - 1);
220
- continue;
221
- }
222
- if (char === "," && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {
223
- properties.push(content.slice(start, index));
224
- start = index + 1;
225
- }
226
- }
227
- const trailing = content.slice(start);
228
- if (trailing.trim().length > 0) properties.push(trailing);
229
- return properties;
230
- }
231
- function readTopLevelStringProperty(content, key) {
232
- const source = extractTopLevelConfigObject(content) ?? content;
233
- const propertyPattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*:\\s*["']([^"']+)["']`);
234
- for (const property of splitTopLevelProperties(source)) {
235
- const match = property.trim().match(propertyPattern);
236
- if (match) return match[1];
237
- }
238
- }
239
- function readTopLevelBooleanProperty(content, key) {
240
- const source = extractTopLevelConfigObject(content) ?? content;
241
- const propertyPattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*:\\s*(true|false)\\b`);
242
- for (const property of splitTopLevelProperties(source)) {
243
- const match = property.trim().match(propertyPattern);
244
- if (match) return match[1] === "true";
245
- }
246
- }
247
- function readNavTitle(content) {
248
- const block = extractObjectLiteral(extractTopLevelConfigObject(content) ?? content, "nav");
249
- if (!block) return void 0;
250
- return readStringProperty(block, "title");
251
- }
252
- function resolveDocsContentDir(rootDir, content, entry) {
253
- const configuredContentDir = readTopLevelStringProperty(content, "contentDir");
254
- if (configuredContentDir) return configuredContentDir;
255
- const candidates = [
256
- entry,
257
- join("app", entry),
258
- join("src", "app", entry)
259
- ];
260
- for (const candidate of candidates) if (existsSync(join(rootDir, candidate))) return candidate;
261
- return entry;
262
- }
263
- function parseEnvValue(rawValue) {
264
- const value = rawValue.trim();
265
- if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) return value.slice(1, -1);
266
- return value;
267
- }
268
- function loadProjectEnv(rootDir) {
269
- const env = {};
270
- for (const filename of [".env", ".env.local"]) {
271
- const fullPath = join(rootDir, filename);
272
- if (!existsSync(fullPath)) continue;
273
- const lines = readFileSync(fullPath, "utf-8").split(/\r?\n/);
274
- for (const line of lines) {
275
- const trimmed = line.trim();
276
- if (!trimmed || trimmed.startsWith("#")) continue;
277
- const equalsIndex = trimmed.indexOf("=");
278
- if (equalsIndex === -1) continue;
279
- const key = trimmed.slice(0, equalsIndex).trim();
280
- const rawValue = trimmed.slice(equalsIndex + 1);
281
- if (!key) continue;
282
- env[key] = parseEnvValue(rawValue);
283
- }
284
- }
285
- return env;
286
- }
287
- async function loadDocsConfigModule(rootDir, explicitPath, options = {}) {
288
- const result = await loadDocsConfigModuleResult(rootDir, explicitPath, options);
289
- return result.status === "evaluated" ? {
290
- path: result.path,
291
- config: result.config
292
- } : null;
293
- }
294
- function resolveDocsConfigModuleExport(loaded) {
295
- if (!loaded || typeof loaded !== "object" || Array.isArray(loaded)) return loaded;
296
- const record = loaded;
297
- return Object.prototype.hasOwnProperty.call(record, "default") ? record.default : loaded;
298
- }
299
- function isPlainDocsConfig(value) {
300
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
301
- const prototype = Object.getPrototypeOf(value);
302
- return prototype === Object.prototype || prototype === null;
303
- }
304
- function resolveDocsConfigTsconfigPath(rootDir, configPath) {
305
- const projectRoot = resolve(rootDir);
306
- let currentDir = dirname(configPath);
307
- while (true) {
308
- const tsconfigPath = join(currentDir, "tsconfig.json");
309
- if (existsSync(tsconfigPath)) return tsconfigPath;
310
- if (currentDir === projectRoot) return false;
311
- const parentDir = dirname(currentDir);
312
- if (parentDir === currentDir) return false;
313
- const relativeParent = relative(projectRoot, parentDir);
314
- if (relativeParent === ".." || relativeParent.startsWith(`..${sep}`)) return false;
315
- currentDir = parentDir;
316
- }
317
- }
318
- /**
319
- * Load docs.config with an explicit confidence signal for diagnostics.
320
- * Existing callers can keep using `loadDocsConfigModule`, which preserves the
321
- * previous evaluated-config-or-null contract.
322
- */
323
- async function loadDocsConfigModuleResult(rootDir, explicitPath, options = {}) {
324
- const configPath = resolveDocsConfigPath(rootDir, explicitPath);
325
- try {
326
- const { createJiti } = await import("jiti");
327
- const config = resolveDocsConfigModuleExport(await createJiti(import.meta.url, {
328
- moduleCache: false,
329
- fsCache: false,
330
- interopDefault: false,
331
- jsx: { runtime: "automatic" },
332
- tsconfigPaths: resolveDocsConfigTsconfigPath(rootDir, configPath)
333
- }).import(configPath));
334
- if (!isPlainDocsConfig(config)) return {
335
- status: "static-fallback",
336
- path: configPath,
337
- error: "The config module did not export a plain object."
338
- };
339
- return {
340
- status: "evaluated",
341
- path: configPath,
342
- config
343
- };
344
- } catch (error) {
345
- const message = error instanceof Error ? error.message : String(error);
346
- if (!options.silent && process.env.NODE_ENV !== "test") console.warn(`[docs] Could not evaluate ${configPath} as a module; falling back to static parsing. ${message}`);
347
- return {
348
- status: "static-fallback",
349
- path: configPath,
350
- error: message
351
- };
352
- }
353
- }
354
- /** Evaluate docs.config after loading project-local env files, then restore process.env. */
355
- async function loadDocsConfigModuleResultWithProjectEnv(rootDir, explicitPath, options = {}) {
356
- const env = loadProjectEnv(rootDir);
357
- const injectedKeys = Object.entries(env).filter(([key]) => process.env[key] === void 0).map(([key, value]) => {
358
- process.env[key] = value;
359
- return key;
360
- });
361
- try {
362
- return await loadDocsConfigModuleResult(rootDir, explicitPath, options);
363
- } finally {
364
- for (const key of injectedKeys) delete process.env[key];
365
- }
366
- }
367
-
368
- //#endregion
369
- export { resolveDocsContentDir as _, loadDocsConfigModule as a, loadProjectEnv as c, readNavTitle as d, readNumberProperty as f, resolveDocsConfigPath as g, readTopLevelStringProperty as h, hasTopLevelProperty as i, readBooleanProperty as l, readTopLevelBooleanProperty as m, extractObjectLiteral as n, loadDocsConfigModuleResult as o, readStringProperty as p, extractTopLevelConfigObject as r, loadDocsConfigModuleResultWithProjectEnv as s, extractNestedObjectLiteral as t, readEnvReferenceProperty as u };