@open-agent-toolkit/cli 0.3.25 → 0.3.26

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 (42) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/docs-tooling/add-docs-to-a-repo.md +14 -6
  3. package/assets/docs/docs-tooling/commands.md +12 -9
  4. package/assets/docs/reference/cli-reference.md +1 -1
  5. package/assets/docs/reference/configuration.md +2 -1
  6. package/assets/docs/reference/docs-index-contract.md +19 -6
  7. package/assets/docs/reference/oat-directory-structure.md +13 -0
  8. package/assets/public-package-versions.json +4 -4
  9. package/assets/skills/oat-docs-bootstrap/SKILL.md +11 -4
  10. package/assets/templates/docs-app-fuma/package.json.template +1 -1
  11. package/assets/templates/docs-app-fuma/source.config.ts +6 -1
  12. package/assets/templates/docs-app-mkdocs/package.json.template +2 -2
  13. package/dist/commands/config/index.d.ts.map +1 -1
  14. package/dist/commands/config/index.js +21 -3
  15. package/dist/commands/docs/index-generate/generator.d.ts +4 -34
  16. package/dist/commands/docs/index-generate/generator.d.ts.map +1 -1
  17. package/dist/commands/docs/index-generate/generator.js +51 -157
  18. package/dist/commands/docs/index-generate/index.d.ts +1 -1
  19. package/dist/commands/docs/index-generate/index.d.ts.map +1 -1
  20. package/dist/commands/docs/index-generate/index.js +26 -8
  21. package/dist/commands/docs/init/index.d.ts.map +1 -1
  22. package/dist/commands/docs/init/index.js +21 -1
  23. package/dist/commands/docs/init/scaffold.d.ts.map +1 -1
  24. package/dist/commands/docs/init/scaffold.js +20 -13
  25. package/dist/commands/docs/nav/contents.d.ts +13 -3
  26. package/dist/commands/docs/nav/contents.d.ts.map +1 -1
  27. package/dist/commands/docs/nav/contents.js +85 -24
  28. package/dist/commands/docs/nav/fumadocs.d.ts +1 -0
  29. package/dist/commands/docs/nav/fumadocs.d.ts.map +1 -1
  30. package/dist/commands/docs/nav/fumadocs.js +26 -9
  31. package/dist/commands/docs/nav/sync.d.ts +2 -0
  32. package/dist/commands/docs/nav/sync.d.ts.map +1 -1
  33. package/dist/commands/docs/nav/sync.js +21 -1
  34. package/dist/commands/docs/shared/exclusions.d.ts +37 -0
  35. package/dist/commands/docs/shared/exclusions.d.ts.map +1 -0
  36. package/dist/commands/docs/shared/exclusions.js +161 -0
  37. package/dist/config/oat-config.d.ts +2 -0
  38. package/dist/config/oat-config.d.ts.map +1 -1
  39. package/dist/config/oat-config.js +6 -3
  40. package/dist/config/resolve.d.ts.map +1 -1
  41. package/dist/config/resolve.js +1 -0
  42. package/package.json +2 -2
@@ -1,155 +1,9 @@
1
1
  import { readdir, readFile } from 'node:fs/promises';
