vitepress-api-references 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@ Enable JSDoc API Reference for VitePress.
8
8
 
9
9
  ### VitePress integration
10
10
 
11
- This repository uses the VitePress integration to generate and serve its own API reference docs. See [`docs/.vitepress/config.ts`](./docs/.vitepress/config.ts) and the generated [`docs/api`](./docs/api) directory for a working self-hosted example.
11
+ This repository uses the VitePress integration to generate and serve its own API reference docs. The generated API reference site is published at <https://kazupon.github.io/vitepress-api-references/>. See [`docs/.vitepress/config.ts`](./docs/.vitepress/config.ts) and the generated [`docs/api`](./docs/api) directory for a working self-hosted example.
12
12
 
13
13
  ```ts
14
14
  import { defineConfig } from 'vitepress'
@@ -20,16 +20,18 @@ export default defineConfig(
20
20
  sidebar: [{ text: 'Guide', link: '/' }, { text: 'API References' }]
21
21
  },
22
22
  apiDocs: {
23
- entryPoints: [{ path: 'src/index.ts', name: 'default' }],
23
+ entryPoints: [{ path: 'src/index.ts' }],
24
24
  outDir: 'docs/api',
25
25
  basePath: '/api',
26
26
  markdown: {
27
27
  pathStrategy: 'typedoc',
28
+ singleEntryRoot: 'flatten',
28
29
  renderStyle: 'markdown',
29
30
  indexFormat: 'table'
30
31
  },
31
32
  nav: {
32
- section: { text: 'API References', collapsed: false },
33
+ section: { text: 'API References' },
34
+ collapsed: true,
33
35
  insert: 'replace',
34
36
  replaceText: 'API References'
35
37
  }
@@ -46,7 +48,7 @@ Use `generateOxContentApiDocs` when you want to generate markdown files directly
46
48
  import { generateOxContentApiDocs } from 'vitepress-api-references'
47
49
 
48
50
  const result = await generateOxContentApiDocs({
49
- entryPoints: [{ path: 'src/index.ts', name: 'default' }],
51
+ entryPoints: [{ path: 'src/index.ts', name: 'main' }],
50
52
  outDir: 'standalone',
51
53
  basePath: '/standalone',
52
54
  markdown: {
package/dist/index.d.mts CHANGED
@@ -21,6 +21,7 @@ interface VitePressSidebarSectionOptions {
21
21
  text: string;
22
22
  /**
23
23
  * Whether the generated top-level sidebar section starts collapsed in VitePress.
24
+ * When omitted, a boolean `nav.collapsed` value is used.
24
25
  *
25
26
  * @default undefined
26
27
  */
@@ -100,6 +101,7 @@ interface VitePressNavOptions {
100
101
  sidebarRoute?: string;
101
102
  /**
102
103
  * Collapsed state for generated sidebar branches, or a resolver called per item.
104
+ * A boolean value also controls the top-level section when `section.collapsed` is omitted.
103
105
  *
104
106
  * @default undefined
105
107
  */
@@ -294,13 +296,21 @@ declare module 'vitepress' {
294
296
  * import { defineConfig } from 'vitepress'
295
297
  * import { withOxContentApiDocs } from 'vitepress-api-references'
296
298
  *
297
- * export default await withOxContentApiDocs(
298
- * defineConfig({
299
+ * export default defineConfig(
300
+ * await withOxContentApiDocs({
299
301
  * title: 'My Library',
302
+ * themeConfig: {
303
+ * sidebar: [{ text: 'Guide', link: '/' }, { text: 'API Reference' }]
304
+ * },
300
305
  * apiDocs: {
301
- * entryPoints: ['src/index.ts'],
302
- * outDir: 'api',
303
- * basePath: '/api'
306
+ * entryPoints: [{ path: 'src/index.ts', name: 'default' }],
307
+ * outDir: 'docs/api',
308
+ * basePath: '/api',
309
+ * nav: {
310
+ * section: { text: 'API Reference', collapsed: false },
311
+ * insert: 'replace',
312
+ * replaceText: 'API Reference'
313
+ * }
304
314
  * }
305
315
  * })
306
316
  * )
package/dist/index.mjs CHANGED
@@ -240,6 +240,7 @@ async function generateOxContentApiDocs(options) {
240
240
  const nav = generateDocsNavMetadataFromDocs(docs, {
241
241
  basePath: resolvedOptions.basePath,
242
242
  pathStrategy: resolvedOptions.markdown?.pathStrategy,
243
+ singleEntryRoot: resolvedOptions.markdown?.singleEntryRoot,
243
244
  groupOrder: resolvedOptions.markdown?.groupOrder,
244
245
  sort: resolvedOptions.markdown?.sort,
245
246
  sortEntryPoints: resolvedOptions.markdown?.sortEntryPoints,
@@ -327,7 +328,7 @@ function createVitePressSidebarSection(nav, options = {}) {
327
328
  if (!section) return { items };
328
329
  return {
329
330
  text: section.text,
330
- collapsed: section.collapsed,
331
+ collapsed: resolveSectionCollapsed(options),
331
332
  items
332
333
  };
333
334
  }
@@ -369,36 +370,44 @@ function mergeVitePressSidebar(sidebar, generated, options = {}) {
369
370
  function toSidebarItem(item, options, depth) {
370
371
  const children = item.children?.map((child) => toSidebarItem(child, options, depth + 1));
371
372
  const sidebarItem = { text: item.title };
372
- const collapsed = resolveCollapsed(item, options, depth);
373
- if (collapsed !== void 0) sidebarItem.collapsed = collapsed;
374
373
  if (children?.length) {
374
+ const collapsed = resolveCollapsed(item, options, depth);
375
+ if (collapsed !== void 0) sidebarItem.collapsed = collapsed;
375
376
  sidebarItem.items = children;
376
377
  if (depth === 0 && item.path) sidebarItem.link = item.path;
377
378
  } else if (item.path) sidebarItem.link = item.path;
378
379
  return sidebarItem;
379
380
  }
380
381
  function replaceSidebarItem(items, generated, replaceText) {
382
+ const result = replaceSidebarItemRecursive(items, generated, replaceText);
383
+ return result.replaced ? result.items : [...items, generated];
384
+ }
385
+ function replaceSidebarItemRecursive(items, generated, replaceText) {
381
386
  let replaced = false;
382
- const next = items.map((item) => {
383
- if (isSidebarItem(item)) {
387
+ return {
388
+ items: items.map((item) => {
389
+ if (!isSidebarItem(item)) return item;
384
390
  if (replaceText && item.text === replaceText) {
385
391
  replaced = true;
386
392
  return generated;
387
393
  }
388
- if (replaceText && item.items) {
389
- const nested = replaceSidebarItem(item.items, generated, replaceText);
390
- if (nested !== item.items) {
394
+ if (replaceText && Array.isArray(item.items)) {
395
+ const nested = replaceSidebarItemRecursive(item.items, generated, replaceText);
396
+ if (nested.replaced) {
391
397
  replaced = true;
392
398
  return {
393
399
  ...item,
394
- items: nested
400
+ items: nested.items
395
401
  };
396
402
  }
397
403
  }
398
- }
399
- return item;
400
- });
401
- return replaced ? next : [...items, generated];
404
+ return item;
405
+ }),
406
+ replaced
407
+ };
408
+ }
409
+ function resolveSectionCollapsed(options) {
410
+ return options.section?.collapsed ?? (typeof options.collapsed === "boolean" ? options.collapsed : void 0);
402
411
  }
403
412
  function resolveCollapsed(item, options, depth) {
404
413
  if (typeof options.collapsed === "function") return options.collapsed(item, depth);
@@ -485,13 +494,21 @@ function getWatchedFiles(options) {
485
494
  * import { defineConfig } from 'vitepress'
486
495
  * import { withOxContentApiDocs } from 'vitepress-api-references'
487
496
  *
488
- * export default await withOxContentApiDocs(
489
- * defineConfig({
497
+ * export default defineConfig(
498
+ * await withOxContentApiDocs({
490
499
  * title: 'My Library',
500
+ * themeConfig: {
501
+ * sidebar: [{ text: 'Guide', link: '/' }, { text: 'API Reference' }]
502
+ * },
491
503
  * apiDocs: {
492
- * entryPoints: ['src/index.ts'],
493
- * outDir: 'api',
494
- * basePath: '/api'
504
+ * entryPoints: [{ path: 'src/index.ts', name: 'default' }],
505
+ * outDir: 'docs/api',
506
+ * basePath: '/api',
507
+ * nav: {
508
+ * section: { text: 'API Reference', collapsed: false },
509
+ * insert: 'replace',
510
+ * replaceText: 'API Reference'
511
+ * }
495
512
  * }
496
513
  * })
497
514
  * )
@@ -508,7 +525,7 @@ async function withOxContentApiDocs(config, override) {
508
525
  const apiDocsOptions = override ? baseOptions ? mergeApiDocsOptions(baseOptions, override) : override : baseOptions;
509
526
  if (!apiDocsOptions) return config;
510
527
  const result = await generateOxContentApiDocs(apiDocsOptions);
511
- const sidebarSection = createVitePressSidebarSection(result.nav, result.resolvedOptions.nav);
528
+ const sidebarSection = removeMissingBranchLinks(createVitePressSidebarSection(result.nav, result.resolvedOptions.nav), createGeneratedRoutePathSet(result.files, result.resolvedOptions.basePath));
512
529
  config.themeConfig ??= {};
513
530
  config.themeConfig.sidebar = mergeVitePressSidebar(config.themeConfig.sidebar, sidebarSection, result.resolvedOptions.nav);
514
531
  config.vite ??= {};
@@ -518,6 +535,28 @@ async function withOxContentApiDocs(config, override) {
518
535
  })];
519
536
  return config;
520
537
  }
538
+ function createGeneratedRoutePathSet(files, basePath) {
539
+ const routes = /* @__PURE__ */ new Set();
540
+ for (const filePath of Object.keys(files)) {
541
+ if (!filePath.endsWith(".md")) continue;
542
+ const routePath = filePath.slice(0, -3);
543
+ if (routePath === "index") routes.add(normalizeRoutePath(basePath));
544
+ else if (routePath.endsWith("/index")) routes.add(normalizeRoutePath(`${basePath}/${routePath.slice(0, -6)}`));
545
+ else routes.add(normalizeRoutePath(`${basePath}/${routePath}`));
546
+ }
547
+ return routes;
548
+ }
549
+ function removeMissingBranchLinks(item, routes) {
550
+ const next = { ...item };
551
+ if (item.items) next.items = item.items.map((child) => removeMissingBranchLinks(child, routes));
552
+ if (next.items?.length && next.link && !routes.has(normalizeRoutePath(next.link))) delete next.link;
553
+ return next;
554
+ }
555
+ function normalizeRoutePath(routePath) {
556
+ const withoutMarkdown = routePath.endsWith(".md") ? routePath.slice(0, -3) : routePath;
557
+ const normalized = withoutMarkdown.startsWith("/") ? withoutMarkdown : `/${withoutMarkdown}`;
558
+ return normalized.length > 1 ? normalized.replace(/\/+$/, "") : normalized;
559
+ }
521
560
  //#endregion
522
561
  //#region src/index.ts
523
562
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitepress-api-references",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Enable JSDoc API Reference for VitePress",
5
5
  "keywords": [
6
6
  "api-references",
@@ -45,9 +45,10 @@
45
45
  "build": "vp pack",
46
46
  "knip": "knip",
47
47
  "dev": "vp pack --watch",
48
- "docs:build": "vp pack && vp exec vitepress build docs",
49
- "docs:dev": "vp pack && vp exec vitepress dev docs",
50
- "docs:standalone": "vp pack && node standalone/generate.ts",
48
+ "docs:build": "vp exec vitepress build docs",
49
+ "docs:preview": "vp exec vitepress preview docs",
50
+ "docs:dev": "vp exec vitepress dev docs",
51
+ "docs:standalone": "node standalone/generate.ts",
51
52
  "test": "vp test",
52
53
  "test:fixtures": "vp exec vitepress build tests/fixtures/basic/docs",
53
54
  "check": "vp check && knip",
@@ -57,12 +58,12 @@
57
58
  "prepare": "vp config"
58
59
  },
59
60
  "dependencies": {
60
- "@ox-content/napi": "^2.63.0"
61
+ "@ox-content/napi": "^2.66.0"
61
62
  },
62
63
  "devDependencies": {
63
64
  "@kazupon/vp-config": "^0.3.2",
64
65
  "@types/node": "^25.9.1",
65
- "@typescript/native-preview": "7.0.0-dev.20260527.2",
66
+ "@typescript/native-preview": "7.0.0-dev.20260602.1",
66
67
  "bumpp": "^11.1.0",
67
68
  "gh-changelogen": "^0.2.8",
68
69
  "knip": "^6.16.0",