specweave 1.0.263 → 1.0.265
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/CLAUDE.md +25 -25
- package/dist/src/cli/commands/docs.d.ts.map +1 -1
- package/dist/src/cli/commands/docs.js +13 -5
- package/dist/src/cli/commands/docs.js.map +1 -1
- package/dist/src/core/living-docs/content-distributor.js +1 -1
- package/dist/src/core/living-docs/content-distributor.js.map +1 -1
- package/dist/src/core/living-docs/scaffolding/template-engine.js +1 -1
- package/dist/src/core/living-docs/scaffolding/template-engine.js.map +1 -1
- package/dist/src/core/living-docs/sync-helpers/generators.js +1 -1
- package/dist/src/core/living-docs/sync-helpers/generators.js.map +1 -1
- package/dist/src/core/llm/consent.d.ts +33 -0
- package/dist/src/core/llm/consent.d.ts.map +1 -0
- package/dist/src/core/llm/consent.js +94 -0
- package/dist/src/core/llm/consent.js.map +1 -0
- package/dist/src/core/llm/provider-factory.d.ts +2 -0
- package/dist/src/core/llm/provider-factory.d.ts.map +1 -1
- package/dist/src/core/llm/provider-factory.js +12 -0
- package/dist/src/core/llm/provider-factory.js.map +1 -1
- package/dist/src/core/llm/types.d.ts +17 -0
- package/dist/src/core/llm/types.d.ts.map +1 -1
- package/dist/src/core/llm/types.js.map +1 -1
- package/dist/src/core/skills/skill-judge.d.ts.map +1 -1
- package/dist/src/core/skills/skill-judge.js +14 -0
- package/dist/src/core/skills/skill-judge.js.map +1 -1
- package/dist/src/utils/docs-preview/config-generator.d.ts +14 -6
- package/dist/src/utils/docs-preview/config-generator.d.ts.map +1 -1
- package/dist/src/utils/docs-preview/config-generator.js +526 -137
- package/dist/src/utils/docs-preview/config-generator.js.map +1 -1
- package/dist/src/utils/docs-preview/docusaurus-setup.d.ts +1 -1
- package/dist/src/utils/docs-preview/docusaurus-setup.d.ts.map +1 -1
- package/dist/src/utils/docs-preview/docusaurus-setup.js +121 -48
- package/dist/src/utils/docs-preview/docusaurus-setup.js.map +1 -1
- package/dist/src/utils/docs-preview/index.d.ts +3 -2
- package/dist/src/utils/docs-preview/index.d.ts.map +1 -1
- package/dist/src/utils/docs-preview/index.js +3 -2
- package/dist/src/utils/docs-preview/index.js.map +1 -1
- package/dist/src/utils/docs-preview/project-detector.d.ts +16 -0
- package/dist/src/utils/docs-preview/project-detector.d.ts.map +1 -0
- package/dist/src/utils/docs-preview/project-detector.js +234 -0
- package/dist/src/utils/docs-preview/project-detector.js.map +1 -0
- package/dist/src/utils/docs-preview/server-manager.d.ts +4 -0
- package/dist/src/utils/docs-preview/server-manager.d.ts.map +1 -1
- package/dist/src/utils/docs-preview/server-manager.js +102 -7
- package/dist/src/utils/docs-preview/server-manager.js.map +1 -1
- package/dist/src/utils/docs-preview/types.d.ts +28 -0
- package/dist/src/utils/docs-preview/types.d.ts.map +1 -1
- package/package.json +1 -6
- package/plugins/specweave/scripts/progress.js +148 -50
- package/plugins/specweave/scripts/read-progress.sh +128 -52
- package/plugins/specweave/scripts/rebuild-dashboard-cache.sh +23 -17
- package/plugins/specweave/skills/done/SKILL.md +5 -4
- package/plugins/specweave/skills/judge-llm/SKILL.md +18 -0
- package/plugins/specweave/skills/progress/SKILL.md +7 -21
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Docusaurus configuration generator
|
|
3
|
-
* Generates docusaurus.config.js with
|
|
3
|
+
* Generates docusaurus.config.js with professional defaults
|
|
4
4
|
*/
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import * as fs from '../../utils/fs-native.js';
|
|
@@ -8,10 +8,26 @@ import * as fs from '../../utils/fs-native.js';
|
|
|
8
8
|
* Generate docusaurus.config.js content
|
|
9
9
|
*/
|
|
10
10
|
export function generateDocusaurusConfig(config) {
|
|
11
|
-
const { title, tagline, url, baseUrl, docsPath
|
|
11
|
+
const { title, tagline, url, baseUrl, docsPath } = config;
|
|
12
|
+
const projectName = config.projectMetadata?.name || title;
|
|
13
|
+
// Build Docusaurus exclude patterns from excludeFolders
|
|
14
|
+
const excludeFolders = config.excludeFolders || [];
|
|
15
|
+
const excludePatterns = excludeFolders.map(f => `'**/${f.replace(/'/g, "\\'")}/**'`).join(', ');
|
|
16
|
+
// Generate footer links from detected categories (max 4)
|
|
17
|
+
const categories = config.projectMetadata?.categories || [];
|
|
18
|
+
const footerItems = categories.slice(0, 4).map(cat => ` {\n label: '${cat.label}',\n to: '/${cat.id}',\n }`).join(',\n');
|
|
19
|
+
const footerLinksBlock = footerItems
|
|
20
|
+
? `[
|
|
21
|
+
{
|
|
22
|
+
title: 'Documentation',
|
|
23
|
+
items: [
|
|
24
|
+
${footerItems},
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
]`
|
|
28
|
+
: `[]`;
|
|
12
29
|
return `// @ts-check
|
|
13
|
-
//
|
|
14
|
-
// Auto-generated by SpecWeave docs-preview plugin
|
|
30
|
+
// Auto-generated documentation site configuration
|
|
15
31
|
// Generated: ${new Date().toISOString()}
|
|
16
32
|
|
|
17
33
|
import {themes as prismThemes} from 'prism-react-renderer';
|
|
@@ -19,19 +35,14 @@ import {themes as prismThemes} from 'prism-react-renderer';
|
|
|
19
35
|
/** @type {import('@docusaurus/types').Config} */
|
|
20
36
|
const config = {
|
|
21
37
|
title: '${title}',
|
|
22
|
-
tagline: '${tagline}',
|
|
23
|
-
favicon: 'img/favicon.
|
|
38
|
+
tagline: '${escapeQuotes(tagline)}',
|
|
39
|
+
favicon: 'img/favicon.svg',
|
|
24
40
|
|
|
25
41
|
// Production URL
|
|
26
42
|
url: '${url}',
|
|
27
43
|
baseUrl: '${baseUrl}',
|
|
28
44
|
|
|
29
|
-
// GitHub Pages deployment config
|
|
30
|
-
organizationName: 'your-org',
|
|
31
|
-
projectName: 'your-repo',
|
|
32
|
-
|
|
33
45
|
onBrokenLinks: 'warn',
|
|
34
|
-
onBrokenMarkdownLinks: 'warn',
|
|
35
46
|
onBrokenAnchors: 'warn',
|
|
36
47
|
|
|
37
48
|
// Internationalization
|
|
@@ -49,17 +60,14 @@ const config = {
|
|
|
49
60
|
routeBasePath: '/',
|
|
50
61
|
path: '${docsPath}',
|
|
51
62
|
sidebarPath: './sidebars.js',
|
|
52
|
-
editUrl: undefined,
|
|
53
|
-
|
|
54
|
-
// Docusaurus default excludes: ['**/_*.{js,jsx,ts,tsx,md,mdx}', '**/_*/**', '**/__tests__/**']
|
|
55
|
-
// We want ALL folders and files visible, so we set exclude to empty array
|
|
56
|
-
exclude: [],
|
|
63
|
+
editUrl: undefined,
|
|
64
|
+
exclude: [${excludePatterns}],
|
|
57
65
|
remarkPlugins: [],
|
|
58
66
|
rehypePlugins: [],
|
|
59
67
|
beforeDefaultRemarkPlugins: [],
|
|
60
68
|
beforeDefaultRehypePlugins: [],
|
|
61
69
|
},
|
|
62
|
-
blog: false,
|
|
70
|
+
blog: false,
|
|
63
71
|
theme: {
|
|
64
72
|
customCss: './src/css/custom.css',
|
|
65
73
|
},
|
|
@@ -70,43 +78,19 @@ const config = {
|
|
|
70
78
|
themeConfig:
|
|
71
79
|
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
|
72
80
|
({
|
|
73
|
-
// Social card image (optional)
|
|
74
|
-
image: 'img/docusaurus-social-card.jpg',
|
|
75
|
-
|
|
76
81
|
navbar: {
|
|
77
|
-
title: '${
|
|
82
|
+
title: '${projectName} Docs',
|
|
78
83
|
logo: {
|
|
79
|
-
alt: '${
|
|
84
|
+
alt: '${projectName} Logo',
|
|
80
85
|
src: 'img/logo.svg',
|
|
81
86
|
},
|
|
82
|
-
items: [
|
|
83
|
-
{
|
|
84
|
-
type: 'docSidebar',
|
|
85
|
-
sidebarId: 'docs',
|
|
86
|
-
position: 'left',
|
|
87
|
-
label: 'Documentation',
|
|
88
|
-
},
|
|
89
|
-
],
|
|
87
|
+
items: [],
|
|
90
88
|
},
|
|
91
89
|
|
|
92
90
|
footer: {
|
|
93
91
|
style: 'dark',
|
|
94
|
-
links:
|
|
95
|
-
|
|
96
|
-
title: 'Documentation',
|
|
97
|
-
items: [
|
|
98
|
-
{
|
|
99
|
-
label: 'Strategy',
|
|
100
|
-
to: '/strategy',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
label: 'Architecture',
|
|
104
|
-
to: '/architecture',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
107
|
-
},
|
|
108
|
-
],
|
|
109
|
-
copyright: \`Copyright © \${new Date().getFullYear()} SpecWeave. Built with Docusaurus.\`,
|
|
92
|
+
links: ${footerLinksBlock},
|
|
93
|
+
copyright: \`Copyright \u00a9 \${new Date().getFullYear()} ${escapeQuotes(projectName)}. Built with Docusaurus.\`,
|
|
110
94
|
},
|
|
111
95
|
|
|
112
96
|
prism: {
|
|
@@ -114,13 +98,20 @@ const config = {
|
|
|
114
98
|
darkTheme: prismThemes.dracula,
|
|
115
99
|
additionalLanguages: ['bash', 'typescript', 'javascript', 'json', 'yaml'],
|
|
116
100
|
},
|
|
101
|
+
|
|
102
|
+
colorMode: {
|
|
103
|
+
defaultMode: 'light',
|
|
104
|
+
respectPrefersColorScheme: true,
|
|
105
|
+
},
|
|
117
106
|
}),
|
|
118
107
|
|
|
119
108
|
// Mermaid diagrams support
|
|
120
|
-
// Use 'md' format since SpecWeave docs are .md files, not .mdx
|
|
121
109
|
markdown: {
|
|
122
110
|
mermaid: true,
|
|
123
111
|
format: 'md',
|
|
112
|
+
hooks: {
|
|
113
|
+
onBrokenMarkdownLinks: 'warn',
|
|
114
|
+
},
|
|
124
115
|
},
|
|
125
116
|
themes: ['@docusaurus/theme-mermaid'],
|
|
126
117
|
};
|
|
@@ -142,7 +133,7 @@ export async function writeDocusaurusConfig(targetDir, config) {
|
|
|
142
133
|
*/
|
|
143
134
|
export function generatePackageJSON(title) {
|
|
144
135
|
return JSON.stringify({
|
|
145
|
-
name: '
|
|
136
|
+
name: 'docs-site',
|
|
146
137
|
version: '1.0.0',
|
|
147
138
|
description: `${title} - Documentation Site`,
|
|
148
139
|
private: true,
|
|
@@ -186,83 +177,340 @@ export async function writePackageJSON(targetDir, title) {
|
|
|
186
177
|
await fs.writeFile(packagePath, content, 'utf-8');
|
|
187
178
|
}
|
|
188
179
|
/**
|
|
189
|
-
* Generate
|
|
180
|
+
* Generate a professional SVG logo from project initials
|
|
181
|
+
*/
|
|
182
|
+
export function generateLogoSVG(initials, primaryColor = '#4f46e5') {
|
|
183
|
+
const darkerColor = darkenColor(primaryColor, 20);
|
|
184
|
+
const fontSize = initials.length > 1 ? 76 : 90;
|
|
185
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
|
|
186
|
+
<defs>
|
|
187
|
+
<linearGradient id="logo-bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
188
|
+
<stop offset="0%" style="stop-color:${primaryColor}" />
|
|
189
|
+
<stop offset="100%" style="stop-color:${darkerColor}" />
|
|
190
|
+
</linearGradient>
|
|
191
|
+
</defs>
|
|
192
|
+
<rect x="8" y="8" width="184" height="184" rx="44" ry="44" fill="url(#logo-bg)" />
|
|
193
|
+
<text x="100" y="100" font-family="system-ui, -apple-system, 'Segoe UI', sans-serif"
|
|
194
|
+
font-size="${fontSize}" font-weight="700" fill="white"
|
|
195
|
+
text-anchor="middle" dominant-baseline="central" letter-spacing="-2">${initials}</text>
|
|
196
|
+
</svg>`;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Generate a favicon SVG (simplified, optimized for small sizes)
|
|
200
|
+
*/
|
|
201
|
+
export function generateFaviconSVG(initials, primaryColor = '#4f46e5') {
|
|
202
|
+
const firstChar = initials.charAt(0);
|
|
203
|
+
const darkerColor = darkenColor(primaryColor, 20);
|
|
204
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
|
|
205
|
+
<defs>
|
|
206
|
+
<linearGradient id="fav-bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
207
|
+
<stop offset="0%" style="stop-color:${primaryColor}" />
|
|
208
|
+
<stop offset="100%" style="stop-color:${darkerColor}" />
|
|
209
|
+
</linearGradient>
|
|
210
|
+
</defs>
|
|
211
|
+
<rect x="1" y="1" width="30" height="30" rx="7" ry="7" fill="url(#fav-bg)" />
|
|
212
|
+
<text x="16" y="16" font-family="system-ui, sans-serif"
|
|
213
|
+
font-size="18" font-weight="700" fill="white"
|
|
214
|
+
text-anchor="middle" dominant-baseline="central">${firstChar}</text>
|
|
215
|
+
</svg>`;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Generate custom CSS for professional theme
|
|
190
219
|
*/
|
|
191
220
|
export function generateCustomCSS(theme) {
|
|
192
221
|
const themes = {
|
|
193
|
-
default:
|
|
222
|
+
default: {
|
|
223
|
+
light: `
|
|
224
|
+
--ifm-color-primary: #4f46e5;
|
|
225
|
+
--ifm-color-primary-dark: #4338ca;
|
|
226
|
+
--ifm-color-primary-darker: #3730a3;
|
|
227
|
+
--ifm-color-primary-darkest: #312e81;
|
|
228
|
+
--ifm-color-primary-light: #6366f1;
|
|
229
|
+
--ifm-color-primary-lighter: #818cf8;
|
|
230
|
+
--ifm-color-primary-lightest: #a5b4fc;`,
|
|
231
|
+
dark: `
|
|
232
|
+
--ifm-color-primary: #818cf8;
|
|
233
|
+
--ifm-color-primary-dark: #6366f1;
|
|
234
|
+
--ifm-color-primary-darker: #4f46e5;
|
|
235
|
+
--ifm-color-primary-darkest: #4338ca;
|
|
236
|
+
--ifm-color-primary-light: #a5b4fc;
|
|
237
|
+
--ifm-color-primary-lighter: #c7d2fe;
|
|
238
|
+
--ifm-color-primary-lightest: #e0e7ff;`,
|
|
239
|
+
},
|
|
240
|
+
classic: {
|
|
241
|
+
light: `
|
|
242
|
+
--ifm-color-primary: #2563eb;
|
|
243
|
+
--ifm-color-primary-dark: #1d4ed8;
|
|
244
|
+
--ifm-color-primary-darker: #1e40af;
|
|
245
|
+
--ifm-color-primary-darkest: #1e3a8a;
|
|
246
|
+
--ifm-color-primary-light: #3b82f6;
|
|
247
|
+
--ifm-color-primary-lighter: #60a5fa;
|
|
248
|
+
--ifm-color-primary-lightest: #93bbfd;`,
|
|
249
|
+
dark: `
|
|
250
|
+
--ifm-color-primary: #60a5fa;
|
|
251
|
+
--ifm-color-primary-dark: #3b82f6;
|
|
252
|
+
--ifm-color-primary-darker: #2563eb;
|
|
253
|
+
--ifm-color-primary-darkest: #1d4ed8;
|
|
254
|
+
--ifm-color-primary-light: #93bbfd;
|
|
255
|
+
--ifm-color-primary-lighter: #bfdbfe;
|
|
256
|
+
--ifm-color-primary-lightest: #dbeafe;`,
|
|
257
|
+
},
|
|
258
|
+
dark: {
|
|
259
|
+
light: `
|
|
260
|
+
--ifm-color-primary: #6366f1;
|
|
261
|
+
--ifm-color-primary-dark: #4f46e5;
|
|
262
|
+
--ifm-color-primary-darker: #4338ca;
|
|
263
|
+
--ifm-color-primary-darkest: #3730a3;
|
|
264
|
+
--ifm-color-primary-light: #818cf8;
|
|
265
|
+
--ifm-color-primary-lighter: #a5b4fc;
|
|
266
|
+
--ifm-color-primary-lightest: #c7d2fe;`,
|
|
267
|
+
dark: `
|
|
268
|
+
--ifm-color-primary: #a5b4fc;
|
|
269
|
+
--ifm-color-primary-dark: #818cf8;
|
|
270
|
+
--ifm-color-primary-darker: #6366f1;
|
|
271
|
+
--ifm-color-primary-darkest: #4f46e5;
|
|
272
|
+
--ifm-color-primary-light: #c7d2fe;
|
|
273
|
+
--ifm-color-primary-lighter: #e0e7ff;
|
|
274
|
+
--ifm-color-primary-lightest: #eef2ff;`,
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
const selected = themes[theme] || themes.default;
|
|
278
|
+
return `/**
|
|
279
|
+
* Professional documentation theme
|
|
280
|
+
* Auto-generated — customize as needed
|
|
281
|
+
*/
|
|
282
|
+
|
|
283
|
+
/* ===== Color Palette ===== */
|
|
194
284
|
:root {
|
|
195
|
-
|
|
196
|
-
--ifm-color-primary-dark: #29784c;
|
|
197
|
-
--ifm-color-primary-darker: #277148;
|
|
198
|
-
--ifm-color-primary-darkest: #205d3b;
|
|
199
|
-
--ifm-color-primary-light: #33925d;
|
|
200
|
-
--ifm-color-primary-lighter: #359962;
|
|
201
|
-
--ifm-color-primary-lightest: #3cad6e;
|
|
285
|
+
${selected.light}
|
|
202
286
|
--ifm-code-font-size: 95%;
|
|
203
|
-
--
|
|
287
|
+
--ifm-heading-font-weight: 600;
|
|
288
|
+
--ifm-font-size-base: 16px;
|
|
289
|
+
--ifm-line-height-base: 1.65;
|
|
290
|
+
--docusaurus-highlighted-code-line-bg: rgba(79, 70, 229, 0.1);
|
|
204
291
|
}
|
|
205
292
|
|
|
206
293
|
[data-theme='dark'] {
|
|
207
|
-
|
|
208
|
-
--
|
|
209
|
-
--ifm-color-primary-darker: #1fa588;
|
|
210
|
-
--ifm-color-primary-darkest: #1a8870;
|
|
211
|
-
--ifm-color-primary-light: #29d5b0;
|
|
212
|
-
--ifm-color-primary-lighter: #32d8b4;
|
|
213
|
-
--ifm-color-primary-lightest: #4fddbf;
|
|
214
|
-
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
|
|
215
|
-
}
|
|
216
|
-
`,
|
|
217
|
-
classic: `
|
|
218
|
-
:root {
|
|
219
|
-
--ifm-color-primary: #0066cc;
|
|
220
|
-
--ifm-color-primary-dark: #005cb8;
|
|
221
|
-
--ifm-color-primary-darker: #0056ad;
|
|
222
|
-
--ifm-color-primary-darkest: #00478f;
|
|
223
|
-
--ifm-color-primary-light: #0070e0;
|
|
224
|
-
--ifm-color-primary-lighter: #0076eb;
|
|
225
|
-
--ifm-color-primary-lightest: #1a85ff;
|
|
226
|
-
--ifm-code-font-size: 95%;
|
|
294
|
+
${selected.dark}
|
|
295
|
+
--docusaurus-highlighted-code-line-bg: rgba(99, 102, 241, 0.15);
|
|
227
296
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
--ifm-background-color: #0d1117;
|
|
233
|
-
--ifm-code-font-size: 95%;
|
|
297
|
+
|
|
298
|
+
/* ===== Global ===== */
|
|
299
|
+
* {
|
|
300
|
+
transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
|
|
234
301
|
}
|
|
235
302
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
--ifm-background-color: #0d1117;
|
|
303
|
+
html {
|
|
304
|
+
scroll-behavior: smooth;
|
|
239
305
|
}
|
|
240
|
-
`
|
|
241
|
-
};
|
|
242
|
-
return `/**
|
|
243
|
-
* Custom CSS for SpecWeave documentation
|
|
244
|
-
* Theme: ${theme}
|
|
245
|
-
* Auto-generated by SpecWeave docs-preview plugin
|
|
246
|
-
*/
|
|
247
306
|
|
|
248
|
-
|
|
307
|
+
/* ===== Navbar ===== */
|
|
308
|
+
.navbar {
|
|
309
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
|
310
|
+
border-bottom: 1px solid var(--ifm-color-emphasis-200);
|
|
311
|
+
backdrop-filter: blur(8px);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.navbar__title {
|
|
315
|
+
font-weight: 700;
|
|
316
|
+
letter-spacing: -0.01em;
|
|
317
|
+
}
|
|
249
318
|
|
|
250
|
-
|
|
319
|
+
.navbar__logo img {
|
|
320
|
+
border-radius: 8px;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/* ===== Sidebar ===== */
|
|
324
|
+
.theme-doc-sidebar-container {
|
|
325
|
+
border-right: 1px solid var(--ifm-color-emphasis-200);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.menu__link {
|
|
329
|
+
border-radius: 6px;
|
|
330
|
+
font-size: 0.9rem;
|
|
331
|
+
padding: 0.4rem 0.75rem;
|
|
332
|
+
transition: all 0.15s ease;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.menu__link:hover {
|
|
336
|
+
background: var(--ifm-color-emphasis-100);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.menu__link--active {
|
|
340
|
+
font-weight: 600;
|
|
341
|
+
color: var(--ifm-color-primary);
|
|
342
|
+
background: var(--ifm-color-primary-lightest);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
[data-theme='dark'] .menu__link--active {
|
|
346
|
+
background: rgba(99, 102, 241, 0.12);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.menu__list-item-collapsible .menu__caret::before {
|
|
350
|
+
filter: var(--ifm-menu-color-active);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/* ===== Content ===== */
|
|
251
354
|
.markdown {
|
|
252
355
|
--ifm-h1-font-size: 2rem;
|
|
253
356
|
--ifm-h2-font-size: 1.5rem;
|
|
254
357
|
--ifm-h3-font-size: 1.25rem;
|
|
255
358
|
}
|
|
256
359
|
|
|
257
|
-
|
|
360
|
+
.markdown h1, .markdown h2, .markdown h3 {
|
|
361
|
+
letter-spacing: -0.02em;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.markdown h2 {
|
|
365
|
+
margin-top: 2.5rem;
|
|
366
|
+
padding-bottom: 0.5rem;
|
|
367
|
+
border-bottom: 1px solid var(--ifm-color-emphasis-200);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/* ===== Links ===== */
|
|
371
|
+
.markdown a {
|
|
372
|
+
text-decoration: none;
|
|
373
|
+
border-bottom: 1px solid transparent;
|
|
374
|
+
transition: border-color 0.15s ease;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.markdown a:hover {
|
|
378
|
+
border-bottom-color: var(--ifm-color-primary);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* ===== Code Blocks ===== */
|
|
258
382
|
.prism-code {
|
|
259
|
-
font-size: 0.
|
|
383
|
+
font-size: 0.875rem;
|
|
384
|
+
border-radius: 8px;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
pre {
|
|
388
|
+
border-radius: 8px !important;
|
|
389
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
[data-theme='dark'] pre {
|
|
393
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
code {
|
|
397
|
+
border-radius: 4px;
|
|
398
|
+
padding: 2px 6px;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/* ===== Tables ===== */
|
|
402
|
+
table {
|
|
403
|
+
display: table;
|
|
404
|
+
width: 100%;
|
|
405
|
+
border-collapse: separate;
|
|
406
|
+
border-spacing: 0;
|
|
407
|
+
border-radius: 8px;
|
|
408
|
+
overflow: hidden;
|
|
409
|
+
border: 1px solid var(--ifm-color-emphasis-200);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
table thead tr {
|
|
413
|
+
background: var(--ifm-color-emphasis-100);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
table thead th {
|
|
417
|
+
font-weight: 600;
|
|
418
|
+
font-size: 0.875rem;
|
|
419
|
+
text-transform: uppercase;
|
|
420
|
+
letter-spacing: 0.03em;
|
|
421
|
+
padding: 0.75rem 1rem;
|
|
422
|
+
border-bottom: 2px solid var(--ifm-color-emphasis-200);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
table tbody td {
|
|
426
|
+
padding: 0.65rem 1rem;
|
|
427
|
+
border-bottom: 1px solid var(--ifm-color-emphasis-100);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
table tbody tr:last-child td {
|
|
431
|
+
border-bottom: none;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
table tbody tr:hover {
|
|
435
|
+
background: var(--ifm-color-emphasis-50, rgba(0, 0, 0, 0.02));
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/* ===== Blockquotes ===== */
|
|
439
|
+
blockquote {
|
|
440
|
+
border-left: 4px solid var(--ifm-color-primary);
|
|
441
|
+
background: var(--ifm-color-emphasis-100);
|
|
442
|
+
border-radius: 0 8px 8px 0;
|
|
443
|
+
padding: 1rem 1.25rem;
|
|
444
|
+
font-style: normal;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/* ===== Admonitions ===== */
|
|
448
|
+
.admonition {
|
|
449
|
+
border-radius: 8px;
|
|
450
|
+
border: none;
|
|
451
|
+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/* ===== Cards (prev/next navigation) ===== */
|
|
455
|
+
.pagination-nav__link {
|
|
456
|
+
border-radius: 10px;
|
|
457
|
+
border: 1px solid var(--ifm-color-emphasis-200);
|
|
458
|
+
transition: all 0.2s ease;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.pagination-nav__link:hover {
|
|
462
|
+
border-color: var(--ifm-color-primary);
|
|
463
|
+
box-shadow: 0 4px 16px rgba(79, 70, 229, 0.1);
|
|
260
464
|
}
|
|
261
465
|
|
|
262
|
-
/* Mermaid
|
|
466
|
+
/* ===== Mermaid ===== */
|
|
263
467
|
.docusaurus-mermaid-container {
|
|
264
468
|
text-align: center;
|
|
265
469
|
margin: 2rem 0;
|
|
470
|
+
padding: 1rem;
|
|
471
|
+
background: var(--ifm-color-emphasis-100);
|
|
472
|
+
border-radius: 8px;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/* ===== Table of Contents ===== */
|
|
476
|
+
.table-of-contents__link--active {
|
|
477
|
+
font-weight: 600;
|
|
478
|
+
color: var(--ifm-color-primary);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/* ===== Footer ===== */
|
|
482
|
+
.footer--dark {
|
|
483
|
+
background: #1e1e2e;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
[data-theme='dark'] .footer--dark {
|
|
487
|
+
background: #111118;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/* ===== Scrollbar ===== */
|
|
491
|
+
::-webkit-scrollbar {
|
|
492
|
+
width: 6px;
|
|
493
|
+
height: 6px;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
::-webkit-scrollbar-track {
|
|
497
|
+
background: transparent;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
::-webkit-scrollbar-thumb {
|
|
501
|
+
background: var(--ifm-color-emphasis-300);
|
|
502
|
+
border-radius: 3px;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
::-webkit-scrollbar-thumb:hover {
|
|
506
|
+
background: var(--ifm-color-emphasis-500);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/* ===== Responsive ===== */
|
|
510
|
+
@media screen and (max-width: 996px) {
|
|
511
|
+
.markdown h2 {
|
|
512
|
+
margin-top: 2rem;
|
|
513
|
+
}
|
|
266
514
|
}
|
|
267
515
|
`;
|
|
268
516
|
}
|
|
@@ -276,9 +524,21 @@ export async function writeCustomCSS(targetDir, theme) {
|
|
|
276
524
|
await fs.writeFile(cssPath, content, 'utf-8');
|
|
277
525
|
}
|
|
278
526
|
/**
|
|
279
|
-
* Generate index page (landing page)
|
|
527
|
+
* Generate index page (landing page) with dynamic categories
|
|
280
528
|
*/
|
|
281
|
-
export function generateIndexPage(title, tagline) {
|
|
529
|
+
export function generateIndexPage(title, tagline, categories, projectName) {
|
|
530
|
+
const firstCategoryLink = categories.length > 0 ? `/${categories[0].id}` : '/';
|
|
531
|
+
// Build category cards JSX
|
|
532
|
+
const categoryCards = categories.map(cat => {
|
|
533
|
+
const escapedDesc = escapeQuotes(cat.description);
|
|
534
|
+
return ` <a href="${cat.id}" className={styles.categoryCard} key="${cat.id}">
|
|
535
|
+
<span className={styles.categoryIcon}>${cat.icon}</span>
|
|
536
|
+
<h3>${cat.label}</h3>
|
|
537
|
+
<p>${escapedDesc}</p>
|
|
538
|
+
<span className={styles.docCount}>${cat.docCount} document${cat.docCount !== 1 ? 's' : ''}</span>
|
|
539
|
+
</a>`;
|
|
540
|
+
}).join('\n');
|
|
541
|
+
const brandName = projectName ? escapeQuotes(projectName) : '';
|
|
282
542
|
return `import React from 'react';
|
|
283
543
|
import clsx from 'clsx';
|
|
284
544
|
import Link from '@docusaurus/Link';
|
|
@@ -289,15 +549,15 @@ import styles from './index.module.css';
|
|
|
289
549
|
function HomepageHeader() {
|
|
290
550
|
const {siteConfig} = useDocusaurusContext();
|
|
291
551
|
return (
|
|
292
|
-
<header className={clsx('hero
|
|
552
|
+
<header className={clsx('hero', styles.heroBanner)}>
|
|
293
553
|
<div className="container">
|
|
294
|
-
<h1 className=
|
|
295
|
-
<p className=
|
|
554
|
+
<h1 className={styles.heroTitle}>${brandName ? `<span className={styles.brandName}>${brandName}</span> Documentation` : '{siteConfig.title}'}</h1>
|
|
555
|
+
<p className={styles.heroSubtitle}>{siteConfig.tagline}</p>
|
|
296
556
|
<div className={styles.buttons}>
|
|
297
557
|
<Link
|
|
298
|
-
className="button button--
|
|
299
|
-
to="
|
|
300
|
-
|
|
558
|
+
className="button button--primary button--lg"
|
|
559
|
+
to="${firstCategoryLink}">
|
|
560
|
+
Browse Documentation
|
|
301
561
|
</Link>
|
|
302
562
|
</div>
|
|
303
563
|
</div>
|
|
@@ -309,31 +569,14 @@ export default function Home() {
|
|
|
309
569
|
const {siteConfig} = useDocusaurusContext();
|
|
310
570
|
return (
|
|
311
571
|
<Layout
|
|
312
|
-
title={
|
|
313
|
-
description="${tagline}">
|
|
572
|
+
title={siteConfig.title}
|
|
573
|
+
description="${escapeQuotes(tagline)}">
|
|
314
574
|
<HomepageHeader />
|
|
315
575
|
<main>
|
|
316
|
-
<div className="container" style={{
|
|
317
|
-
<div className=
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
<p>
|
|
321
|
-
This is your SpecWeave documentation site, automatically generated from your
|
|
322
|
-
<code>.specweave/docs/</code> folder.
|
|
323
|
-
</p>
|
|
324
|
-
<p>
|
|
325
|
-
Use the sidebar to navigate through your documentation:
|
|
326
|
-
</p>
|
|
327
|
-
<ul>
|
|
328
|
-
<li><strong>Strategy</strong>: Business rationale, PRDs, OKRs</li>
|
|
329
|
-
<li><strong>Specs</strong>: Feature specifications and user stories</li>
|
|
330
|
-
<li><strong>Architecture</strong>: Technical design, ADRs, diagrams</li>
|
|
331
|
-
<li><strong>Delivery</strong>: Build & release processes</li>
|
|
332
|
-
<li><strong>Operations</strong>: Runbooks, SLOs, incidents</li>
|
|
333
|
-
<li><strong>Governance</strong>: Policies, security, compliance</li>
|
|
334
|
-
</ul>
|
|
335
|
-
</div>
|
|
336
|
-
</div>
|
|
576
|
+
<div className="container" style={{padding: '3rem 0'}}>
|
|
577
|
+
${categories.length > 0 ? ` <div className={styles.categoryGrid}>
|
|
578
|
+
${categoryCards}
|
|
579
|
+
</div>` : ''}
|
|
337
580
|
</div>
|
|
338
581
|
</main>
|
|
339
582
|
</Layout>
|
|
@@ -344,9 +587,9 @@ export default function Home() {
|
|
|
344
587
|
/**
|
|
345
588
|
* Write index page to file
|
|
346
589
|
*/
|
|
347
|
-
export async function writeIndexPage(targetDir, title, tagline) {
|
|
590
|
+
export async function writeIndexPage(targetDir, title, tagline, categories = [], projectName) {
|
|
348
591
|
const indexPath = path.join(targetDir, 'src', 'pages', 'index.js');
|
|
349
|
-
const content = generateIndexPage(title, tagline);
|
|
592
|
+
const content = generateIndexPage(title, tagline, categories, projectName);
|
|
350
593
|
await fs.ensureDir(path.dirname(indexPath));
|
|
351
594
|
await fs.writeFile(indexPath, content, 'utf-8');
|
|
352
595
|
}
|
|
@@ -355,16 +598,38 @@ export async function writeIndexPage(targetDir, title, tagline) {
|
|
|
355
598
|
*/
|
|
356
599
|
export function generateIndexModuleCSS() {
|
|
357
600
|
return `.heroBanner {
|
|
358
|
-
padding:
|
|
601
|
+
padding: 5rem 0 4rem;
|
|
359
602
|
text-align: center;
|
|
360
603
|
position: relative;
|
|
361
604
|
overflow: hidden;
|
|
605
|
+
background: linear-gradient(135deg, #4f46e5 0%, #6366f1 50%, #818cf8 100%);
|
|
606
|
+
color: white;
|
|
362
607
|
}
|
|
363
608
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
609
|
+
[data-theme='dark'] .heroBanner {
|
|
610
|
+
background: linear-gradient(135deg, #312e81 0%, #3730a3 50%, #4338ca 100%);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.heroTitle {
|
|
614
|
+
font-size: 3rem;
|
|
615
|
+
font-weight: 400;
|
|
616
|
+
letter-spacing: -0.03em;
|
|
617
|
+
margin-bottom: 0.75rem;
|
|
618
|
+
color: rgba(255, 255, 255, 0.9);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
.brandName {
|
|
622
|
+
font-weight: 800;
|
|
623
|
+
color: white;
|
|
624
|
+
letter-spacing: -0.04em;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
.heroSubtitle {
|
|
628
|
+
font-size: 1.25rem;
|
|
629
|
+
opacity: 0.9;
|
|
630
|
+
max-width: 600px;
|
|
631
|
+
margin: 0 auto 1.5rem;
|
|
632
|
+
color: white;
|
|
368
633
|
}
|
|
369
634
|
|
|
370
635
|
.buttons {
|
|
@@ -374,6 +639,114 @@ export function generateIndexModuleCSS() {
|
|
|
374
639
|
gap: 1rem;
|
|
375
640
|
margin-top: 2rem;
|
|
376
641
|
}
|
|
642
|
+
|
|
643
|
+
.buttons a {
|
|
644
|
+
background: white;
|
|
645
|
+
color: #4f46e5;
|
|
646
|
+
border: none;
|
|
647
|
+
font-weight: 600;
|
|
648
|
+
padding: 0.75rem 2rem;
|
|
649
|
+
border-radius: 8px;
|
|
650
|
+
font-size: 1rem;
|
|
651
|
+
transition: all 0.2s ease;
|
|
652
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.buttons a:hover {
|
|
656
|
+
background: #f8fafc;
|
|
657
|
+
color: #4338ca;
|
|
658
|
+
transform: translateY(-2px);
|
|
659
|
+
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
|
|
660
|
+
text-decoration: none;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/* Category Grid */
|
|
664
|
+
.categoryGrid {
|
|
665
|
+
display: grid;
|
|
666
|
+
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
667
|
+
gap: 1.5rem;
|
|
668
|
+
padding: 1rem 0 2rem;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
.categoryCard {
|
|
672
|
+
background: var(--ifm-card-background-color, white);
|
|
673
|
+
border: 1px solid var(--ifm-color-emphasis-200);
|
|
674
|
+
border-radius: 12px;
|
|
675
|
+
padding: 1.75rem;
|
|
676
|
+
transition: all 0.2s ease;
|
|
677
|
+
text-decoration: none !important;
|
|
678
|
+
color: inherit;
|
|
679
|
+
display: block;
|
|
680
|
+
cursor: pointer;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
.categoryCard:hover {
|
|
684
|
+
transform: translateY(-4px);
|
|
685
|
+
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.08);
|
|
686
|
+
border-color: var(--ifm-color-primary);
|
|
687
|
+
text-decoration: none !important;
|
|
688
|
+
color: inherit;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
[data-theme='dark'] .categoryCard:hover {
|
|
692
|
+
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
.categoryCard h3 {
|
|
696
|
+
margin: 0.5rem 0 0.25rem;
|
|
697
|
+
font-size: 1.15rem;
|
|
698
|
+
font-weight: 600;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
.categoryCard p {
|
|
702
|
+
margin: 0 0 0.75rem;
|
|
703
|
+
font-size: 0.9rem;
|
|
704
|
+
color: var(--ifm-color-emphasis-700);
|
|
705
|
+
line-height: 1.5;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.categoryIcon {
|
|
709
|
+
font-size: 2rem;
|
|
710
|
+
display: block;
|
|
711
|
+
margin-bottom: 0.25rem;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
.docCount {
|
|
715
|
+
font-size: 0.8rem;
|
|
716
|
+
color: var(--ifm-color-emphasis-500);
|
|
717
|
+
font-weight: 500;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/* Responsive */
|
|
721
|
+
@media screen and (max-width: 996px) {
|
|
722
|
+
.heroBanner {
|
|
723
|
+
padding: 3rem 1.5rem;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
.heroTitle {
|
|
727
|
+
font-size: 2.25rem;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
.categoryGrid {
|
|
731
|
+
grid-template-columns: 1fr;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
@media screen and (max-width: 600px) {
|
|
736
|
+
.heroTitle {
|
|
737
|
+
font-size: 1.75rem;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
.brandName {
|
|
741
|
+
display: block;
|
|
742
|
+
font-size: 2rem;
|
|
743
|
+
margin-bottom: 0.25rem;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
.heroSubtitle {
|
|
747
|
+
font-size: 1rem;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
377
750
|
`;
|
|
378
751
|
}
|
|
379
752
|
/**
|
|
@@ -385,4 +758,20 @@ export async function writeIndexModuleCSS(targetDir) {
|
|
|
385
758
|
await fs.ensureDir(path.dirname(cssPath));
|
|
386
759
|
await fs.writeFile(cssPath, content, 'utf-8');
|
|
387
760
|
}
|
|
761
|
+
/**
|
|
762
|
+
* Escape single quotes for template string safety
|
|
763
|
+
*/
|
|
764
|
+
function escapeQuotes(str) {
|
|
765
|
+
return str.replace(/'/g, "\\'").replace(/\n/g, ' ');
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Darken a hex color by a percentage
|
|
769
|
+
*/
|
|
770
|
+
function darkenColor(hex, percent) {
|
|
771
|
+
const num = parseInt(hex.replace('#', ''), 16);
|
|
772
|
+
const r = Math.max(0, (num >> 16) - Math.round(2.55 * percent));
|
|
773
|
+
const g = Math.max(0, ((num >> 8) & 0x00ff) - Math.round(2.55 * percent));
|
|
774
|
+
const b = Math.max(0, (num & 0x0000ff) - Math.round(2.55 * percent));
|
|
775
|
+
return `#${(r << 16 | g << 8 | b).toString(16).padStart(6, '0')}`;
|
|
776
|
+
}
|
|
388
777
|
//# sourceMappingURL=config-generator.js.map
|