@karaoke-cms/module-docs 0.15.1 → 0.16.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 (2) hide show
  1. package/package.json +4 -4
  2. package/src/index.ts +80 -31
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@karaoke-cms/module-docs",
3
3
  "type": "module",
4
- "version": "0.15.1",
4
+ "version": "0.16.0",
5
5
  "description": "Docs module for karaoke-cms — documentation pages with sidebar navigation",
6
6
  "main": "./src/index.ts",
7
7
  "exports": {
@@ -23,13 +23,13 @@
23
23
  ],
24
24
  "peerDependencies": {
25
25
  "astro": ">=6.0.0",
26
- "@karaoke-cms/contracts": "^0.15.1"
26
+ "@karaoke-cms/contracts": "^0.16.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "astro": "^6.0.8",
30
30
  "vitest": "^4.1.1",
31
- "@karaoke-cms/astro": "0.15.1",
32
- "@karaoke-cms/contracts": "0.15.1"
31
+ "@karaoke-cms/astro": "0.16.0",
32
+ "@karaoke-cms/contracts": "0.16.0"
33
33
  },
34
34
  "scripts": {
35
35
  "test": "vitest run test/docs-factory.test.js"
package/src/index.ts CHANGED
@@ -1,7 +1,8 @@
1
- import type { ModuleInstance } from '@karaoke-cms/contracts';
1
+ import type { DocsSection, ModuleInstance } from '@karaoke-cms/contracts';
2
2
  import { cssContract } from './css-contract.js';
3
3
 
4
4
  export { cssContract } from './css-contract.js';
5
+ export type { DocsSection } from '@karaoke-cms/contracts';
5
6
  // docsSchema is exported from '@karaoke-cms/module-docs/schema' to avoid
6
7
  // pulling zod into the config-loading context.
7
8
 
@@ -24,43 +25,26 @@ export interface DocsConfig {
24
25
  }
25
26
 
26
27
  /**
27
- * Docs module documentation pages with sidebar navigation.
28
- *
29
- * Returns a ModuleInstance that karaoke() uses to code-generate per-instance
30
- * .astro page files and inject them as routes. Multiple instances may be
31
- * configured to serve separate docs sections from different vault folders.
32
- *
33
- * Publishes three routes per instance:
34
- * - `{mount}` — home page listing all doc titles
35
- * - `{mount}/list` — standalone full docs list
36
- * - `{mount}/[slug]` — individual doc with left-sidebar nav
37
- *
38
- * @example
39
- * // karaoke.config.ts — default section
40
- * import { docs } from '@karaoke-cms/module-docs';
41
- * export default defineConfig({
42
- * theme: themeDefault({ implements: [docs({ mount: '/docs' })] }),
43
- * });
44
- *
45
- * @example
46
- * // karaoke.config.ts — two independent sections
47
- * export default defineConfig({
48
- * theme: themeDefault({ implements: [docs({ mount: '/docs' })] }),
49
- * modules: [docs({ mount: '/api-docs', folder: 'api-reference', label: 'API Reference' })],
50
- * });
28
+ * Shared helper: derive mount, folder, id, and label from config fields.
29
+ * Used by both docsFromSingle and docsFromSection to keep derivation in sync.
51
30
  */
52
- export function docs(config: DocsConfig = {}): ModuleInstance {
53
- const mount = (config.mount ?? '/docs').replace(/\/$/, '');
31
+ function computeDocsMeta(cfg: { mount?: string; folder?: string; id?: string; label?: string }) {
32
+ const mount = (cfg.mount ?? '/docs').replace(/\/$/, '');
54
33
  const rawFolder = mount.replace(/^\//, '');
55
- if (config.folder === undefined && rawFolder === '') {
34
+ if (cfg.folder === undefined && rawFolder === '') {
56
35
  console.warn(
57
36
  '[karaoke-cms] docs({ mount: \'/\' }): folder defaults to "docs". ' +
58
37
  'Pass folder explicitly (e.g. docs({ mount: \'/\', folder: \'docs\' })) to suppress this warning.',
59
38
  );
60
39
  }
61
- const folder = config.folder ?? (rawFolder || 'docs');
62
- const id = config.id ?? (folder.replace(/\//g, '-') || 'docs');
63
- const label = config.label ?? (id.charAt(0).toUpperCase() + id.slice(1).replace(/-/g, ' '));
40
+ const folder = cfg.folder ?? (rawFolder || 'docs');
41
+ const id = cfg.id ?? (folder.replace(/\//g, '-') || 'docs');
42
+ const label = cfg.label ?? id.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
43
+ return { mount, folder, id, label };
44
+ }
45
+
46
+ function docsFromSingle(config: DocsConfig = {}): ModuleInstance {
47
+ const { mount, folder, id, label } = computeDocsMeta(config);
64
48
  return {
65
49
  _type: 'module-instance',
66
50
  id,
@@ -82,3 +66,68 @@ export function docs(config: DocsConfig = {}): ModuleInstance {
82
66
  scaffoldPages: undefined,
83
67
  };
84
68
  }
69
+
70
+ function docsFromSection(s: DocsSection): ModuleInstance {
71
+ const { mount, folder, id, label } = computeDocsMeta(s);
72
+ return {
73
+ _type: 'module-instance',
74
+ id,
75
+ mount,
76
+ enabled: true,
77
+ collection: {
78
+ name: id,
79
+ folder,
80
+ label,
81
+ layout: s.layout ?? 'default',
82
+ sidebarStyle: s.sidebarStyle ?? 'tree',
83
+ },
84
+ // routes is empty — karaoke() generates per-instance pages via codegen
85
+ routes: [],
86
+ menuEntries: [{
87
+ id,
88
+ name: label,
89
+ path: mount,
90
+ section: 'main',
91
+ weight: s.weight ?? 20,
92
+ ...(s.parent !== undefined ? { parent: s.parent } : {}),
93
+ }],
94
+ cssContract,
95
+ hasDefaultCss: false,
96
+ defaultCssPath: undefined,
97
+ scaffoldPages: undefined,
98
+ };
99
+ }
100
+
101
+ /**
102
+ * Docs module — documentation pages with sidebar navigation.
103
+ *
104
+ * Single-form: returns one ModuleInstance.
105
+ * Array-form: accepts DocsSection[] and returns ModuleInstance[] (one per active section).
106
+ * Sections with `enabled: false` are excluded from the returned array.
107
+ *
108
+ * Publishes three routes per instance:
109
+ * - `{mount}` — home page listing all doc titles
110
+ * - `{mount}/list` — standalone full docs list
111
+ * - `{mount}/[slug]` — individual doc with left-sidebar nav
112
+ *
113
+ * @example
114
+ * // karaoke.config.ts — single section
115
+ * modules: [docs({ mount: '/docs' })]
116
+ *
117
+ * @example
118
+ * // karaoke.config.ts — multiple sections with menu ordering
119
+ * modules: [
120
+ * docs([
121
+ * { id: 'docs', mount: '/docs', label: 'Docs', weight: 20 },
122
+ * { id: 'api-docs', mount: '/api-docs', folder: 'api-reference', label: 'API Reference', weight: 25, parent: 'docs' },
123
+ * ]),
124
+ * ]
125
+ */
126
+ export function docs(config: DocsSection[]): ModuleInstance[];
127
+ export function docs(config?: DocsConfig): ModuleInstance;
128
+ export function docs(config?: DocsConfig | DocsSection[]): ModuleInstance | ModuleInstance[] {
129
+ if (Array.isArray(config)) {
130
+ return config.filter(s => s.enabled !== false).map(s => docsFromSection(s));
131
+ }
132
+ return docsFromSingle(config);
133
+ }