@knowcode/doc-builder 1.0.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.
- package/README.md +250 -0
- package/assets/css/notion-style.css +1462 -0
- package/assets/css/style.css +1974 -0
- package/assets/js/auth.js +65 -0
- package/assets/js/main.js +1333 -0
- package/cli.js +282 -0
- package/index.js +38 -0
- package/lib/builder.js +79 -0
- package/lib/config.js +255 -0
- package/lib/deploy.js +158 -0
- package/lib/dev-server.js +96 -0
- package/package.json +35 -0
- package/scripts/npx-runner.js +27 -0
- package/scripts/setup.js +56 -0
package/cli.js
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { program } = require('commander');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const prompts = require('prompts');
|
|
6
|
+
const ora = require('ora');
|
|
7
|
+
const fs = require('fs-extra');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { build } = require('./lib/builder');
|
|
10
|
+
const { startDevServer } = require('./lib/dev-server');
|
|
11
|
+
const { deployToVercel, setupVercelProject } = require('./lib/deploy');
|
|
12
|
+
const { loadConfig, createDefaultConfig } = require('./lib/config');
|
|
13
|
+
const { execSync } = require('child_process');
|
|
14
|
+
|
|
15
|
+
// Package info
|
|
16
|
+
const packageJson = require('./package.json');
|
|
17
|
+
|
|
18
|
+
// Default to build command if no args provided
|
|
19
|
+
if (process.argv.length === 2) {
|
|
20
|
+
process.argv.push('build');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
program
|
|
24
|
+
.name('doc-builder')
|
|
25
|
+
.description(packageJson.description)
|
|
26
|
+
.version(packageJson.version)
|
|
27
|
+
.addHelpText('before', `
|
|
28
|
+
${chalk.cyan('🚀 @juno/doc-builder')} - Transform your markdown into beautiful documentation sites
|
|
29
|
+
|
|
30
|
+
${chalk.yellow('What it does:')}
|
|
31
|
+
• Converts markdown files to static HTML with a beautiful Notion-inspired theme
|
|
32
|
+
• Automatically generates navigation from your folder structure
|
|
33
|
+
• Supports mermaid diagrams, syntax highlighting, and dark mode
|
|
34
|
+
• Deploys to Vercel with one command (zero configuration)
|
|
35
|
+
• Optional authentication to protect private documentation
|
|
36
|
+
|
|
37
|
+
${chalk.yellow('Quick Start:')}
|
|
38
|
+
${chalk.gray('$')} npx @juno/doc-builder ${chalk.gray('# Build and deploy to Vercel')}
|
|
39
|
+
${chalk.gray('$')} npx @juno/doc-builder build ${chalk.gray('# Build HTML files only')}
|
|
40
|
+
${chalk.gray('$')} npx @juno/doc-builder dev ${chalk.gray('# Start development server')}
|
|
41
|
+
`);
|
|
42
|
+
|
|
43
|
+
// Build command
|
|
44
|
+
program
|
|
45
|
+
.command('build')
|
|
46
|
+
.description('Build the documentation site to static HTML')
|
|
47
|
+
.option('-c, --config <path>', 'path to config file (default: doc-builder.config.js)')
|
|
48
|
+
.option('-i, --input <dir>', 'input directory containing markdown files (default: docs)')
|
|
49
|
+
.option('-o, --output <dir>', 'output directory for HTML files (default: html)')
|
|
50
|
+
.option('--preset <preset>', 'use a preset configuration (available: cybersolstice)')
|
|
51
|
+
.option('--legacy', 'use legacy mode for backward compatibility')
|
|
52
|
+
.option('--no-auth', 'disable authentication even if configured')
|
|
53
|
+
.option('--no-changelog', 'disable automatic changelog generation')
|
|
54
|
+
.addHelpText('after', `
|
|
55
|
+
${chalk.yellow('Examples:')}
|
|
56
|
+
${chalk.gray('$')} doc-builder build ${chalk.gray('# Build with defaults')}
|
|
57
|
+
${chalk.gray('$')} doc-builder build --input docs --output dist
|
|
58
|
+
${chalk.gray('$')} doc-builder build --preset cybersolstice ${chalk.gray('# Use JUNO platform preset')}
|
|
59
|
+
${chalk.gray('$')} doc-builder build --config my-config.js ${chalk.gray('# Use custom config')}
|
|
60
|
+
`)
|
|
61
|
+
.action(async (options) => {
|
|
62
|
+
const spinner = ora('Building documentation...').start();
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const config = await loadConfig(options.config || 'doc-builder.config.js', options);
|
|
66
|
+
await build(config);
|
|
67
|
+
spinner.succeed('Documentation built successfully!');
|
|
68
|
+
} catch (error) {
|
|
69
|
+
spinner.fail('Build failed');
|
|
70
|
+
console.error(chalk.red(error.message));
|
|
71
|
+
if (error.stack) {
|
|
72
|
+
console.error(chalk.gray(error.stack));
|
|
73
|
+
}
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Dev server command
|
|
79
|
+
program
|
|
80
|
+
.command('dev')
|
|
81
|
+
.description('Start development server with live reload')
|
|
82
|
+
.option('-c, --config <path>', 'path to config file (default: doc-builder.config.js)')
|
|
83
|
+
.option('-p, --port <port>', 'port to run dev server on (default: 3000)')
|
|
84
|
+
.option('-h, --host <host>', 'host to bind to (default: localhost)')
|
|
85
|
+
.option('--no-open', 'don\'t open browser automatically')
|
|
86
|
+
.addHelpText('after', `
|
|
87
|
+
${chalk.yellow('Examples:')}
|
|
88
|
+
${chalk.gray('$')} doc-builder dev ${chalk.gray('# Start on http://localhost:3000')}
|
|
89
|
+
${chalk.gray('$')} doc-builder dev --port 8080 ${chalk.gray('# Use custom port')}
|
|
90
|
+
${chalk.gray('$')} doc-builder dev --host 0.0.0.0 ${chalk.gray('# Allow external connections')}
|
|
91
|
+
`)
|
|
92
|
+
.action(async (options) => {
|
|
93
|
+
try {
|
|
94
|
+
const config = await loadConfig(options.config, options);
|
|
95
|
+
await startDevServer(config, options.port);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error(chalk.red(error.message));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Deploy command
|
|
103
|
+
program
|
|
104
|
+
.command('deploy')
|
|
105
|
+
.description('Deploy documentation to Vercel (requires Vercel CLI)')
|
|
106
|
+
.option('-c, --config <path>', 'path to config file (default: doc-builder.config.js)')
|
|
107
|
+
.option('--prod', 'deploy to production (default: preview deployment)')
|
|
108
|
+
.option('--no-build', 'skip building before deployment')
|
|
109
|
+
.option('--force', 'force deployment without confirmation')
|
|
110
|
+
.addHelpText('after', `
|
|
111
|
+
${chalk.yellow('Examples:')}
|
|
112
|
+
${chalk.gray('$')} doc-builder deploy ${chalk.gray('# Deploy preview to Vercel')}
|
|
113
|
+
${chalk.gray('$')} doc-builder deploy --prod ${chalk.gray('# Deploy to production')}
|
|
114
|
+
${chalk.gray('$')} doc-builder deploy --no-build ${chalk.gray('# Deploy existing build')}
|
|
115
|
+
|
|
116
|
+
${chalk.yellow('First-time setup:')}
|
|
117
|
+
The tool will guide you through:
|
|
118
|
+
1. Installing Vercel CLI (if needed)
|
|
119
|
+
2. Creating a new Vercel project
|
|
120
|
+
3. Configuring deployment settings
|
|
121
|
+
|
|
122
|
+
${chalk.yellow('Important:')} After deployment, disable Vercel Authentication in project settings for public docs.
|
|
123
|
+
`)
|
|
124
|
+
.action(async (options) => {
|
|
125
|
+
const spinner = ora('Deploying to Vercel...').start();
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
const config = await loadConfig(options.config, options);
|
|
129
|
+
|
|
130
|
+
// Check if this is the first deployment
|
|
131
|
+
const vercelConfigPath = path.join(process.cwd(), '.vercel', 'project.json');
|
|
132
|
+
if (!fs.existsSync(vercelConfigPath)) {
|
|
133
|
+
spinner.stop();
|
|
134
|
+
console.log(chalk.yellow('\n🚀 First time deploying to Vercel!\n'));
|
|
135
|
+
|
|
136
|
+
const setupConfirm = await prompts({
|
|
137
|
+
type: 'confirm',
|
|
138
|
+
name: 'value',
|
|
139
|
+
message: 'Would you like to set up a new Vercel project?',
|
|
140
|
+
initial: true
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
if (setupConfirm.value) {
|
|
144
|
+
await setupVercelProject(config);
|
|
145
|
+
} else {
|
|
146
|
+
console.log(chalk.gray('Run `vercel` manually to set up your project.'));
|
|
147
|
+
process.exit(0);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
spinner.start('Deploying to Vercel...');
|
|
152
|
+
const url = await deployToVercel(config, options.prod);
|
|
153
|
+
spinner.succeed(`Deployed successfully! ${chalk.cyan(url)}`);
|
|
154
|
+
|
|
155
|
+
} catch (error) {
|
|
156
|
+
spinner.fail('Deployment failed');
|
|
157
|
+
console.error(chalk.red(error.message));
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Init command
|
|
163
|
+
program
|
|
164
|
+
.command('init')
|
|
165
|
+
.description('Initialize doc-builder in your project')
|
|
166
|
+
.option('--config', 'create configuration file')
|
|
167
|
+
.option('--example', 'create example documentation structure')
|
|
168
|
+
.addHelpText('after', `
|
|
169
|
+
${chalk.yellow('Examples:')}
|
|
170
|
+
${chalk.gray('$')} doc-builder init --config ${chalk.gray('# Create doc-builder.config.js')}
|
|
171
|
+
${chalk.gray('$')} doc-builder init --example ${chalk.gray('# Create example docs folder')}
|
|
172
|
+
`)
|
|
173
|
+
.action(async (options) => {
|
|
174
|
+
if (options.config) {
|
|
175
|
+
const configPath = path.join(process.cwd(), 'doc-builder.config.js');
|
|
176
|
+
|
|
177
|
+
if (fs.existsSync(configPath)) {
|
|
178
|
+
const overwrite = await prompts({
|
|
179
|
+
type: 'confirm',
|
|
180
|
+
name: 'value',
|
|
181
|
+
message: 'Config file already exists. Overwrite?',
|
|
182
|
+
initial: false
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
if (!overwrite.value) {
|
|
186
|
+
console.log(chalk.gray('Cancelled.'));
|
|
187
|
+
process.exit(0);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const config = await createDefaultConfig();
|
|
192
|
+
fs.writeFileSync(configPath, `module.exports = ${JSON.stringify(config, null, 2)};`);
|
|
193
|
+
console.log(chalk.green('✅ Created doc-builder.config.js'));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (options.example) {
|
|
197
|
+
const docsDir = path.join(process.cwd(), 'docs');
|
|
198
|
+
|
|
199
|
+
if (!fs.existsSync(docsDir)) {
|
|
200
|
+
fs.mkdirSync(docsDir, { recursive: true });
|
|
201
|
+
|
|
202
|
+
// Create example files
|
|
203
|
+
const exampleFiles = {
|
|
204
|
+
'README.md': `# Welcome to Your Documentation\n\nThis is an example documentation site created with @knowcode/doc-builder.\n\n## Features\n\n- 📝 Write in Markdown\n- 🎨 Beautiful Notion-inspired design\n- 📊 Mermaid diagram support\n- 🌙 Dark mode\n- 🚀 Deploy to Vercel\n\n## Getting Started\n\n1. Edit this file and add your content\n2. Create new markdown files\n3. Run \`npx @knowcode/doc-builder\` to build and deploy\n\n## Example Diagram\n\n\`\`\`mermaid\ngraph TD\n A[Write Docs] --> B[Build]\n B --> C[Deploy]\n C --> D[Share]\n\`\`\`\n`,
|
|
205
|
+
'getting-started.md': `# Getting Started\n\n**Generated**: ${new Date().toISOString().split('T')[0]}\n**Status**: Draft\n**Verified**: ❓\n\n## Overview\n\nThis guide will help you get started with your documentation.\n\n## Installation\n\nNo installation required! Just use:\n\n\`\`\`bash\nnpx @knowcode/doc-builder\n\`\`\`\n\n## Writing Documentation\n\n1. Create markdown files in the \`docs\` folder\n2. Use folders to organize your content\n3. Add front matter for metadata\n\n## Building\n\nTo build your documentation:\n\n\`\`\`bash\nnpx @knowcode/doc-builder build\n\`\`\`\n\n## Deployment\n\nDeploy to Vercel:\n\n\`\`\`bash\nnpx @knowcode/doc-builder deploy --prod\n\`\`\`\n`,
|
|
206
|
+
'guides/configuration.md': `# Configuration Guide\n\n**Generated**: ${new Date().toISOString().split('T')[0]}\n**Status**: Draft\n**Verified**: ❓\n\n## Overview\n\n@knowcode/doc-builder works with zero configuration, but you can customize it.\n\n## Configuration File\n\nCreate \`doc-builder.config.js\`:\n\n\`\`\`javascript\nmodule.exports = {\n siteName: 'My Documentation',\n siteDescription: 'Documentation for my project',\n \n features: {\n authentication: false,\n changelog: true,\n mermaid: true,\n darkMode: true\n }\n};\n\`\`\`\n\n## Options\n\n### Site Information\n\n- \`siteName\`: Your documentation site name\n- \`siteDescription\`: Brief description\n\n### Directories\n\n- \`docsDir\`: Input directory (default: 'docs')\n- \`outputDir\`: Output directory (default: 'html')\n\n### Features\n\n- \`authentication\`: Enable password protection\n- \`changelog\`: Generate changelog automatically\n- \`mermaid\`: Support for diagrams\n- \`darkMode\`: Dark theme support\n`
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// Create example files
|
|
210
|
+
for (const [filePath, content] of Object.entries(exampleFiles)) {
|
|
211
|
+
const fullPath = path.join(docsDir, filePath);
|
|
212
|
+
const dir = path.dirname(fullPath);
|
|
213
|
+
|
|
214
|
+
if (!fs.existsSync(dir)) {
|
|
215
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
fs.writeFileSync(fullPath, content);
|
|
219
|
+
console.log(chalk.green(`✅ Created ${filePath}`));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
console.log(chalk.cyan('\\n📚 Example documentation created in docs/ folder'));
|
|
223
|
+
console.log(chalk.gray('\\nNext steps:'));
|
|
224
|
+
console.log(chalk.gray('1. Edit the example files to add your content'));
|
|
225
|
+
console.log(chalk.gray('2. Run `npx @knowcode/doc-builder` to build and deploy'));
|
|
226
|
+
} else {
|
|
227
|
+
console.log(chalk.yellow('⚠️ docs/ directory already exists'));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Add a default command handler for when doc-builder is run without arguments
|
|
233
|
+
program
|
|
234
|
+
.action(async () => {
|
|
235
|
+
// Default action is build + deploy
|
|
236
|
+
console.log(chalk.cyan('\n🚀 Building and deploying your documentation...\n'));
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
// Build first
|
|
240
|
+
const config = await loadConfig('doc-builder.config.js', { legacy: true });
|
|
241
|
+
const buildSpinner = ora('Building documentation...').start();
|
|
242
|
+
await build(config);
|
|
243
|
+
buildSpinner.succeed('Documentation built successfully!');
|
|
244
|
+
|
|
245
|
+
// Then deploy
|
|
246
|
+
const deploySpinner = ora('Deploying to Vercel...').start();
|
|
247
|
+
|
|
248
|
+
// Check if this is the first deployment
|
|
249
|
+
const vercelConfigPath = path.join(process.cwd(), '.vercel', 'project.json');
|
|
250
|
+
if (!fs.existsSync(vercelConfigPath)) {
|
|
251
|
+
deploySpinner.stop();
|
|
252
|
+
console.log(chalk.yellow('\n🚀 First time deploying to Vercel!\n'));
|
|
253
|
+
|
|
254
|
+
const setupConfirm = await prompts({
|
|
255
|
+
type: 'confirm',
|
|
256
|
+
name: 'value',
|
|
257
|
+
message: 'Would you like to set up a new Vercel project?',
|
|
258
|
+
initial: true
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
if (setupConfirm.value) {
|
|
262
|
+
await setupVercelProject(config);
|
|
263
|
+
} else {
|
|
264
|
+
console.log(chalk.gray('\nTo deploy manually, run: vercel'));
|
|
265
|
+
console.log(chalk.gray('To skip deployment, run: doc-builder build\n'));
|
|
266
|
+
process.exit(0);
|
|
267
|
+
}
|
|
268
|
+
deploySpinner.start('Deploying to Vercel...');
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const url = await deployToVercel(config, false);
|
|
272
|
+
deploySpinner.succeed(`Deployed successfully! ${chalk.cyan(url)}`);
|
|
273
|
+
|
|
274
|
+
} catch (error) {
|
|
275
|
+
console.error(chalk.red('\nError: ' + error.message));
|
|
276
|
+
console.log(chalk.gray('\nTo build without deploying, run: doc-builder build'));
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Parse arguments
|
|
282
|
+
program.parse(process.argv);
|
package/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @knowcode/doc-builder - Programmatic API
|
|
3
|
+
*
|
|
4
|
+
* This module exports functions for use in scripts or other tools
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { build } = require('./lib/builder');
|
|
8
|
+
const { startDevServer } = require('./lib/dev-server');
|
|
9
|
+
const { deployToVercel, setupVercelProject } = require('./lib/deploy');
|
|
10
|
+
const { loadConfig, createDefaultConfig } = require('./lib/config');
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
// Main functions
|
|
14
|
+
build,
|
|
15
|
+
startDevServer,
|
|
16
|
+
deployToVercel,
|
|
17
|
+
setupVercelProject,
|
|
18
|
+
|
|
19
|
+
// Config utilities
|
|
20
|
+
loadConfig,
|
|
21
|
+
createDefaultConfig,
|
|
22
|
+
|
|
23
|
+
// Convenience wrapper for common operations
|
|
24
|
+
async buildDocs(configPath = 'doc-builder.config.js', options = {}) {
|
|
25
|
+
const config = await loadConfig(configPath, options);
|
|
26
|
+
return build(config);
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
async deploy(configPath = 'doc-builder.config.js', options = {}) {
|
|
30
|
+
const config = await loadConfig(configPath, options);
|
|
31
|
+
return deployToVercel(config, options.prod);
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
async dev(configPath = 'doc-builder.config.js', options = {}) {
|
|
35
|
+
const config = await loadConfig(configPath, options);
|
|
36
|
+
return startDevServer(config, options.port || 3000);
|
|
37
|
+
}
|
|
38
|
+
};
|
package/lib/builder.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Main build function
|
|
7
|
+
* This wraps the existing build.js functionality
|
|
8
|
+
*/
|
|
9
|
+
async function build(config) {
|
|
10
|
+
console.log(chalk.blue(`\n🚀 Building ${config.siteName}...\n`));
|
|
11
|
+
|
|
12
|
+
// Validate config
|
|
13
|
+
if (!config || typeof config !== 'object') {
|
|
14
|
+
throw new Error('Invalid configuration provided to build function');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// For now, we'll use the existing build.js file
|
|
18
|
+
// In a future refactor, we'll move all the logic here
|
|
19
|
+
const buildScriptPath = path.join(__dirname, '../../../html/build.js');
|
|
20
|
+
|
|
21
|
+
if (!fs.existsSync(buildScriptPath)) {
|
|
22
|
+
throw new Error('Build script not found. This package must be run from the cybersolstice project.');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Set environment variables for the build script
|
|
26
|
+
process.env.DOC_BUILDER_CONFIG = JSON.stringify(config);
|
|
27
|
+
|
|
28
|
+
// Import and run the existing build
|
|
29
|
+
const buildModule = require(buildScriptPath);
|
|
30
|
+
|
|
31
|
+
// Run the build - it doesn't take parameters, config is passed via env
|
|
32
|
+
if (typeof buildModule.build === 'function') {
|
|
33
|
+
await buildModule.build();
|
|
34
|
+
} else {
|
|
35
|
+
// If it's not a function, it might be auto-executing
|
|
36
|
+
// Just requiring it should run it
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Copy assets to output directory
|
|
40
|
+
await copyAssets(config);
|
|
41
|
+
|
|
42
|
+
console.log(chalk.green('\n✨ Build complete!\n'));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Copy package assets to output directory
|
|
47
|
+
*/
|
|
48
|
+
async function copyAssets(config) {
|
|
49
|
+
const outputDir = path.join(process.cwd(), config.outputDir);
|
|
50
|
+
const assetsDir = path.join(__dirname, '../assets');
|
|
51
|
+
|
|
52
|
+
// Ensure output directory exists
|
|
53
|
+
await fs.ensureDir(outputDir);
|
|
54
|
+
|
|
55
|
+
// Copy CSS
|
|
56
|
+
const cssSource = path.join(assetsDir, 'css');
|
|
57
|
+
const cssDest = path.join(outputDir, 'css');
|
|
58
|
+
if (fs.existsSync(cssSource)) {
|
|
59
|
+
await fs.copy(cssSource, cssDest, { overwrite: true });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Copy JS
|
|
63
|
+
const jsSource = path.join(assetsDir, 'js');
|
|
64
|
+
const jsDest = path.join(outputDir, 'js');
|
|
65
|
+
if (fs.existsSync(jsSource)) {
|
|
66
|
+
await fs.copy(jsSource, jsDest, { overwrite: true });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Copy auth.js to root
|
|
70
|
+
const authSource = path.join(assetsDir, 'js', 'auth.js');
|
|
71
|
+
const authDest = path.join(outputDir, 'auth.js');
|
|
72
|
+
if (fs.existsSync(authSource)) {
|
|
73
|
+
await fs.copy(authSource, authDest, { overwrite: true });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
build
|
|
79
|
+
};
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Default configuration
|
|
7
|
+
*/
|
|
8
|
+
const defaultConfig = {
|
|
9
|
+
// Source and output directories
|
|
10
|
+
docsDir: 'docs',
|
|
11
|
+
outputDir: 'html',
|
|
12
|
+
|
|
13
|
+
// Site metadata
|
|
14
|
+
siteName: 'Documentation',
|
|
15
|
+
siteDescription: 'Documentation site built with @knowcode/doc-builder',
|
|
16
|
+
|
|
17
|
+
// Features
|
|
18
|
+
features: {
|
|
19
|
+
authentication: false,
|
|
20
|
+
changelog: true,
|
|
21
|
+
mermaid: true,
|
|
22
|
+
tooltips: true,
|
|
23
|
+
search: false,
|
|
24
|
+
darkMode: true
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
// Authentication (if enabled)
|
|
28
|
+
auth: {
|
|
29
|
+
username: 'admin',
|
|
30
|
+
password: 'password'
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// Changelog settings
|
|
34
|
+
changelog: {
|
|
35
|
+
daysBack: 14,
|
|
36
|
+
enabled: true
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
// Navigation configuration
|
|
40
|
+
folderOrder: [],
|
|
41
|
+
folderDescriptions: {},
|
|
42
|
+
folderIcons: {},
|
|
43
|
+
|
|
44
|
+
// Deployment
|
|
45
|
+
deployment: {
|
|
46
|
+
platform: 'vercel',
|
|
47
|
+
outputDirectory: 'html'
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Cybersolstice preset - maintains compatibility with existing project
|
|
53
|
+
*/
|
|
54
|
+
const cybersolsticePreset = {
|
|
55
|
+
docsDir: 'docs',
|
|
56
|
+
outputDir: 'html',
|
|
57
|
+
siteName: 'JUNO Platform', // Keep original for cybersolstice project
|
|
58
|
+
siteDescription: 'Transforming complex sales through intelligent automation',
|
|
59
|
+
|
|
60
|
+
features: {
|
|
61
|
+
authentication: true,
|
|
62
|
+
changelog: true,
|
|
63
|
+
mermaid: true,
|
|
64
|
+
tooltips: true,
|
|
65
|
+
search: false,
|
|
66
|
+
darkMode: true
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
auth: {
|
|
70
|
+
username: 'juno',
|
|
71
|
+
password: 'docs2025'
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
changelog: {
|
|
75
|
+
daysBack: 14,
|
|
76
|
+
enabled: true
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
// Folder descriptions from existing code
|
|
80
|
+
folderDescriptions: {
|
|
81
|
+
'product-roadmap': 'Strategic vision, timeline, and feature planning for the JUNO platform',
|
|
82
|
+
'product-requirements': 'Detailed product specifications, requirements documents, and feature definitions',
|
|
83
|
+
'architecture': 'System design, data flows, and technical infrastructure documentation',
|
|
84
|
+
'system-analysis': 'Comprehensive system analysis, functional requirements, and cross-component documentation',
|
|
85
|
+
'bubble': 'Core application platform - business logic, UI/UX, and user workflows',
|
|
86
|
+
'quickbase': 'Database schema, data management, and backend operations',
|
|
87
|
+
'activecampaign': 'Marketing automation integration and lead management system',
|
|
88
|
+
'juno-signer': 'Document signing service for digital signatures and PDF generation',
|
|
89
|
+
'juno-api-deprecated': 'Legacy API documentation (deprecated, for reference only)',
|
|
90
|
+
'postman': 'API testing tools, collections, and test automation',
|
|
91
|
+
'mcp': 'Model Context Protocol setup and configuration guides',
|
|
92
|
+
'team': 'Team roles, responsibilities, and task assignments',
|
|
93
|
+
'thought-leadership': 'Strategic thinking, industry insights, and future vision',
|
|
94
|
+
'paths': 'Dynamic pathway routing system for insurance applications',
|
|
95
|
+
'testing': 'Testing procedures, checklists, and quality assurance',
|
|
96
|
+
'technical': 'Technical documentation and implementation details',
|
|
97
|
+
'application': 'Application components, data types, and workflows'
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
folderIcons: {
|
|
101
|
+
'root': 'fas fa-home',
|
|
102
|
+
'product-roadmap': 'fas fa-road',
|
|
103
|
+
'product-requirements': 'fas fa-clipboard-list',
|
|
104
|
+
'architecture': 'fas fa-sitemap',
|
|
105
|
+
'system-analysis': 'fas fa-analytics',
|
|
106
|
+
'system': 'fas fa-cogs',
|
|
107
|
+
'bubble': 'fas fa-bubble',
|
|
108
|
+
'quickbase': 'fas fa-database',
|
|
109
|
+
'activecampaign': 'fas fa-envelope',
|
|
110
|
+
'juno-signer': 'fas fa-signature',
|
|
111
|
+
'juno-api-deprecated': 'fas fa-archive',
|
|
112
|
+
'postman': 'fas fa-flask',
|
|
113
|
+
'mcp': 'fas fa-puzzle-piece',
|
|
114
|
+
'team': 'fas fa-users',
|
|
115
|
+
'thought-leadership': 'fas fa-lightbulb',
|
|
116
|
+
'middleware': 'fas fa-layer-group',
|
|
117
|
+
'paths': 'fas fa-route',
|
|
118
|
+
'testing': 'fas fa-vial',
|
|
119
|
+
'juno-api': 'fas fa-plug'
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
folderOrder: [
|
|
123
|
+
'product-roadmap',
|
|
124
|
+
'product-requirements',
|
|
125
|
+
'architecture',
|
|
126
|
+
'system-analysis',
|
|
127
|
+
'bubble',
|
|
128
|
+
'quickbase',
|
|
129
|
+
'activecampaign',
|
|
130
|
+
'juno-signer',
|
|
131
|
+
'juno-api-deprecated',
|
|
132
|
+
'postman',
|
|
133
|
+
'mcp',
|
|
134
|
+
'team',
|
|
135
|
+
'thought-leadership'
|
|
136
|
+
]
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Load configuration
|
|
141
|
+
*/
|
|
142
|
+
async function loadConfig(configPath, options = {}) {
|
|
143
|
+
let config = { ...defaultConfig };
|
|
144
|
+
|
|
145
|
+
// Apply preset if specified
|
|
146
|
+
if (options.preset === 'cybersolstice') {
|
|
147
|
+
config = { ...config, ...cybersolsticePreset };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Load custom config file if it exists
|
|
151
|
+
const customConfigPath = path.join(process.cwd(), configPath);
|
|
152
|
+
if (fs.existsSync(customConfigPath)) {
|
|
153
|
+
try {
|
|
154
|
+
const customConfig = require(customConfigPath);
|
|
155
|
+
config = { ...config, ...customConfig };
|
|
156
|
+
console.log(chalk.gray(`Loaded config from ${configPath}`));
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.warn(chalk.yellow(`Warning: Failed to load config file: ${error.message}`));
|
|
159
|
+
}
|
|
160
|
+
} else if (!options.preset && !options.legacy) {
|
|
161
|
+
console.log(chalk.gray('No config file found, using defaults'));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Apply CLI options (these override config file)
|
|
165
|
+
if (options.input) {
|
|
166
|
+
config.docsDir = options.input;
|
|
167
|
+
}
|
|
168
|
+
if (options.output) {
|
|
169
|
+
config.outputDir = options.output;
|
|
170
|
+
}
|
|
171
|
+
if (options.auth === false) {
|
|
172
|
+
config.features.authentication = false;
|
|
173
|
+
}
|
|
174
|
+
if (options.changelog === false) {
|
|
175
|
+
config.features.changelog = false;
|
|
176
|
+
config.changelog.enabled = false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Legacy mode - auto-detect structure
|
|
180
|
+
if (options.legacy) {
|
|
181
|
+
const docsPath = path.join(process.cwd(), 'docs');
|
|
182
|
+
const htmlPath = path.join(process.cwd(), 'html');
|
|
183
|
+
|
|
184
|
+
if (fs.existsSync(docsPath) && fs.existsSync(htmlPath)) {
|
|
185
|
+
console.log(chalk.gray('Legacy mode: detected docs/ and html/ structure'));
|
|
186
|
+
config.docsDir = 'docs';
|
|
187
|
+
config.outputDir = 'html';
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Validate paths
|
|
192
|
+
const docsPath = path.join(process.cwd(), config.docsDir);
|
|
193
|
+
if (!fs.existsSync(docsPath)) {
|
|
194
|
+
throw new Error(`Documentation directory not found: ${config.docsDir}`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return config;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Create default configuration
|
|
202
|
+
*/
|
|
203
|
+
async function createDefaultConfig() {
|
|
204
|
+
const answers = await require('prompts')([
|
|
205
|
+
{
|
|
206
|
+
type: 'text',
|
|
207
|
+
name: 'siteName',
|
|
208
|
+
message: 'Site name:',
|
|
209
|
+
initial: 'My Documentation'
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
type: 'text',
|
|
213
|
+
name: 'siteDescription',
|
|
214
|
+
message: 'Site description:',
|
|
215
|
+
initial: 'Documentation for my project'
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
type: 'confirm',
|
|
219
|
+
name: 'authentication',
|
|
220
|
+
message: 'Enable authentication?',
|
|
221
|
+
initial: false
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
type: prev => prev ? 'text' : null,
|
|
225
|
+
name: 'authUsername',
|
|
226
|
+
message: 'Authentication username:',
|
|
227
|
+
initial: 'admin'
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
type: prev => prev ? 'password' : null,
|
|
231
|
+
name: 'authPassword',
|
|
232
|
+
message: 'Authentication password:',
|
|
233
|
+
initial: 'password'
|
|
234
|
+
}
|
|
235
|
+
]);
|
|
236
|
+
|
|
237
|
+
const config = { ...defaultConfig };
|
|
238
|
+
config.siteName = answers.siteName;
|
|
239
|
+
config.siteDescription = answers.siteDescription;
|
|
240
|
+
config.features.authentication = answers.authentication;
|
|
241
|
+
|
|
242
|
+
if (answers.authentication) {
|
|
243
|
+
config.auth.username = answers.authUsername;
|
|
244
|
+
config.auth.password = answers.authPassword;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return config;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
module.exports = {
|
|
251
|
+
defaultConfig,
|
|
252
|
+
cybersolsticePreset,
|
|
253
|
+
loadConfig,
|
|
254
|
+
createDefaultConfig
|
|
255
|
+
};
|