2
- import { join } from 'node:path';
3
- const NO_EXCLUSIONS = {
4
- excludesFile: () => false,
5
- excludesDirectory: () => false,
6
- };
7
- /**
8
- * Match one path segment against one pattern segment, where `*` is the only
9
- * metacharacter and never crosses `/`.
10
- *
11
- * This is the classic greedy two-pointer wildcard match, deliberately not a
12
- * compiled regular expression: a pattern like `*a*a*a...` translates to
13
- * nested-quantifier alternatives that backtrack exponentially, and exclusion
14
- * patterns come from config and flags where a typo should not hang generation.
15
- * Restarting from the last `*` instead bounds the work at O(pattern x text).
16
- */
17
- function matchSegment(pattern, text) {
18
- let patternIndex = 0;
19
- let textIndex = 0;
20
- let starPatternIndex = -1;
21
- let starTextIndex = 0;
22
- while (textIndex < text.length) {
23
- if (pattern[patternIndex] === '*') {
24
- // Collapse a run of stars: within a segment they are all equivalent.
25
- while (pattern[patternIndex] === '*') {
26
- patternIndex += 1;
27
- }
28
- if (patternIndex === pattern.length) {
29
- return true;
30
- }
31
- starPatternIndex = patternIndex;
32
- starTextIndex = textIndex;
33
- continue;
34
- }
35
- if (patternIndex < pattern.length &&
36
- pattern[patternIndex] === text[textIndex]) {
37
- patternIndex += 1;
38
- textIndex += 1;
39
- continue;
40
- }
41
- if (starPatternIndex === -1) {
42
- return false;
43
- }
44
- // Give the last star one more character and retry from just after it.
45
- starTextIndex += 1;
46
- patternIndex = starPatternIndex;
47
- textIndex = starTextIndex;
48
- }
49
- while (pattern[patternIndex] === '*') {
50
- patternIndex += 1;
51
- }
52
- return patternIndex === pattern.length;
53
- }
54
- /**
55
- * Match a docs-root-relative path against a pattern, segment by segment, where
56
- * a whole-segment `**` spans zero or more path segments.
57
- *
58
- * Same greedy-restart shape as {@link matchSegment}, one level up, so a pattern
59
- * full of `**` segments stays bounded too.
60
- */
61
- function matchPath(patternSegments, pathSegments) {
62
- let patternIndex = 0;
63
- let pathIndex = 0;
64
- let starPatternIndex = -1;
65
- let starPathIndex = 0;
66
- while (pathIndex < pathSegments.length) {
67
- if (patternSegments[patternIndex] === '**') {
68
- while (patternSegments[patternIndex] === '**') {
69
- patternIndex += 1;
70
- }
71
- if (patternIndex === patternSegments.length) {
72
- return true;
73
- }
74
- starPatternIndex = patternIndex;
75
- starPathIndex = pathIndex;
76
- continue;
77
- }
78
- if (patternIndex < patternSegments.length &&
79
- matchSegment(patternSegments[patternIndex], pathSegments[pathIndex])) {
80
- patternIndex += 1;
81
- pathIndex += 1;
82
- continue;
83
- }
84
- if (starPatternIndex === -1) {
85
- return false;
86
- }
87
- starPathIndex += 1;
88
- patternIndex = starPatternIndex;
89
- pathIndex = starPathIndex;
90
- }
91
- while (patternSegments[patternIndex] === '**') {
92
- patternIndex += 1;
93
- }
94
- return patternIndex === patternSegments.length;
95
- }
96
- /**
97
- * Compile exclusion globs matched against **docs-root-relative POSIX paths**
98
- * (`api/auth.md`, `api/nested`), never against absolute or CWD-relative ones.
99
- *
100
- * Grammar, defined once and documented in
101
- * `apps/oat-docs/docs/reference/oat-directory-structure.md`:
102
- *
103
- * - `*` matches any run of characters inside a single path segment.
104
- * - `**` spans `/` only as a whole segment, where it covers zero or more
105
- * segments: `**\/CLAUDE.md` matches `CLAUDE.md` and `api/CLAUDE.md`. Inside a
106
- * segment (`a**b`) it is an ordinary single-segment wildcard.
107
- * - Patterns are anchored at both ends against the whole relative path, so a
108
- * bare `CLAUDE.md` matches only the root-level file. Use `**\/CLAUDE.md` for
109
- * every depth.
110
- * - A trailing `/` restricts a pattern to directories: `drafts/` prunes the
111
- * `drafts` directory and everything beneath it, and never matches a file.
112
- * Without it, a pattern that matches a directory path prunes it too.
113
- * - Matching is case-sensitive, `/` is the separator on every platform, and
114
- * `*` is the only metacharacter — `.`, `+`, and friends are literal.
115
- *
116
- * Entries are trimmed; a leading `./` or `/` is stripped so both spellings
117
- * anchor at the docs root. Blank entries are ignored.
118
- */
119
- export function createExclusionMatcher(patterns) {
120
- const filePatterns = [];
121
- const directoryPatterns = [];
122
- for (const rawPattern of patterns) {
123
- const trimmedPattern = rawPattern.trim();
124
- if (!trimmedPattern) {
125
- continue;
126
- }
127
- const directoryOnly = trimmedPattern.endsWith('/');
128
- const normalized = trimmedPattern
129
- .replace(/\/+$/, '')
130
- .replace(/^\.\//, '')
131
- .replace(/^\/+/, '');
132
- if (!normalized) {
133
- continue;
134
- }
135
- const segments = normalized.split('/');
136
- directoryPatterns.push(segments);
137
- if (!directoryOnly) {
138
- filePatterns.push(segments);
139
- }
140
- }
141
- if (directoryPatterns.length === 0) {
142
- return NO_EXCLUSIONS;
143
- }
144
- const matches = (compiled, relativePath) => {
145
- const pathSegments = relativePath.split('/');
146
- return compiled.some((segments) => matchPath(segments, pathSegments));
147
- };
148
- return {
149
- excludesFile: (relativePath) => matches(filePatterns, relativePath),
150
- excludesDirectory: (relativePath) => matches(directoryPatterns, relativePath),
151
- };
152
- }
2
+ import { join, relative, resolve } from 'node:path';
3
+ import { hasIndexContents, parseIndexContents, } from '../../docs/nav/contents.js';
4
+ import { resolveFolderTitle } from '../../docs/nav/fumadocs.js';
5
+ import { createExclusionMatcher, } from '../../docs/shared/exclusions.js';
6
+ export { createExclusionMatcher } from '../../docs/shared/exclusions.js';
153
7
  const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---/;
154
8
  const HEADING_RE = /^#\s+(.+)$/m;
155
9
  function fileNameToTitle(fileName) {
@@ -206,17 +60,18 @@ function sortEntries(entries) {
206
60
  function prefixEntryPath(entry, prefix) {
207
61
  return {
208
62
  ...entry,
209
- path: join(prefix, entry.path),
63
+ path: relativeKey(prefix, entry.path),
210
64
  children: entry.children?.map((child) => prefixEntryPath(child, prefix)),
211
65
  };
212
66
  }
213
- /** Docs-root-relative POSIX path used for matching, never for reading files. */
67
+ /** Relative POSIX path used for matching and manifests, never for file IO. */
214
68
  function relativeKey(base, name) {
215
69
  return base ? `${base}/${name}` : name;
216
70
  }
217
71
  async function collectEntries(docsDir, relativeBase, matcher) {
218
72
  const entries = [];
219
73
  const subdirs = [];
74
+ let indexMarkdown;
220
75
  const dirEntries = await readdir(docsDir, { withFileTypes: true });
221
76
  for (const entry of dirEntries) {
222
77
  const relativePath = relativeKey(relativeBase, entry.name);
@@ -231,6 +86,8 @@ async function collectEntries(docsDir, relativeBase, matcher) {
231
86
  }
232
87
  const filePath = join(docsDir, entry.name);
233
88
  const content = await readFile(filePath, 'utf8');
89
+ if (entry.name === 'index.md')
90
+ indexMarkdown = content;
234
91
  const { title, description } = resolveTitle(content, entry.name);
235
92
  entries.push({
236
93
  title,
@@ -246,13 +103,50 @@ async function collectEntries(docsDir, relativeBase, matcher) {
246
103
  // them, and it composes upward through the recursion.
247
104
  if (children.length > 0) {
248
105
  entries.push({
249
- title: fileNameToTitle(subdir),
106
+ title: children.find((child) => child.path === 'index.md')
107
+ ? (resolveFolderTitle(await readFile(join(docsDir, subdir, 'index.md'), 'utf8')) ?? fileNameToTitle(subdir))
108
+ : fileNameToTitle(subdir),
250
109
  path: subdir,
251
110
  children: children.map((child) => prefixEntryPath(child, subdir)),
252
111
  });
253
112
  }
254
113
  }
255
- return sortEntries(entries);
114
+ const fallback = sortEntries(entries);
115
+ if (indexMarkdown === undefined || !hasIndexContents(indexMarkdown))
116
+ return fallback;
117
+ const contents = parseIndexContents(indexMarkdown, join(docsDir, 'index.md'), {
118
+ allowEmpty: true,
119
+ });
120
+ // Contents only orders surviving inventory. Looking up captured paths avoids
121
+ // probing missing, excluded or outside-root targets with nav's strict resolver.
122
+ const inventory = new Map();
123
+ const recordPaths = (entry, direct) => {
124
+ inventory.set(entry.path, direct);
125
+ for (const child of entry.children ?? [])
126
+ recordPaths(child, direct);
127
+ };
128
+ for (const entry of entries)
129
+ recordPaths(entry, entry);
130
+ const ordered = [];
131
+ const add = (entry) => {
132
+ if (entry && !ordered.includes(entry))
133
+ ordered.push(entry);
134
+ };
135
+ add(entries.find((entry) => entry.path === 'index.md'));
136
+ for (const entry of contents) {
137
+ const href = entry.href.split('#', 1)[0]?.trim() ?? '';
138
+ if (!href || /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith('//'))
139
+ continue;
140
+ const local = relative(docsDir, resolve(docsDir, href)).replaceAll('\\', '/');
141
+ if (local === '..' || local.startsWith('../'))
142
+ continue;
143
+ add(inventory.get(local));
144
+ }
145
+ for (const entry of fallback) {
146
+ if (!ordered.includes(entry))
147
+ ordered.push({ ...entry, unlisted: true });
148
+ }
149
+ return ordered;
256
150
  }
257
151
  export async function generateIndex(docsDir, options = {}) {
258
152
  return collectEntries(docsDir, '', createExclusionMatcher(options.excludes ?? []));
@@ -262,12 +156,12 @@ function renderEntries(entries, indent) {
262
156
  const prefix = ' '.repeat(indent);
263
157
  for (const entry of entries) {
264
158
  if (entry.children) {
265
- lines.push(`${prefix}- ${entry.title}`);
159
+ lines.push(`${prefix}- ${entry.title}${entry.unlisted ? ' [unlisted in Contents]' : ''}`);
266
160
  lines.push(...renderEntries(entry.children, indent + 1));
267
161
  }
268
162
  else {
269
163
  const desc = entry.description ? ` — ${entry.description}` : '';
270
- lines.push(`${prefix}- [${entry.title}](${entry.path})${desc}`);
164
+ lines.push(`${prefix}- [${entry.title}](${entry.path})${desc}${entry.unlisted ? ' [unlisted in Contents]' : ''}`);
271
165
  }
272
166
  }
273
167
  return lines;
@@ -1,7 +1,7 @@
1
1
  import { type CommandContext, type GlobalOptions } from '../../../app/command-context.js';
2
2
  import { type OatConfig } from '../../../config/oat-config.js';
3
3
  import { Command } from 'commander';
4
- export declare const GENERATED_INDEX_WARNING = "<!-- AUTOGENERATED by `oat docs generate-index`. Do not hand-edit; changes are clobbered on every `predev` / `prebuild`. -->";
4
+ export declare const GENERATED_INDEX_WARNING = "<!-- AUTOGENERATED by `oat docs generate-index`. Do not hand-edit; run `oat docs generate-index` to regenerate. -->";
5
5
  interface IndexGenerateFileDependencies {
6
6
  generateIndex: (docsDir: string, options: import('./generator.js').GenerateIndexOptions) => Promise<import('./generator.js').IndexEntry[]>;
7
7
  renderIndex: (entries: import('./generator.js').IndexEntry[]) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/index-generate/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAI5C,eAAO,MAAM,uBAAuB,iIAC4F,CAAC;AAuBjI,UAAU,6BAA6B;IACrC,aAAa,EAAE,CACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,aAAa,EAAE,oBAAoB,KAChD,OAAO,CAAC,OAAO,aAAa,EAAE,UAAU,EAAE,CAAC,CAAC;IACjD,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,aAAa,EAAE,UAAU,EAAE,KAAK,MAAM,CAAC;IACrE,SAAS,EAAE,CACT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,cAAc,KACrB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5D,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC7D;AAED,UAAU,yBAAyB;IACjC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,QAAQ,EAAE,6BAA6B,CAAC;CACzC;AAspBD,wBAAgB,8BAA8B,CAC5C,SAAS,GAAE,OAAO,CAAC,yBAAyB,CAAM,GACjD,OAAO,CAgCT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/index-generate/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAI5C,eAAO,MAAM,uBAAuB,wHACmF,CAAC;AA2BxH,UAAU,6BAA6B;IACrC,aAAa,EAAE,CACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,aAAa,EAAE,oBAAoB,KAChD,OAAO,CAAC,OAAO,aAAa,EAAE,UAAU,EAAE,CAAC,CAAC;IACjD,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,aAAa,EAAE,UAAU,EAAE,KAAK,MAAM,CAAC;IACrE,SAAS,EAAE,CACT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,cAAc,KACrB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5D,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC7D;AAED,UAAU,yBAAyB;IACjC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,QAAQ,EAAE,6BAA6B,CAAC;CACzC;AAmrBD,wBAAgB,8BAA8B,CAC5C,SAAS,GAAE,OAAO,CAAC,yBAAyB,CAAM,GACjD,OAAO,CAgCT"}
@@ -8,7 +8,9 @@ import { dirExists } from '../../../fs/io.js';
8
8
  import { normalizeToPosixPath, resolveProjectRoot } from '../../../fs/paths.js';
9
9
  import { Command, Option } from 'commander';
10
10
  import { generateIndex, renderIndex } from './generator.js';
11
- export const GENERATED_INDEX_WARNING = '<!-- AUTOGENERATED by `oat docs generate-index`. Do not hand-edit; changes are clobbered on every `predev` / `prebuild`. -->';
11
+ export const GENERATED_INDEX_WARNING = '<!-- AUTOGENERATED by `oat docs generate-index`. Do not hand-edit; run `oat docs generate-index` to regenerate. -->';
12
+ // Released before the tooling-aware regeneration instructions were introduced.
13
+ const LEGACY_GENERATED_INDEX_WARNING = '<!-- AUTOGENERATED by `oat docs generate-index`. Do not hand-edit; changes are clobbered on every `predev` / `prebuild`. -->';
12
14
  const YAML_EXTENSIONS = ['.yml', '.yaml'];
13
15
  /**
14
16
  * Exit codes, per the `packages/cli/AGENTS.md` taxonomy.
@@ -59,11 +61,19 @@ const DEFAULT_DEPENDENCIES = {
59
61
  buildCommandContext,
60
62
  fileDeps: DEFAULT_FILE_DEPS,
61
63
  };
62
- function buildGeneratedIndexOutput(content) {
64
+ function buildGeneratedIndexOutput(content, tooling) {
65
+ const regeneration = tooling === 'markdown'
66
+ ? 'Markdown has no automatic manifest hooks; regenerate explicitly after source changes.'
67
+ : tooling === 'fumadocs'
68
+ ? 'Fresh Fumadocs apps regenerate this manifest in predev/prebuild.'
69
+ : tooling === 'mkdocs'
70
+ ? 'MkDocs manifests are optional; regenerate explicitly or configure a build hook.'
71
+ : 'Regenerate after source changes, or configure a dev/build hook.';
72
+ const header = `${GENERATED_INDEX_WARNING}\n<!-- ${regeneration} -->`;
63
73
  if (!content) {
64
- return GENERATED_INDEX_WARNING;
74
+ return header;
65
75
  }
66
- return `${GENERATED_INDEX_WARNING}\n\n${content}`;
76
+ return `${header}\n\n${content}`;
67
77
  }
68
78
  /**
69
79
  * True when the relative path escapes its base. A bare `startsWith('..')` test
@@ -171,10 +181,11 @@ function collectExclude(value, previous) {
171
181
  * repository deliberately excluded. Entries are trimmed, blanks are dropped,
172
182
  * and duplicates collapse while preserving first-seen order.
173
183
  */
174
- function resolveExcludes(config, flagValues) {
184
+ function resolveExcludes(config, flagValues, nonReaderPaths = []) {
175
185
  const merged = [];
176
186
  for (const value of [
177
187
  ...(config.documentation?.excludes ?? []),
188
+ ...nonReaderPaths,
178
189
  ...(flagValues ?? []),
179
190
  ]) {
180
191
  const entry = value.trim();
@@ -252,7 +263,13 @@ async function resolveIndexGeneratePaths(context, options, deps) {
252
263
  docsDirSource,
253
264
  outputPath,
254
265
  outputIsExplicit,
255
- excludes: resolveExcludes(config, options.exclude),
266
+ excludes: resolveExcludes(config, options.exclude, configuredRoot &&
267
+ docsDir ===
268
+ (!isMarkdown && (await deps.dirExists(join(configuredRoot, 'docs')))
269
+ ? join(configuredRoot, 'docs')
270
+ : configuredRoot)
271
+ ? config.documentation?.nonReaderPaths
272
+ : []),
256
273
  };
257
274
  }
258
275
  /** `canonicalize`, but an unresolvable path yields null instead of throwing. */
@@ -359,7 +376,8 @@ async function assertOutputIsSafe(resolved, canonical, deps) {
359
376
  return;
360
377
  }
361
378
  const existing = await deps.readFileIfPresent(outputPath);
362
- if (existing !== null && !existing.includes(GENERATED_INDEX_WARNING)) {
379
+ if (existing !== null &&
380
+ ![GENERATED_INDEX_WARNING, LEGACY_GENERATED_INDEX_WARNING].some((marker) => existing.includes(marker))) {
363
381
  throw new CliError(`Refusing to overwrite ${outputPath}: the file exists and is not a generated index ` +
364
382
  '(it has no `oat docs generate-index` AUTOGENERATED header). ' +
365
383
  'Move or delete it, or pass --output to name it explicitly.', REFUSAL_EXIT_CODE);
@@ -412,7 +430,7 @@ async function runIndexGenerate(context, options, deps) {
412
430
  const entries = await deps.generateIndex(docsDir, {
413
431
  excludes: resolved.excludes,
414
432
  });
415
- const content = buildGeneratedIndexOutput(deps.renderIndex(entries));
433
+ const content = buildGeneratedIndexOutput(deps.renderIndex(entries), resolved.config.documentation?.tooling);
416
434
  await deps.writeFile(outputPath, content, 'utf8');
417
435
  if (isFumadocsManifestTransition(resolved, canonical)) {
418
436
  const indexPath = buildDocumentationIndexValue(resolved, canonical);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,mBAAmB,EAGxB,sBAAsB,EAEvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,YAAY,EAElB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAU5C,OAAO,EAIL,KAAK,uBAAuB,EAK7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,gBAAgB,CAAC;AAgBxB,UAAU,uBAAuB;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/C,YAAY,CAAC,EACT,SAAS,GACT,SAAS,GACT,WAAW,GACX,QAAQ,GACR,eAAe,CAAC;IACpB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D;AAED,UAAU,oBAAoB;IAC5B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,gBAAgB,CAAC,CAAC;IAC9E,gBAAgB,EAAE,CAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5B,eAAe,EAAE,CAAC,CAAC,SAAS,MAAM,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EAC1B,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,WAAW,EAAE,CACX,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,uBAAuB,EAChC,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;IAC7C,qBAAqB,EAAE,CACrB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1E;AAuLD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAoC7E;AA0QD,wBAAgB,qBAAqB,CACnC,SAAS,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAC5C,OAAO,CAiET"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,mBAAmB,EAGxB,sBAAsB,EAEvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,YAAY,EAElB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAU5C,OAAO,EAIL,KAAK,uBAAuB,EAK7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,gBAAgB,CAAC;AAgBxB,UAAU,uBAAuB;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,sBAAsB,CAAC;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/C,YAAY,CAAC,EACT,SAAS,GACT,SAAS,GACT,WAAW,GACX,QAAQ,GACR,eAAe,CAAC;IACpB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D;AAED,UAAU,oBAAoB;IAC5B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,gBAAgB,CAAC,CAAC;IAC9E,gBAAgB,EAAE,CAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5B,eAAe,EAAE,CAAC,CAAC,SAAS,MAAM,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EAC1B,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,WAAW,EAAE,CACX,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,uBAAuB,EAChC,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;IAC7C,qBAAqB,EAAE,CACrB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1E;AA2MD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAoC7E;AA0QD,wBAAgB,qBAAqB,CACnC,SAAS,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAC5C,OAAO,CAiET"}
@@ -1,10 +1,13 @@
1
+ import { readFile } from 'node:fs/promises';
1
2
  import { join } from 'node:path';
2
3
  import { buildCommandContext, } from '../../../app/command-context.js';
4
+ import { syncDocsNavigation } from '../../docs/nav/sync.js';
3
5
  import { formatAgentsMdGuidanceResult, formatAgentsMdMutationFailure, previewAgentsMdSection, upsertAgentsMdSection, } from '../../shared/agents-md.js';
4
6
  import { confirmAction, inputWithDefault, selectWithAbort, } from '../../shared/shared.prompts.js';
5
7
  import { readGlobalOptions } from '../../shared/shared.utils.js';
6
8
  import { readOatConfig, writeOatConfig, } from '../../../config/oat-config.js';
7
9
  import { resolveAssetsRoot } from '../../../fs/assets.js';
10
+ import { atomicWriteJson, fileExists } from '../../../fs/io.js';
8
11
  import { Command, Option } from 'commander';
9
12
  import { buildDocsCommands } from './docs-commands.js';
10
13
  import { applyMarkdownDocsPlan, MarkdownDocsWriteError, planMarkdownDocs, validateMarkdownConfig, validateMarkdownTarget, } from './markdown.js';
@@ -146,7 +149,24 @@ const DEFAULT_DEPENDENCIES = {
146
149
  ...config.documentation,
147
150
  ...result.documentationConfig,
148
151
  };
149
- await writeOatConfig(context.cwd, config);
152
+ // Fresh app creation replaces only the seeded documentation keys. Keep
153
+ // unknown repository and documentation siblings for other consumers.
154
+ const configPath = join(context.cwd, '.oat/config.json');
155
+ const raw = (await fileExists(configPath))
156
+ ? JSON.parse(await readFile(configPath, 'utf8'))
157
+ : config;
158
+ await atomicWriteJson(configPath, {
159
+ ...raw,
160
+ documentation: {
161
+ ...raw.documentation,
162
+ ...result.documentationConfig,
163
+ },
164
+ });
165
+ await syncDocsNavigation({
166
+ appRoot: result.appRoot,
167
+ configuredTooling: options.framework,
168
+ nonReaderPaths: config.documentation.nonReaderPaths,
169
+ });
150
170
  if (!context.json) {
151
171
  context.logger.info(`Scaffolded docs app at ${options.targetDir}`);
152
172
  context.logger.info(` Framework: ${options.framework}`);
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/scaffold.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAMjE,OAAO,KAAK,EAEV,aAAa,EACb,uBAAuB,EAExB,MAAM,mBAAmB,CAAC;AAsF3B,MAAM,WAAW,sBAAuB,SAAQ,uBAAuB;IACrE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mBAAmB,EAAE,sBAAsB,CAAC;CAC7C;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,WAAW,2BAA2B;IAC1C,iBAAiB,EAAE,MAAM,YAAY,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACjE,0BAA0B,EAAE,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,KACZ,YAAY,CAAC,OAAO,CAAC,CAAC;CAC5B;AAUD,eAAO,MAAM,aAAa,YAAY,CAAC;AAEvC,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOxE;AAgDD,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC,CAaxB;AA2MD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,MAAM,GAChB,sBAAsB,CAsBxB;AA6CD,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,EAC/B,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAAC,qBAAqB,CAAC,CAwDhC"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/init/scaffold.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAMjE,OAAO,KAAK,EAEV,aAAa,EACb,uBAAuB,EAExB,MAAM,mBAAmB,CAAC;AAsF3B,MAAM,WAAW,sBAAuB,SAAQ,uBAAuB;IACrE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mBAAmB,EAAE,sBAAsB,CAAC;CAC7C;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,WAAW,2BAA2B;IAC1C,iBAAiB,EAAE,MAAM,YAAY,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACjE,0BAA0B,EAAE,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,KACZ,YAAY,CAAC,OAAO,CAAC,CAAC;CAC5B;AAUD,eAAO,MAAM,aAAa,YAAY,CAAC;AAEvC,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOxE;AAgDD,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC,CAaxB;AAmND;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,MAAM,GAChB,sBAAsB,CAwBxB;AA6CD,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,EAC/B,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAAC,qBAAqB,CAAC,CAwDhC"}
@@ -135,16 +135,6 @@ export async function resolveOatDepContext(repoRoot, assetsRoot) {
135
135
  };
136
136
  return { isOatRepo, localPackages, oatPackageVersions };
137
137
  }
138
- function buildDevDependencies(lint, format) {
139
- const entries = [];
140
- if (lint === 'markdownlint-cli2') {
141
- entries.push(' "markdownlint-cli2": "^0.13.0"');
142
- }
143
- if (format === 'oxfmt') {
144
- entries.push(' "oxfmt": "^0.36.0"');
145
- }
146
- return entries.join(',\n');
147
- }
148
138
  function buildFumaDevDependencies(lint, format) {
149
139
  const entries = [];
150
140
  if (lint === 'markdownlint-cli2') {
@@ -158,9 +148,22 @@ function buildFumaDevDependencies(lint, format) {
158
148
  }
159
149
  return `,\n${entries.join(',\n')}`;
160
150
  }
151
+ function shellQuote(value) {
152
+ return /^[a-zA-Z0-9_./-]+$/.test(value)
153
+ ? value
154
+ : `'${value.replaceAll("'", "'\\''")}'`;
155
+ }
156
+ function jsonStringContent(value) {
157
+ return JSON.stringify(value).slice(1, -1);
158
+ }
159
+ function buildNavSyncCheckCmd(isOatRepo, targetDir) {
160
+ return isOatRepo
161
+ ? `pnpm -w run cli:source -- docs nav sync --target-dir ${shellQuote(targetDir)} --check`
162
+ : 'oat docs nav sync --target-dir . --check';
163
+ }
161
164
  function buildGenerateIndexCmd(isOatRepo, targetDir) {
162
165
  if (isOatRepo) {
163
- return `pnpm -w run cli:source -- docs generate-index --docs-dir ${targetDir}/docs --output ${targetDir}/index.md`;
166
+ return `pnpm -w run cli:source -- docs generate-index --docs-dir ${shellQuote(`${targetDir}/docs`)} --output ${shellQuote(`${targetDir}/index.md`)}`;
164
167
  }
165
168
  return 'oat docs generate-index --docs-dir docs --output index.md';
166
169
  }
@@ -231,6 +234,7 @@ function renderTemplate(template, options, depContext, packageManagerField, node
231
234
  ' // {{TURBOPACK_ROOT_OPTION}}\n': options.repoShape === 'nested-standalone'
232
235
  ? ' turbopack: { root: dirname(fileURLToPath(import.meta.url)) },\n'
233
236
  : '',
237
+ '{{OAT_CONFIG_RELATIVE_PATH}}': `./${relative(resolve(options.repoRoot, options.targetDir), join(options.repoRoot, '.oat/config.json')).replaceAll('\\', '/')}`,
234
238
  '{{APP_NAME}}': options.appName,
235
239
  '{{NODE_REQUIREMENT}}': nodeRequirement,
236
240
  '{{PACKAGE_NAME}}': options.appName,
@@ -252,11 +256,12 @@ function renderTemplate(template, options, depContext, packageManagerField, node
252
256
  '{{DOCS_FORMAT_CHECK_SCRIPT}}': options.format === 'oxfmt'
253
257
  ? "oxfmt --check 'docs/**/*.md'"
254
258
  : "echo 'docs format check disabled'",
255
- '{{DEV_DEPENDENCIES}}': buildDevDependencies(options.lint, options.format),
259
+ '{{DEV_DEPENDENCIES}}': buildFumaDevDependencies(options.lint, options.format),
256
260
  '{{FUMA_DEV_DEPENDENCIES}}': buildFumaDevDependencies(options.lint, options.format),
257
261
  '{{REPO_NAME}}': repoName,
258
262
  '{{APP_DIR}}': options.targetDir,
259
- '{{GENERATE_INDEX_CMD}}': buildGenerateIndexCmd(depContext.isOatRepo, options.targetDir),
263
+ '{{GENERATE_INDEX_CMD}}': jsonStringContent(buildGenerateIndexCmd(depContext.isOatRepo, options.targetDir)),
264
+ '{{NAV_SYNC_CHECK_CMD}}': jsonStringContent(buildNavSyncCheckCmd(depContext.isOatRepo, options.targetDir)),
260
265
  '{{OAT_DOCS_CONFIG_DEP}}': oatDepVersion(depContext, 'docs-config'),
261
266
  '{{OAT_DOCS_THEME_DEP}}': oatDepVersion(depContext, 'docs-theme'),
262
267
  '{{OAT_DOCS_TRANSFORMS_DEP}}': oatDepVersion(depContext, 'docs-transforms'),
@@ -285,12 +290,14 @@ export function buildDocumentationConfig(framework, targetDir) {
285
290
  return {
286
291
  root: targetDir,
287
292
  tooling: 'fumadocs',
293
+ navOwner: 'nav-sync',
288
294
  index: join(targetDir, 'index.md'),
289
295
  };
290
296
  }
291
297
  return {
292
298
  root: targetDir,
293
299
  tooling: 'mkdocs',
300
+ navOwner: 'nav-sync',
294
301
  config: join(targetDir, 'mkdocs.yml'),
295
302
  index: join(targetDir, 'mkdocs.yml'),
296
303
  };
@@ -1,21 +1,31 @@
1
+ import { type ExclusionMatcher } from '../../docs/shared/exclusions.js';
1
2
  export interface DocsContentsEntry {
2
3
  title: string;
3
4
  href: string;
5
+ group?: {
6
+ title: string;
7
+ line: number;
8
+ };
4
9
  }
5
- export declare function parseIndexContents(markdown: string, sourcePath?: string): DocsContentsEntry[];
10
+ /** Shared discovery lets inventory generation retain its no-map fallback. */
11
+ export declare function hasIndexContents(markdown: string): boolean;
12
+ export declare function parseIndexContents(markdown: string, sourcePath?: string, options?: {
13
+ allowEmpty?: boolean;
14
+ }): DocsContentsEntry[];
6
15
  export type DocsNavTree = Array<Record<string, DocsNavTree | string> | string>;
7
16
  interface BuildDocsNavTreeOptions {
8
17
  docsRoot: string;
9
18
  dirRelativePath?: string;
10
19
  visitedDirectories?: Set<string>;
20
+ nonReaderPaths?: readonly string[];
11
21
  }
12
22
  export declare function resolveEntryTarget(docsRoot: string, directoryPath: string, dirRelativePath: string, entry: DocsContentsEntry,
13
23
  /**
14
24
  * Page extensions a Contents link may target. MkDocs renders only `.md`;
15
25
  * Fumadocs also renders `.mdx` pages.
16
26
  */
17
- pageExtensions?: readonly string[]): Promise<{
18
- kind: 'page' | 'section';
27
+ pageExtensions?: readonly string[], matcher?: ExclusionMatcher): Promise<{
28
+ kind: 'page' | 'section' | 'excluded';
19
29
  path: string;
20
30
  }>;
21
31
  export declare function buildDocsNavTree(options: BuildDocsNavTreeOptions): Promise<DocsNavTree>;
@@ -1 +1 @@
1
- {"version":3,"file":"contents.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/nav/contents.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,UAAU,SAAa,GACtB,iBAAiB,EAAE,CAqCrB;AAED,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;AAE/E,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAClC;AAMD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,iBAAiB;AACxB;;;GAGG;AACH,cAAc,GAAE,SAAS,MAAM,EAAY,GAC1C,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAmErD;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,WAAW,CAAC,CA8DtB"}
1
+ {"version":3,"file":"contents.d.ts","sourceRoot":"","sources":["../../../../src/commands/docs/nav/contents.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,kCAAkC,CAAC;AAG1C,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC;AA8BD,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,UAAU,SAAa,EACvB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACrC,iBAAiB,EAAE,CAoDrB;AAED,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;AAE/E,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAMD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,iBAAiB;AACxB;;;GAGG;AACH,cAAc,GAAE,SAAS,MAAM,EAAY,EAC3C,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAuElE;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,WAAW,CAAC,CA0EtB"}