@alliance-droid/svelte-docs-system 0.0.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/COMPONENTS.md +365 -0
- package/COVERAGE_REPORT.md +663 -0
- package/README.md +42 -0
- package/SEARCH_VERIFICATION.md +229 -0
- package/TEST_SUMMARY.md +344 -0
- package/bin/init.js +821 -0
- package/docs/E2E_TESTS.md +354 -0
- package/docs/TESTING.md +754 -0
- package/docs/de/index.md +41 -0
- package/docs/en/COMPONENTS.md +443 -0
- package/docs/en/api/examples.md +100 -0
- package/docs/en/api/overview.md +69 -0
- package/docs/en/components/index.md +622 -0
- package/docs/en/config/navigation.md +505 -0
- package/docs/en/config/theme-and-colors.md +395 -0
- package/docs/en/getting-started/integration.md +406 -0
- package/docs/en/guides/common-setups.md +651 -0
- package/docs/en/index.md +243 -0
- package/docs/en/markdown.md +102 -0
- package/docs/en/routing.md +64 -0
- package/docs/en/setup.md +52 -0
- package/docs/en/troubleshooting.md +704 -0
- package/docs/es/index.md +41 -0
- package/docs/fr/index.md +41 -0
- package/docs/ja/index.md +41 -0
- package/package.json +40 -0
- package/pagefind.toml +8 -0
- package/postcss.config.js +5 -0
- package/src/app.css +119 -0
- package/src/app.d.ts +13 -0
- package/src/app.html +11 -0
- package/src/lib/assets/favicon.svg +1 -0
- package/src/lib/components/APITable.svelte +120 -0
- package/src/lib/components/APITable.test.ts +153 -0
- package/src/lib/components/Breadcrumbs.svelte +85 -0
- package/src/lib/components/Breadcrumbs.test.ts +148 -0
- package/src/lib/components/Callout.svelte +60 -0
- package/src/lib/components/Callout.test.ts +100 -0
- package/src/lib/components/CodeBlock.svelte +68 -0
- package/src/lib/components/CodeBlock.test.ts +133 -0
- package/src/lib/components/DocLayout.svelte +84 -0
- package/src/lib/components/Footer.svelte +78 -0
- package/src/lib/components/Image.svelte +100 -0
- package/src/lib/components/Image.test.ts +163 -0
- package/src/lib/components/Navbar.svelte +141 -0
- package/src/lib/components/Search.svelte +248 -0
- package/src/lib/components/Sidebar.svelte +110 -0
- package/src/lib/components/Tabs.svelte +48 -0
- package/src/lib/components/Tabs.test.ts +102 -0
- package/src/lib/config.test.ts +140 -0
- package/src/lib/config.ts +179 -0
- package/src/lib/configIntegration.test.ts +272 -0
- package/src/lib/configLoader.ts +231 -0
- package/src/lib/configParser.test.ts +217 -0
- package/src/lib/configParser.ts +234 -0
- package/src/lib/index.ts +34 -0
- package/src/lib/integration.test.ts +426 -0
- package/src/lib/navigationBuilder.test.ts +338 -0
- package/src/lib/navigationBuilder.ts +268 -0
- package/src/lib/performance.test.ts +369 -0
- package/src/lib/routing.test.ts +202 -0
- package/src/lib/routing.ts +127 -0
- package/src/lib/search-functionality.test.ts +493 -0
- package/src/lib/stores/i18n.test.ts +180 -0
- package/src/lib/stores/i18n.ts +143 -0
- package/src/lib/stores/nav.ts +36 -0
- package/src/lib/stores/search.test.ts +140 -0
- package/src/lib/stores/search.ts +162 -0
- package/src/lib/stores/theme.ts +59 -0
- package/src/lib/stores/version.test.ts +139 -0
- package/src/lib/stores/version.ts +111 -0
- package/src/lib/themeCustomization.test.ts +223 -0
- package/src/lib/themeCustomization.ts +212 -0
- package/src/lib/utils/highlight.test.ts +136 -0
- package/src/lib/utils/highlight.ts +100 -0
- package/src/lib/utils/index.ts +7 -0
- package/src/lib/utils/markdown.test.ts +357 -0
- package/src/lib/utils/markdown.ts +77 -0
- package/src/routes/+layout.server.ts +1 -0
- package/src/routes/+layout.svelte +28 -0
- package/src/routes/+page.svelte +165 -0
- package/static/robots.txt +3 -0
- package/svelte.config.js +18 -0
- package/tailwind.config.ts +55 -0
- package/template-starter/.github/workflows/build.yml +40 -0
- package/template-starter/.github/workflows/deploy-github-pages.yml +47 -0
- package/template-starter/.github/workflows/deploy-netlify.yml +41 -0
- package/template-starter/.github/workflows/deploy-vercel.yml +64 -0
- package/template-starter/NPM-PACKAGE-SETUP.md +233 -0
- package/template-starter/README.md +320 -0
- package/template-starter/docs/_config.json +39 -0
- package/template-starter/docs/api/components.md +257 -0
- package/template-starter/docs/api/overview.md +169 -0
- package/template-starter/docs/guides/configuration.md +145 -0
- package/template-starter/docs/guides/github-pages-deployment.md +254 -0
- package/template-starter/docs/guides/netlify-deployment.md +159 -0
- package/template-starter/docs/guides/vercel-deployment.md +131 -0
- package/template-starter/docs/index.md +49 -0
- package/template-starter/docs/setup.md +149 -0
- package/template-starter/package.json +31 -0
- package/template-starter/pagefind.toml +3 -0
- package/template-starter/postcss.config.js +5 -0
- package/template-starter/src/app.css +34 -0
- package/template-starter/src/app.d.ts +13 -0
- package/template-starter/src/app.html +11 -0
- package/template-starter/src/lib/components/APITable.svelte +120 -0
- package/template-starter/src/lib/components/APITable.test.ts +19 -0
- package/template-starter/src/lib/components/Breadcrumbs.svelte +85 -0
- package/template-starter/src/lib/components/Breadcrumbs.test.ts +19 -0
- package/template-starter/src/lib/components/Callout.svelte +60 -0
- package/template-starter/src/lib/components/Callout.test.ts +16 -0
- package/template-starter/src/lib/components/CodeBlock.svelte +68 -0
- package/template-starter/src/lib/components/CodeBlock.test.ts +12 -0
- package/template-starter/src/lib/components/DocLayout.svelte +84 -0
- package/template-starter/src/lib/components/Footer.svelte +78 -0
- package/template-starter/src/lib/components/Image.svelte +100 -0
- package/template-starter/src/lib/components/Image.test.ts +15 -0
- package/template-starter/src/lib/components/Navbar.svelte +141 -0
- package/template-starter/src/lib/components/Search.svelte +248 -0
- package/template-starter/src/lib/components/Sidebar.svelte +110 -0
- package/template-starter/src/lib/components/Tabs.svelte +48 -0
- package/template-starter/src/lib/components/Tabs.test.ts +17 -0
- package/template-starter/src/lib/index.ts +15 -0
- package/template-starter/src/routes/+layout.svelte +28 -0
- package/template-starter/src/routes/+page.svelte +92 -0
- package/template-starter/svelte.config.js +17 -0
- package/template-starter/tailwind.config.ts +17 -0
- package/template-starter/tsconfig.json +13 -0
- package/template-starter/vite.config.ts +6 -0
- package/tests/e2e/example.spec.ts +345 -0
- package/tsconfig.json +20 -0
- package/vite.config.ts +6 -0
- package/vitest.config.ts +34 -0
- package/vitest.setup.ts +21 -0
package/bin/init.js
ADDED
|
@@ -0,0 +1,821 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Initialize docs system in an existing SvelteKit project
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx svelte-docs-system init [--route /docs] [--folder ./docs]
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { dirname } from 'path';
|
|
14
|
+
import readline from 'readline';
|
|
15
|
+
|
|
16
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const projectRoot = process.cwd();
|
|
18
|
+
|
|
19
|
+
// Colors for console output
|
|
20
|
+
const colors = {
|
|
21
|
+
reset: '\x1b[0m',
|
|
22
|
+
bright: '\x1b[1m',
|
|
23
|
+
green: '\x1b[32m',
|
|
24
|
+
yellow: '\x1b[33m',
|
|
25
|
+
blue: '\x1b[34m',
|
|
26
|
+
red: '\x1b[31m'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function log(message, color = 'reset') {
|
|
30
|
+
console.log(`${colors[color]}${message}${colors.reset}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function error(message) {
|
|
34
|
+
console.error(`${colors.red}✘ Error: ${message}${colors.reset}`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function success(message) {
|
|
39
|
+
log(`✓ ${message}`, 'green');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function info(message) {
|
|
43
|
+
log(`ℹ ${message}`, 'blue');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function warn(message) {
|
|
47
|
+
log(`⚠ ${message}`, 'yellow');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Create readline interface for prompts
|
|
51
|
+
const rl = readline.createInterface({
|
|
52
|
+
input: process.stdin,
|
|
53
|
+
output: process.stdout
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
function prompt(question) {
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
rl.question(question, (answer) => {
|
|
59
|
+
resolve(answer);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Simple argument parser
|
|
65
|
+
function parseArgs() {
|
|
66
|
+
const args = process.argv.slice(2);
|
|
67
|
+
const result = {
|
|
68
|
+
route: null,
|
|
69
|
+
folder: null
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
for (let i = 0; i < args.length; i++) {
|
|
73
|
+
if (args[i] === '--route' && args[i + 1]) {
|
|
74
|
+
result.route = args[i + 1];
|
|
75
|
+
i++;
|
|
76
|
+
} else if (args[i] === '--folder' && args[i + 1]) {
|
|
77
|
+
result.folder = args[i + 1];
|
|
78
|
+
i++;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function main() {
|
|
86
|
+
try {
|
|
87
|
+
log('\n🚀 Initializing documentation system...', 'bright');
|
|
88
|
+
|
|
89
|
+
// Check if we're in a SvelteKit project
|
|
90
|
+
const svelteConfigPath = path.join(projectRoot, 'svelte.config.js');
|
|
91
|
+
if (!fs.existsSync(svelteConfigPath)) {
|
|
92
|
+
error('svelte.config.js not found. Please run this in a SvelteKit project root.');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Get config options from args or prompts
|
|
96
|
+
const defaultRoute = '/docs';
|
|
97
|
+
const defaultFolder = './docs';
|
|
98
|
+
const args = parseArgs();
|
|
99
|
+
|
|
100
|
+
let finalRoute, finalFolder;
|
|
101
|
+
|
|
102
|
+
if (args.route && args.folder) {
|
|
103
|
+
// Non-interactive mode
|
|
104
|
+
finalRoute = args.route;
|
|
105
|
+
finalFolder = args.folder;
|
|
106
|
+
info(`Using route: ${finalRoute}`);
|
|
107
|
+
info(`Using folder: ${finalFolder}`);
|
|
108
|
+
} else {
|
|
109
|
+
// Interactive mode
|
|
110
|
+
log('\nConfiguration:', 'bright');
|
|
111
|
+
const docsRoute = await prompt(
|
|
112
|
+
`Enter docs route (default: ${defaultRoute}): `
|
|
113
|
+
);
|
|
114
|
+
finalRoute = docsRoute.trim() || defaultRoute;
|
|
115
|
+
|
|
116
|
+
const docsFolder = await prompt(
|
|
117
|
+
`Enter docs folder path (default: ${defaultFolder}): `
|
|
118
|
+
);
|
|
119
|
+
finalFolder = docsFolder.trim() || defaultFolder;
|
|
120
|
+
|
|
121
|
+
info(`Using route: ${finalRoute}`);
|
|
122
|
+
info(`Using folder: ${finalFolder}`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Create docs folder structure
|
|
126
|
+
log('\nCreating folder structure...', 'bright');
|
|
127
|
+
const docsFolderPath = path.join(projectRoot, finalFolder);
|
|
128
|
+
const apiFolderPath = path.join(docsFolderPath, 'api');
|
|
129
|
+
const guidesFolderPath = path.join(docsFolderPath, 'guides');
|
|
130
|
+
|
|
131
|
+
// Create directories
|
|
132
|
+
[docsFolderPath, apiFolderPath, guidesFolderPath].forEach((dir) => {
|
|
133
|
+
if (!fs.existsSync(dir)) {
|
|
134
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
135
|
+
success(`Created directory: ${path.relative(projectRoot, dir)}`);
|
|
136
|
+
} else {
|
|
137
|
+
warn(`Directory already exists: ${path.relative(projectRoot, dir)}`);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Create example markdown files
|
|
142
|
+
log('\nCreating example documentation...', 'bright');
|
|
143
|
+
createMarkdownFiles(docsFolderPath, finalRoute);
|
|
144
|
+
|
|
145
|
+
// Create route handlers
|
|
146
|
+
log('\nCreating route handlers...', 'bright');
|
|
147
|
+
createRouteHandlers(projectRoot, finalRoute, finalFolder);
|
|
148
|
+
|
|
149
|
+
// Update svelte.config.js
|
|
150
|
+
log('\nUpdating svelte.config.js...', 'bright');
|
|
151
|
+
updateSvelteConfig(svelteConfigPath, finalRoute, finalFolder);
|
|
152
|
+
|
|
153
|
+
// Create navigation config
|
|
154
|
+
log('\nCreating navigation config...', 'bright');
|
|
155
|
+
createNavConfig(docsFolderPath, finalRoute);
|
|
156
|
+
|
|
157
|
+
log('\n✨ Documentation system initialized!', 'green');
|
|
158
|
+
log(`\nNext steps:`, 'bright');
|
|
159
|
+
log(` 1. Start dev server: npm run dev`);
|
|
160
|
+
log(` 2. Visit: http://localhost:5173${finalRoute}`);
|
|
161
|
+
log(` 3. Edit markdown files in ${finalFolder}/ to customize docs`);
|
|
162
|
+
log(` 4. Edit ${finalFolder}/_config.json to customize navigation\n`);
|
|
163
|
+
|
|
164
|
+
rl.close();
|
|
165
|
+
} catch (err) {
|
|
166
|
+
error(err.message);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function createMarkdownFiles(docsFolderPath, docsRoute) {
|
|
171
|
+
const files = {
|
|
172
|
+
'index.md': `---
|
|
173
|
+
title: Documentation Home
|
|
174
|
+
description: Welcome to your documentation
|
|
175
|
+
author: Your Name
|
|
176
|
+
date: ${new Date().toISOString().split('T')[0]}
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
# Welcome to Your Documentation
|
|
180
|
+
|
|
181
|
+
This is the home page of your documentation site.
|
|
182
|
+
|
|
183
|
+
## Getting Started
|
|
184
|
+
|
|
185
|
+
- Check out the [Setup Guide](${docsRoute}/setup) to get started
|
|
186
|
+
- Read the [Architecture Guide](${docsRoute}/guides/architecture) for an overview
|
|
187
|
+
- Visit the [API Reference](${docsRoute}/api/overview) for detailed API docs
|
|
188
|
+
|
|
189
|
+
## Features
|
|
190
|
+
|
|
191
|
+
- **Automatic routing** from markdown files
|
|
192
|
+
- **Nested paths** support (organize docs in folders)
|
|
193
|
+
- **Frontmatter metadata** (title, author, date)
|
|
194
|
+
- **Professional styling** out of the box
|
|
195
|
+
- **Easy to customize** and extend
|
|
196
|
+
|
|
197
|
+
## Project Structure
|
|
198
|
+
|
|
199
|
+
\`\`\`
|
|
200
|
+
${path.basename(docsFolderPath)}/
|
|
201
|
+
├── index.md (This file)
|
|
202
|
+
├── setup.md (Getting started)
|
|
203
|
+
├── api/
|
|
204
|
+
│ ├── overview.md (API overview)
|
|
205
|
+
│ └── reference.md (API reference)
|
|
206
|
+
└── guides/
|
|
207
|
+
├── architecture.md (Architecture guide)
|
|
208
|
+
└── advanced.md (Advanced topics)
|
|
209
|
+
\`\`\`
|
|
210
|
+
|
|
211
|
+
Each markdown file automatically becomes a route. For example:
|
|
212
|
+
- \`${path.basename(docsFolderPath)}/setup.md\` → \`${docsRoute}/setup\`
|
|
213
|
+
- \`${path.basename(docsFolderPath)}/api/overview.md\` → \`${docsRoute}/api/overview\`
|
|
214
|
+
`,
|
|
215
|
+
'setup.md': `---
|
|
216
|
+
title: Setup Guide
|
|
217
|
+
description: Get started with your documentation
|
|
218
|
+
author: Your Name
|
|
219
|
+
date: ${new Date().toISOString().split('T')[0]}
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
# Setup Guide
|
|
223
|
+
|
|
224
|
+
This guide will help you get started with your documentation.
|
|
225
|
+
|
|
226
|
+
## Prerequisites
|
|
227
|
+
|
|
228
|
+
- Node.js 18 or higher
|
|
229
|
+
- npm, pnpm, or yarn
|
|
230
|
+
|
|
231
|
+
## Installation
|
|
232
|
+
|
|
233
|
+
If you haven't already, install the dependencies:
|
|
234
|
+
|
|
235
|
+
\`\`\`bash
|
|
236
|
+
npm install
|
|
237
|
+
\`\`\`
|
|
238
|
+
|
|
239
|
+
## Starting Development
|
|
240
|
+
|
|
241
|
+
Start the development server:
|
|
242
|
+
|
|
243
|
+
\`\`\`bash
|
|
244
|
+
npm run dev
|
|
245
|
+
\`\`\`
|
|
246
|
+
|
|
247
|
+
Visit \`http://localhost:5173\` in your browser.
|
|
248
|
+
|
|
249
|
+
## Creating Documentation
|
|
250
|
+
|
|
251
|
+
1. Create new markdown files in the \`docs/\` folder
|
|
252
|
+
2. Use frontmatter for metadata (title, description, author, date)
|
|
253
|
+
3. Organize files in folders for nested routing
|
|
254
|
+
4. Markdown files automatically become routes
|
|
255
|
+
|
|
256
|
+
### Example
|
|
257
|
+
|
|
258
|
+
Create \`docs/guides/my-guide.md\`:
|
|
259
|
+
|
|
260
|
+
\`\`\`markdown
|
|
261
|
+
---
|
|
262
|
+
title: My Guide
|
|
263
|
+
description: A guide about something
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
# My Guide
|
|
267
|
+
|
|
268
|
+
Content goes here...
|
|
269
|
+
\`\`\`
|
|
270
|
+
|
|
271
|
+
This creates a route: \`/docs/guides/my-guide\`
|
|
272
|
+
|
|
273
|
+
## Customization
|
|
274
|
+
|
|
275
|
+
Edit \`docs/_config.json\` to customize the navigation structure. See the comments in that file for options.
|
|
276
|
+
|
|
277
|
+
## Next Steps
|
|
278
|
+
|
|
279
|
+
- Read the [API Reference](/docs/api/overview)
|
|
280
|
+
- Explore the [Architecture Guide](/docs/guides/architecture)
|
|
281
|
+
`,
|
|
282
|
+
'api/overview.md': `---
|
|
283
|
+
title: API Overview
|
|
284
|
+
description: API documentation overview
|
|
285
|
+
author: Your Name
|
|
286
|
+
date: ${new Date().toISOString().split('T')[0]}
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
# API Overview
|
|
290
|
+
|
|
291
|
+
This page provides an overview of your API.
|
|
292
|
+
|
|
293
|
+
## Base URL
|
|
294
|
+
|
|
295
|
+
\`\`\`
|
|
296
|
+
https://api.example.com/v1
|
|
297
|
+
\`\`\`
|
|
298
|
+
|
|
299
|
+
## Authentication
|
|
300
|
+
|
|
301
|
+
Include your API key in the request headers:
|
|
302
|
+
|
|
303
|
+
\`\`\`bash
|
|
304
|
+
curl -H "Authorization: Bearer YOUR_API_KEY" https://api.example.com/v1/...
|
|
305
|
+
\`\`\`
|
|
306
|
+
|
|
307
|
+
## Response Format
|
|
308
|
+
|
|
309
|
+
All responses are JSON:
|
|
310
|
+
|
|
311
|
+
\`\`\`json
|
|
312
|
+
{
|
|
313
|
+
"success": true,
|
|
314
|
+
"data": { /* ... */ }
|
|
315
|
+
}
|
|
316
|
+
\`\`\`
|
|
317
|
+
|
|
318
|
+
## Endpoints
|
|
319
|
+
|
|
320
|
+
For detailed endpoint documentation, see the [API Reference](/docs/api/reference).
|
|
321
|
+
|
|
322
|
+
## Rate Limiting
|
|
323
|
+
|
|
324
|
+
API requests are rate limited to 1000 per hour per API key.
|
|
325
|
+
`,
|
|
326
|
+
'api/reference.md': `---
|
|
327
|
+
title: API Reference
|
|
328
|
+
description: Complete API reference documentation
|
|
329
|
+
author: Your Name
|
|
330
|
+
date: ${new Date().toISOString().split('T')[0]}
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
# API Reference
|
|
334
|
+
|
|
335
|
+
Complete documentation of all API endpoints.
|
|
336
|
+
|
|
337
|
+
## GET /users
|
|
338
|
+
|
|
339
|
+
Retrieve a list of users.
|
|
340
|
+
|
|
341
|
+
### Parameters
|
|
342
|
+
|
|
343
|
+
| Name | Type | Description |
|
|
344
|
+
|------|------|-------------|
|
|
345
|
+
| page | integer | Page number (default: 1) |
|
|
346
|
+
| limit | integer | Results per page (default: 10) |
|
|
347
|
+
|
|
348
|
+
### Example
|
|
349
|
+
|
|
350
|
+
\`\`\`bash
|
|
351
|
+
curl https://api.example.com/v1/users?page=1&limit=10
|
|
352
|
+
\`\`\`
|
|
353
|
+
|
|
354
|
+
### Response
|
|
355
|
+
|
|
356
|
+
\`\`\`json
|
|
357
|
+
{
|
|
358
|
+
"success": true,
|
|
359
|
+
"data": [
|
|
360
|
+
{
|
|
361
|
+
"id": "user_123",
|
|
362
|
+
"name": "John Doe",
|
|
363
|
+
"email": "john@example.com"
|
|
364
|
+
}
|
|
365
|
+
]
|
|
366
|
+
}
|
|
367
|
+
\`\`\`
|
|
368
|
+
|
|
369
|
+
## POST /users
|
|
370
|
+
|
|
371
|
+
Create a new user.
|
|
372
|
+
|
|
373
|
+
### Request Body
|
|
374
|
+
|
|
375
|
+
| Field | Type | Required | Description |
|
|
376
|
+
|-------|------|----------|-------------|
|
|
377
|
+
| name | string | Yes | User's full name |
|
|
378
|
+
| email | string | Yes | User's email address |
|
|
379
|
+
|
|
380
|
+
### Example
|
|
381
|
+
|
|
382
|
+
\`\`\`bash
|
|
383
|
+
curl -X POST https://api.example.com/v1/users \\
|
|
384
|
+
-H "Content-Type: application/json" \\
|
|
385
|
+
-d '{"name":"Jane Doe","email":"jane@example.com"}'
|
|
386
|
+
\`\`\`
|
|
387
|
+
|
|
388
|
+
### Response
|
|
389
|
+
|
|
390
|
+
\`\`\`json
|
|
391
|
+
{
|
|
392
|
+
"success": true,
|
|
393
|
+
"data": {
|
|
394
|
+
"id": "user_456",
|
|
395
|
+
"name": "Jane Doe",
|
|
396
|
+
"email": "jane@example.com"
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
\`\`\`
|
|
400
|
+
`,
|
|
401
|
+
'guides/architecture.md': `---
|
|
402
|
+
title: Architecture Guide
|
|
403
|
+
description: Overview of the system architecture
|
|
404
|
+
author: Your Name
|
|
405
|
+
date: ${new Date().toISOString().split('T')[0]}
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
# Architecture Guide
|
|
409
|
+
|
|
410
|
+
This guide explains the high-level architecture of the system.
|
|
411
|
+
|
|
412
|
+
## Overview
|
|
413
|
+
|
|
414
|
+
The system is built with modern web technologies:
|
|
415
|
+
|
|
416
|
+
- **Frontend:** SvelteKit with Svelte 5
|
|
417
|
+
- **Styling:** Tailwind CSS
|
|
418
|
+
- **Build Tool:** Vite
|
|
419
|
+
- **Documentation:** This markdown-based system
|
|
420
|
+
|
|
421
|
+
## Components
|
|
422
|
+
|
|
423
|
+
### Documentation System
|
|
424
|
+
|
|
425
|
+
The documentation system automatically:
|
|
426
|
+
|
|
427
|
+
- Converts markdown files to web pages
|
|
428
|
+
- Generates navigation from folder structure
|
|
429
|
+
- Provides search functionality
|
|
430
|
+
- Handles dark mode and responsive design
|
|
431
|
+
|
|
432
|
+
### Adding Custom Components
|
|
433
|
+
|
|
434
|
+
You can add custom Svelte components to your markdown files by extending the markdown processor.
|
|
435
|
+
|
|
436
|
+
## Data Flow
|
|
437
|
+
|
|
438
|
+
\`\`\`
|
|
439
|
+
User navigates to /docs/page
|
|
440
|
+
↓
|
|
441
|
+
SvelteKit router matches route
|
|
442
|
+
↓
|
|
443
|
+
Page loader fetches markdown file
|
|
444
|
+
↓
|
|
445
|
+
Markdown is parsed and converted to HTML
|
|
446
|
+
↓
|
|
447
|
+
Components are rendered with Svelte
|
|
448
|
+
↓
|
|
449
|
+
Page is displayed in browser
|
|
450
|
+
\`\`\`
|
|
451
|
+
|
|
452
|
+
## Performance
|
|
453
|
+
|
|
454
|
+
- Static file serving for fast load times
|
|
455
|
+
- Optimized image delivery
|
|
456
|
+
- Minimal JavaScript by default
|
|
457
|
+
- Full-text search via Pagefind
|
|
458
|
+
|
|
459
|
+
## Customization
|
|
460
|
+
|
|
461
|
+
All components can be customized by:
|
|
462
|
+
|
|
463
|
+
1. Overriding styles via Tailwind CSS
|
|
464
|
+
2. Creating custom Svelte components
|
|
465
|
+
3. Modifying the layout templates
|
|
466
|
+
|
|
467
|
+
See the configuration guide for more details.
|
|
468
|
+
`,
|
|
469
|
+
'guides/advanced.md': `---
|
|
470
|
+
title: Advanced Topics
|
|
471
|
+
description: Advanced usage and customization
|
|
472
|
+
author: Your Name
|
|
473
|
+
date: ${new Date().toISOString().split('T')[0]}
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
# Advanced Topics
|
|
477
|
+
|
|
478
|
+
This guide covers advanced usage and customization topics.
|
|
479
|
+
|
|
480
|
+
## Custom Components in Markdown
|
|
481
|
+
|
|
482
|
+
Create reusable components for your documentation:
|
|
483
|
+
|
|
484
|
+
\`\`\`svelte
|
|
485
|
+
<script>
|
|
486
|
+
export let type = 'info';
|
|
487
|
+
</script>
|
|
488
|
+
|
|
489
|
+
<div class="custom-component {type}">
|
|
490
|
+
<slot />
|
|
491
|
+
</div>
|
|
492
|
+
\`\`\`
|
|
493
|
+
|
|
494
|
+
Then use them in markdown:
|
|
495
|
+
|
|
496
|
+
\`\`\`markdown
|
|
497
|
+
<CustomComponent type="warning">
|
|
498
|
+
This is important!
|
|
499
|
+
</CustomComponent>
|
|
500
|
+
\`\`\`
|
|
501
|
+
|
|
502
|
+
## Extending the Theme
|
|
503
|
+
|
|
504
|
+
Customize the theme by:
|
|
505
|
+
|
|
506
|
+
1. Modifying Tailwind CSS configuration
|
|
507
|
+
2. Overriding component styles
|
|
508
|
+
3. Creating custom layout templates
|
|
509
|
+
|
|
510
|
+
## SEO Optimization
|
|
511
|
+
|
|
512
|
+
Each markdown file supports frontmatter metadata:
|
|
513
|
+
|
|
514
|
+
- \`title\` - Page title (shown in browser tab)
|
|
515
|
+
- \`description\` - Meta description (shown in search results)
|
|
516
|
+
- \`author\` - Author name
|
|
517
|
+
- \`date\` - Last modified date
|
|
518
|
+
|
|
519
|
+
These are automatically converted to meta tags.
|
|
520
|
+
|
|
521
|
+
## Version Management
|
|
522
|
+
|
|
523
|
+
You can maintain multiple versions of documentation:
|
|
524
|
+
|
|
525
|
+
\`\`\`
|
|
526
|
+
docs/
|
|
527
|
+
├── v1/
|
|
528
|
+
│ ├── index.md
|
|
529
|
+
│ └── api/
|
|
530
|
+
├── v2/
|
|
531
|
+
│ ├── index.md
|
|
532
|
+
│ └── api/
|
|
533
|
+
└── latest -> v2 (symlink or config)
|
|
534
|
+
\`\`\`
|
|
535
|
+
|
|
536
|
+
## Troubleshooting
|
|
537
|
+
|
|
538
|
+
### Pages not appearing
|
|
539
|
+
|
|
540
|
+
Make sure markdown files are in the \`docs/\` folder and have \`.md\` extension.
|
|
541
|
+
|
|
542
|
+
### Styling issues
|
|
543
|
+
|
|
544
|
+
Clear the \`.svelte-kit\` and \`node_modules\` folders and rebuild:
|
|
545
|
+
|
|
546
|
+
\`\`\`bash
|
|
547
|
+
rm -rf .svelte-kit node_modules
|
|
548
|
+
npm install
|
|
549
|
+
npm run build
|
|
550
|
+
\`\`\`
|
|
551
|
+
|
|
552
|
+
### Search not working
|
|
553
|
+
|
|
554
|
+
Ensure the project is built:
|
|
555
|
+
|
|
556
|
+
\`\`\`bash
|
|
557
|
+
npm run build
|
|
558
|
+
\`\`\`
|
|
559
|
+
|
|
560
|
+
Search only works with built pages.
|
|
561
|
+
`
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
for (const [filename, content] of Object.entries(files)) {
|
|
565
|
+
const filePath = path.join(docsFolderPath, filename);
|
|
566
|
+
const dirPath = path.dirname(filePath);
|
|
567
|
+
|
|
568
|
+
if (!fs.existsSync(dirPath)) {
|
|
569
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
if (!fs.existsSync(filePath)) {
|
|
573
|
+
fs.writeFileSync(filePath, content);
|
|
574
|
+
success(`Created: ${path.relative(projectRoot, filePath)}`);
|
|
575
|
+
} else {
|
|
576
|
+
warn(`File already exists: ${path.relative(projectRoot, filePath)}`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function createRouteHandlers(projectRoot, docsRoute, docsFolder) {
|
|
582
|
+
const routePath = path.join(projectRoot, 'src/routes');
|
|
583
|
+
const docsRouteName = docsRoute.substring(1); // Remove leading /
|
|
584
|
+
|
|
585
|
+
// Create the docs route folder
|
|
586
|
+
const docsRouteFolder = path.join(routePath, docsRouteName);
|
|
587
|
+
if (!fs.existsSync(docsRouteFolder)) {
|
|
588
|
+
fs.mkdirSync(docsRouteFolder, { recursive: true });
|
|
589
|
+
success(`Created directory: src/routes/${docsRouteName}`);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Create the dynamic route folder
|
|
593
|
+
const dynamicFolder = path.join(docsRouteFolder, '[...slug]');
|
|
594
|
+
if (!fs.existsSync(dynamicFolder)) {
|
|
595
|
+
fs.mkdirSync(dynamicFolder, { recursive: true });
|
|
596
|
+
success(`Created directory: src/routes/${docsRouteName}/[...slug]`);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// Create layout.svelte
|
|
600
|
+
const layoutContent = `<script lang="ts">
|
|
601
|
+
import { DocLayout } from 'svelte-docs-system';
|
|
602
|
+
import { onMount } from 'svelte';
|
|
603
|
+
|
|
604
|
+
let config = {};
|
|
605
|
+
|
|
606
|
+
onMount(async () => {
|
|
607
|
+
// Load nav config if _config.json exists
|
|
608
|
+
try {
|
|
609
|
+
const response = await fetch('${docsRoute}/_config.json');
|
|
610
|
+
if (response.ok) {
|
|
611
|
+
config = await response.json();
|
|
612
|
+
}
|
|
613
|
+
} catch (e) {
|
|
614
|
+
// Config file not found, use defaults
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
</script>
|
|
618
|
+
|
|
619
|
+
<DocLayout {config}>
|
|
620
|
+
<slot />
|
|
621
|
+
</DocLayout>
|
|
622
|
+
`;
|
|
623
|
+
|
|
624
|
+
const layoutPath = path.join(docsRouteFolder, '+layout.svelte');
|
|
625
|
+
if (!fs.existsSync(layoutPath)) {
|
|
626
|
+
fs.writeFileSync(layoutPath, layoutContent);
|
|
627
|
+
success(`Created: src/routes/${docsRouteName}/+layout.svelte`);
|
|
628
|
+
} else {
|
|
629
|
+
warn(`File already exists: src/routes/${docsRouteName}/+layout.svelte`);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// Create +page.svelte for dynamic route
|
|
633
|
+
const pageContent = `<script lang="ts" context="module">
|
|
634
|
+
import { dev } from '$app/environment';
|
|
635
|
+
|
|
636
|
+
export async function load({ params }) {
|
|
637
|
+
const slug = params.slug || 'index';
|
|
638
|
+
const docPath = '${docsRoute}/\${slug}.md';
|
|
639
|
+
|
|
640
|
+
try {
|
|
641
|
+
const response = await fetch(docPath);
|
|
642
|
+
if (!response.ok) {
|
|
643
|
+
return {
|
|
644
|
+
status: 404,
|
|
645
|
+
error: new Error('Documentation page not found')
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
const content = await response.text();
|
|
650
|
+
return {
|
|
651
|
+
props: {
|
|
652
|
+
content,
|
|
653
|
+
slug
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
} catch (error) {
|
|
657
|
+
return {
|
|
658
|
+
status: 500,
|
|
659
|
+
error: new Error('Failed to load documentation')
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
</script>
|
|
664
|
+
|
|
665
|
+
<script>
|
|
666
|
+
import { renderMarkdown } from 'svelte-docs-system';
|
|
667
|
+
|
|
668
|
+
export let data;
|
|
669
|
+
|
|
670
|
+
let { html = '', metadata = {} } = renderMarkdown(data.props?.content || '') || {};
|
|
671
|
+
</script>
|
|
672
|
+
|
|
673
|
+
<svelte:head>
|
|
674
|
+
<title>{metadata.title || 'Documentation'} | Docs</title>
|
|
675
|
+
<meta name="description" content={metadata.description || 'Documentation'} />
|
|
676
|
+
</svelte:head>
|
|
677
|
+
|
|
678
|
+
<article>
|
|
679
|
+
{@html html}
|
|
680
|
+
</article>
|
|
681
|
+
|
|
682
|
+
<style>
|
|
683
|
+
:global(article) {
|
|
684
|
+
max-width: 900px;
|
|
685
|
+
margin: 0 auto;
|
|
686
|
+
padding: 2rem;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
:global(article h1) {
|
|
690
|
+
font-size: 2.5rem;
|
|
691
|
+
margin-bottom: 1rem;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
:global(article h2) {
|
|
695
|
+
font-size: 1.875rem;
|
|
696
|
+
margin-top: 2rem;
|
|
697
|
+
margin-bottom: 1rem;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
:global(article p) {
|
|
701
|
+
line-height: 1.75;
|
|
702
|
+
margin-bottom: 1rem;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
:global(article code) {
|
|
706
|
+
background-color: #f3f4f6;
|
|
707
|
+
padding: 0.125rem 0.5rem;
|
|
708
|
+
border-radius: 0.25rem;
|
|
709
|
+
font-family: 'Courier New', monospace;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
:global(article pre) {
|
|
713
|
+
background-color: #1f2937;
|
|
714
|
+
color: #f3f4f6;
|
|
715
|
+
padding: 1rem;
|
|
716
|
+
border-radius: 0.5rem;
|
|
717
|
+
overflow-x: auto;
|
|
718
|
+
margin-bottom: 1rem;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
:global(article pre code) {
|
|
722
|
+
background-color: transparent;
|
|
723
|
+
padding: 0;
|
|
724
|
+
color: inherit;
|
|
725
|
+
}
|
|
726
|
+
</style>
|
|
727
|
+
`;
|
|
728
|
+
|
|
729
|
+
const pagePath = path.join(dynamicFolder, '+page.svelte');
|
|
730
|
+
if (!fs.existsSync(pagePath)) {
|
|
731
|
+
fs.writeFileSync(pagePath, pageContent);
|
|
732
|
+
success(`Created: src/routes/${docsRouteName}/[...slug]/+page.svelte`);
|
|
733
|
+
} else {
|
|
734
|
+
warn(`File already exists: src/routes/${docsRouteName}/[...slug]/+page.svelte`);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
function updateSvelteConfig(configPath, docsRoute, docsFolder) {
|
|
739
|
+
let config = fs.readFileSync(configPath, 'utf-8');
|
|
740
|
+
|
|
741
|
+
// Check if docs plugin is already registered
|
|
742
|
+
if (config.includes('docs plugin')) {
|
|
743
|
+
warn('Docs plugin appears to already be configured in svelte.config.js');
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// Insert plugin configuration
|
|
748
|
+
const pluginConfig = `\timport { docs } from 'svelte-docs-system';\n\n`;
|
|
749
|
+
const pluginInConfig = `\t\tdocs({
|
|
750
|
+
\t\t\tdocsRoute: '${docsRoute}',
|
|
751
|
+
\t\t\tdocsFolderPath: '${docsFolder}',
|
|
752
|
+
\t\t\tbasePath: '${docsRoute}'
|
|
753
|
+
\t\t}),`;
|
|
754
|
+
|
|
755
|
+
// Add import at the top
|
|
756
|
+
if (!config.includes("from 'svelte-docs-system'")) {
|
|
757
|
+
const firstImportIndex = config.indexOf('import');
|
|
758
|
+
config = config.slice(0, firstImportIndex) + pluginConfig + config.slice(firstImportIndex);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// Add to plugins array if exists
|
|
762
|
+
const pluginsIndex = config.indexOf('plugins:');
|
|
763
|
+
if (pluginsIndex !== -1) {
|
|
764
|
+
const arrayStart = config.indexOf('[', pluginsIndex);
|
|
765
|
+
const insertPos = arrayStart + 1;
|
|
766
|
+
config = config.slice(0, insertPos) + '\n' + pluginInConfig + '\n' + config.slice(insertPos);
|
|
767
|
+
} else {
|
|
768
|
+
// Add plugins section
|
|
769
|
+
const kitClosing = config.lastIndexOf('}');
|
|
770
|
+
const plugins = `,\n\t\tplugins: [
|
|
771
|
+
${pluginInConfig}
|
|
772
|
+
\t\t]`;
|
|
773
|
+
config = config.slice(0, kitClosing) + plugins + config.slice(kitClosing);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
fs.writeFileSync(configPath, config);
|
|
777
|
+
success('Updated svelte.config.js with docs plugin');
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
function createNavConfig(docsFolderPath, docsRoute) {
|
|
781
|
+
const configPath = path.join(docsFolderPath, '_config.json');
|
|
782
|
+
|
|
783
|
+
if (fs.existsSync(configPath)) {
|
|
784
|
+
warn(`Navigation config already exists: _config.json`);
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
const navConfig = {
|
|
789
|
+
name: 'Documentation',
|
|
790
|
+
baseUrl: docsRoute,
|
|
791
|
+
sections: [
|
|
792
|
+
{
|
|
793
|
+
title: 'Getting Started',
|
|
794
|
+
pages: [
|
|
795
|
+
{ label: 'Home', path: docsRoute },
|
|
796
|
+
{ label: 'Setup', path: `${docsRoute}/setup` }
|
|
797
|
+
]
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
title: 'API',
|
|
801
|
+
pages: [
|
|
802
|
+
{ label: 'Overview', path: `${docsRoute}/api/overview` },
|
|
803
|
+
{ label: 'Reference', path: `${docsRoute}/api/reference` }
|
|
804
|
+
]
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
title: 'Guides',
|
|
808
|
+
pages: [
|
|
809
|
+
{ label: 'Architecture', path: `${docsRoute}/guides/architecture` },
|
|
810
|
+
{ label: 'Advanced', path: `${docsRoute}/guides/advanced` }
|
|
811
|
+
]
|
|
812
|
+
}
|
|
813
|
+
]
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
fs.writeFileSync(configPath, JSON.stringify(navConfig, null, 2));
|
|
817
|
+
success('Created: docs/_config.json');
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// Run the main function
|
|
821
|
+
main();
|