@knowcode/doc-builder 1.1.4 ā 1.1.6
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/CHANGELOG.md +30 -0
- package/cli.js +35 -2
- package/lib/core-builder.js +1 -1
- package/lib/deploy.js +97 -16
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,36 @@ All notable changes to @knowcode/doc-builder will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.6] - 2025-01-19
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Fixed missing CSS and JS styling in deployed documentation
|
|
12
|
+
- Corrected relative paths for assets (css/style.css instead of ./css/style.css)
|
|
13
|
+
- Added proper styling to fallback index.html
|
|
14
|
+
- Enhanced index.html with beautiful grid layout when no README exists
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- Cache headers for CSS and JS files in vercel.json
|
|
18
|
+
- Proper meta tags and viewport settings in generated index files
|
|
19
|
+
- Beautiful card-based layout for documentation listing
|
|
20
|
+
|
|
21
|
+
### Improved
|
|
22
|
+
- Index.html now uses the same Notion-inspired styling as other pages
|
|
23
|
+
- Better visual consistency across all generated pages
|
|
24
|
+
|
|
25
|
+
## [1.1.5] - 2025-01-19
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- Clear explanation of Vercel URLs after deployment
|
|
29
|
+
- Shows permanent production URL (e.g., gasworld.vercel.app)
|
|
30
|
+
- Explains the difference between production and preview URLs
|
|
31
|
+
- Better post-deployment messaging
|
|
32
|
+
|
|
33
|
+
### Improved
|
|
34
|
+
- Deployment success message now shows both URLs clearly
|
|
35
|
+
- Production URL is highlighted as the one to share
|
|
36
|
+
- Preview URL is explained as deployment-specific
|
|
37
|
+
|
|
8
38
|
## [1.1.4] - 2025-01-19
|
|
9
39
|
|
|
10
40
|
### Fixed
|
package/cli.js
CHANGED
|
@@ -319,7 +319,28 @@ ${chalk.yellow('Troubleshooting:')}
|
|
|
319
319
|
// Default to production deployment
|
|
320
320
|
const isProduction = options.prod !== false; // Default true unless explicitly --no-prod
|
|
321
321
|
const url = await deployToVercel(config, isProduction);
|
|
322
|
-
spinner.succeed(`Deployed successfully
|
|
322
|
+
spinner.succeed(`Deployed successfully!`);
|
|
323
|
+
|
|
324
|
+
// Extract project name from URL
|
|
325
|
+
const projectName = url.match(/https:\/\/([^-]+)/)?.[1] || 'your-project';
|
|
326
|
+
|
|
327
|
+
console.log(chalk.green('\nā
Deployment Complete!\n'));
|
|
328
|
+
|
|
329
|
+
if (isProduction) {
|
|
330
|
+
console.log(chalk.yellow('š Your documentation is live at:'));
|
|
331
|
+
console.log(chalk.cyan.bold(` ${projectName}.vercel.app`) + chalk.gray(' (Production URL - share this!)'));
|
|
332
|
+
console.log();
|
|
333
|
+
console.log(chalk.gray('This deployment also created a unique preview URL:'));
|
|
334
|
+
console.log(chalk.gray(` ${url}`));
|
|
335
|
+
console.log(chalk.gray(' (This URL is specific to this deployment)'));
|
|
336
|
+
} else {
|
|
337
|
+
console.log(chalk.yellow('š Preview deployment created at:'));
|
|
338
|
+
console.log(chalk.cyan(` ${url}`));
|
|
339
|
+
console.log();
|
|
340
|
+
console.log(chalk.gray('To deploy to production, run:'));
|
|
341
|
+
console.log(chalk.gray(' npx @knowcode/doc-builder deploy'));
|
|
342
|
+
}
|
|
343
|
+
console.log();
|
|
323
344
|
|
|
324
345
|
} catch (error) {
|
|
325
346
|
spinner.fail('Deployment failed');
|
|
@@ -510,7 +531,19 @@ program
|
|
|
510
531
|
|
|
511
532
|
// Default to production deployment
|
|
512
533
|
const url = await deployToVercel(config, true);
|
|
513
|
-
deploySpinner.succeed(`Deployed successfully
|
|
534
|
+
deploySpinner.succeed(`Deployed successfully!`);
|
|
535
|
+
|
|
536
|
+
// Extract project name from URL
|
|
537
|
+
const projectName = url.match(/https:\/\/([^-]+)/)?.[1] || 'your-project';
|
|
538
|
+
|
|
539
|
+
console.log(chalk.green('\nā
Deployment Complete!\n'));
|
|
540
|
+
console.log(chalk.yellow('š Your documentation is live at:'));
|
|
541
|
+
console.log(chalk.cyan.bold(` ${projectName}.vercel.app`) + chalk.gray(' (Production URL - share this!)'));
|
|
542
|
+
console.log();
|
|
543
|
+
console.log(chalk.gray('This deployment also created a unique preview URL:'));
|
|
544
|
+
console.log(chalk.gray(` ${url}`));
|
|
545
|
+
console.log(chalk.gray(' (This URL is specific to this deployment)'));
|
|
546
|
+
console.log();
|
|
514
547
|
|
|
515
548
|
} catch (error) {
|
|
516
549
|
console.error(chalk.red('\nError: ' + error.message));
|
package/lib/core-builder.js
CHANGED
|
@@ -59,7 +59,7 @@ function processMarkdownContent(content) {
|
|
|
59
59
|
// Generate HTML from template
|
|
60
60
|
function generateHTML(title, content, navigation, currentPath = '', config = {}) {
|
|
61
61
|
const depth = currentPath.split('/').filter(p => p).length;
|
|
62
|
-
const relativePath = depth > 0 ? '../'.repeat(depth) : '
|
|
62
|
+
const relativePath = depth > 0 ? '../'.repeat(depth) : '';
|
|
63
63
|
|
|
64
64
|
const siteName = config.siteName || 'Documentation';
|
|
65
65
|
const siteDescription = config.siteDescription || 'Documentation site';
|
package/lib/deploy.js
CHANGED
|
@@ -66,7 +66,27 @@ async function setupVercelProject(config) {
|
|
|
66
66
|
"installCommand": "",
|
|
67
67
|
"framework": null,
|
|
68
68
|
"cleanUrls": true,
|
|
69
|
-
"trailingSlash": false
|
|
69
|
+
"trailingSlash": false,
|
|
70
|
+
"headers": [
|
|
71
|
+
{
|
|
72
|
+
"source": "/css/(.*)",
|
|
73
|
+
"headers": [
|
|
74
|
+
{
|
|
75
|
+
"key": "Cache-Control",
|
|
76
|
+
"value": "public, max-age=31536000, immutable"
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"source": "/js/(.*)",
|
|
82
|
+
"headers": [
|
|
83
|
+
{
|
|
84
|
+
"key": "Cache-Control",
|
|
85
|
+
"value": "public, max-age=31536000, immutable"
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
]
|
|
70
90
|
};
|
|
71
91
|
|
|
72
92
|
fs.writeJsonSync(vercelConfigPath, vercelConfig, { spaces: 2 });
|
|
@@ -181,7 +201,27 @@ async function deployToVercel(config, isProd = false) {
|
|
|
181
201
|
"installCommand": "",
|
|
182
202
|
"framework": null,
|
|
183
203
|
"cleanUrls": true,
|
|
184
|
-
"trailingSlash": false
|
|
204
|
+
"trailingSlash": false,
|
|
205
|
+
"headers": [
|
|
206
|
+
{
|
|
207
|
+
"source": "/css/(.*)",
|
|
208
|
+
"headers": [
|
|
209
|
+
{
|
|
210
|
+
"key": "Cache-Control",
|
|
211
|
+
"value": "public, max-age=31536000, immutable"
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"source": "/js/(.*)",
|
|
217
|
+
"headers": [
|
|
218
|
+
{
|
|
219
|
+
"key": "Cache-Control",
|
|
220
|
+
"value": "public, max-age=31536000, immutable"
|
|
221
|
+
}
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
]
|
|
185
225
|
};
|
|
186
226
|
fs.writeJsonSync(vercelConfigPath, vercelConfig, { spaces: 2 });
|
|
187
227
|
}
|
|
@@ -295,15 +335,20 @@ async function prepareDeployment(config) {
|
|
|
295
335
|
if (!fs.existsSync(indexPath)) {
|
|
296
336
|
const readmePath = path.join(outputDir, 'README.html');
|
|
297
337
|
if (fs.existsSync(readmePath)) {
|
|
298
|
-
// Create redirect to README.html
|
|
338
|
+
// Create redirect to README.html with proper styling
|
|
299
339
|
const redirectHtml = `<!DOCTYPE html>
|
|
300
340
|
<html>
|
|
301
341
|
<head>
|
|
342
|
+
<meta charset="UTF-8">
|
|
343
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
302
344
|
<meta http-equiv="refresh" content="0; url=README.html">
|
|
303
345
|
<title>Redirecting...</title>
|
|
346
|
+
<link rel="stylesheet" href="css/style.css">
|
|
304
347
|
</head>
|
|
305
348
|
<body>
|
|
306
|
-
<
|
|
349
|
+
<div style="text-align: center; margin-top: 50px;">
|
|
350
|
+
<p>Redirecting to <a href="README.html">documentation</a>...</p>
|
|
351
|
+
</div>
|
|
307
352
|
</body>
|
|
308
353
|
</html>`;
|
|
309
354
|
fs.writeFileSync(indexPath, redirectHtml);
|
|
@@ -318,21 +363,57 @@ async function prepareDeployment(config) {
|
|
|
318
363
|
const indexHtml = `<!DOCTYPE html>
|
|
319
364
|
<html>
|
|
320
365
|
<head>
|
|
366
|
+
<meta charset="UTF-8">
|
|
367
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
321
368
|
<title>Documentation</title>
|
|
322
|
-
<
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
ul { list-style: none; padding: 0; }
|
|
326
|
-
li { margin: 10px 0; }
|
|
327
|
-
a { color: #0066cc; text-decoration: none; }
|
|
328
|
-
a:hover { text-decoration: underline; }
|
|
329
|
-
</style>
|
|
369
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
|
370
|
+
<link rel="stylesheet" href="css/style.css">
|
|
371
|
+
<link rel="stylesheet" href="css/notion-style.css">
|
|
330
372
|
</head>
|
|
331
373
|
<body>
|
|
332
|
-
<
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
374
|
+
<div class="navigation">
|
|
375
|
+
<div class="nav-header">
|
|
376
|
+
<h2>${config.siteName || 'Documentation'}</h2>
|
|
377
|
+
</div>
|
|
378
|
+
<nav>
|
|
379
|
+
<ul>
|
|
380
|
+
${htmlFiles.map(file => {
|
|
381
|
+
const name = file.replace('.html', '').replace(/-/g, ' ');
|
|
382
|
+
const capitalizedName = name.split(' ').map(word =>
|
|
383
|
+
word.charAt(0).toUpperCase() + word.slice(1)
|
|
384
|
+
).join(' ');
|
|
385
|
+
return `<li><a href="${file}"><i class="fas fa-file"></i> ${capitalizedName}</a></li>`;
|
|
386
|
+
}).join('\n ')}
|
|
387
|
+
</ul>
|
|
388
|
+
</nav>
|
|
389
|
+
</div>
|
|
390
|
+
<div class="content">
|
|
391
|
+
<div class="header">
|
|
392
|
+
<h1 style="text-align: center; margin: 50px 0;">š Documentation</h1>
|
|
393
|
+
</div>
|
|
394
|
+
<div class="main-content">
|
|
395
|
+
<div class="doc-grid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; padding: 20px;">
|
|
396
|
+
${htmlFiles.map(file => {
|
|
397
|
+
const name = file.replace('.html', '').replace(/-/g, ' ');
|
|
398
|
+
const capitalizedName = name.split(' ').map(word =>
|
|
399
|
+
word.charAt(0).toUpperCase() + word.slice(1)
|
|
400
|
+
).join(' ');
|
|
401
|
+
return `
|
|
402
|
+
<a href="${file}" class="doc-card" style="display: block; padding: 20px; border: 1px solid #e1e4e8; border-radius: 8px; text-decoration: none; color: inherit; transition: all 0.2s;">
|
|
403
|
+
<h3 style="margin: 0 0 10px 0; color: #0366d6;"><i class="fas fa-file-alt"></i> ${capitalizedName}</h3>
|
|
404
|
+
<p style="margin: 0; color: #586069; font-size: 14px;">Click to view this documentation</p>
|
|
405
|
+
</a>`;
|
|
406
|
+
}).join('')}
|
|
407
|
+
</div>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
<script src="js/main.js"></script>
|
|
411
|
+
<style>
|
|
412
|
+
.doc-card:hover {
|
|
413
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
414
|
+
transform: translateY(-2px);
|
|
415
|
+
}
|
|
416
|
+
</style>
|
|
336
417
|
</body>
|
|
337
418
|
</html>`;
|
|
338
419
|
fs.writeFileSync(indexPath, indexHtml);
|