@knowcode/doc-builder 1.9.30 → 1.10.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/lib/core-builder.js +164 -174
- package/lib/emoji-mapper.js +27 -12
- package/package.json +12 -2
- package/.claude/settings.local.json +0 -56
- package/CACHE-BUSTING-GUIDE.md +0 -82
- package/CLAUDE.md +0 -86
- package/CONTRIBUTING.md +0 -148
- package/GITHUB_SETUP.md +0 -203
- package/RELEASE-NOTES-1.7.5.md +0 -64
- package/Screenshot 2025-07-22 at 19.51.21.png +0 -0
- package/Screenshot 2025-07-26 at 17.06.49.png +0 -0
- package/add-user-clive.sql +0 -35
- package/add-user-lindsay-fixed.sql +0 -85
- package/add-user-lindsay.sql +0 -68
- package/add-user-pmorgan.sql +0 -35
- package/add-user-robbie.sql +0 -35
- package/add-wru-users.sql +0 -105
- package/debug-login.sql +0 -30
- package/doc-builder.config.js +0 -126
- package/doc-builder.config.js.backup.1753793768283 +0 -47
- package/doc-builder.config.js.backup.1753803964423 +0 -114
- package/doc-builder.config.js.backup.1753945707032 +0 -115
- package/doc-builder.config.js.backup.1754059241330 +0 -115
- package/doc-builder.config.js.backup.1754119567787 +0 -123
- package/doc-builder.config.js.backup.1754120048862 +0 -124
- package/doc-builder.config.js.backup.1754120529913 +0 -124
- package/doc-builder.config.js.backup.1754218469785 +0 -124
- package/doc-builder.config.js.backup.1754384764054 +0 -124
- package/doc-builder.config.js.backup.1754567425847 +0 -124
- package/doc-builder.config.js.backup.1754568137859 +0 -126
- package/doc-builder.config.js.backup.1754569388252 +0 -126
- package/doc-builder.config.js.backup.1754576694123 +0 -126
- package/doc-builder.config.js.backup.1755031374829 +0 -126
- package/doc-builder.config.js.backup.1755034500990 +0 -126
- package/doc-builder.config.js.backup.1755034809236 +0 -126
- package/grant-access.sql +0 -15
- package/html/11.png +0 -0
- package/html/404.html +0 -115
- package/html/README.html +0 -522
- package/html/Screenshot 2025-08-12 at 21.35.07.png +0 -0
- package/html/about-doc-builder.html +0 -491
- package/html/auth.js +0 -157
- package/html/claude-workflow-guide.html +0 -525
- package/html/css/notion-style.css +0 -2502
- package/html/documentation-index.html +0 -471
- package/html/guides/authentication-default-change.html +0 -370
- package/html/guides/authentication-guide.html +0 -509
- package/html/guides/cache-control-anti-pattern.html +0 -361
- package/html/guides/claude-workflow-guide.html +0 -1074
- package/html/guides/configuration-guide.html +0 -472
- package/html/guides/document-standards.html +0 -518
- package/html/guides/documentation-standards.html +0 -694
- package/html/guides/html-embedding-guide.html +0 -461
- package/html/guides/image-modal-guide.html +0 -515
- package/html/guides/next-steps-walkthrough.html +0 -638
- package/html/guides/phosphor-icons-guide.html +0 -584
- package/html/guides/private-directory-authentication-troubleshooting.html +0 -555
- package/html/guides/private-directory-authentication.html +0 -541
- package/html/guides/public-site-deployment.html +0 -431
- package/html/guides/search-engine-verification-guide.html +0 -542
- package/html/guides/seo-guide.html +0 -661
- package/html/guides/seo-optimization-guide.html +0 -887
- package/html/guides/supabase-auth-implementation-plan.html +0 -543
- package/html/guides/supabase-auth-integration-plan.html +0 -671
- package/html/guides/supabase-auth-setup-guide.html +0 -498
- package/html/guides/supabase-authentication-complete-guide.html +0 -866
- package/html/guides/troubleshooting-guide.html +0 -633
- package/html/guides/vercel-deployment-auth-setup.html +0 -337
- package/html/guides/windows-setup-guide.html +0 -859
- package/html/image-modal-test.html +0 -318
- package/html/index.html +0 -522
- package/html/js/auth.js +0 -157
- package/html/js/main.js +0 -1754
- package/html/launch/README.html +0 -297
- package/html/launch/bubble-plugin-specification.html +0 -933
- package/html/launch/go-to-market-strategy.html +0 -663
- package/html/launch/launch-announcements.html +0 -593
- package/html/login.html +0 -102
- package/html/logout.html +0 -18
- package/html/private/cache-control-anti-pattern.html +0 -429
- package/html/private/launch/README.html +0 -371
- package/html/private/launch/auth-cleanup-summary.html +0 -361
- package/html/private/launch/bubble-plugin-specification.html +0 -1007
- package/html/private/launch/go-to-market-strategy.html +0 -737
- package/html/private/launch/launch-announcements.html +0 -667
- package/html/private/launch/vercel-deployment-auth-setup.html +0 -417
- package/html/private/next-steps-walkthrough.html +0 -679
- package/html/private/supabase-auth-implementation-completed.html +0 -454
- package/html/private/supabase-auth-implementation-plan.html +0 -594
- package/html/private/supabase-auth-integration-plan.html +0 -704
- package/html/private/supabase-auth-setup-guide.html +0 -555
- package/html/private/test-private-doc.html +0 -302
- package/html/private/user-management-tooling.html +0 -601
- package/html/prompts/Screenshot 2025-08-02 at 08.49.55.png +0 -0
- package/html/prompts/beautiful-documentation-design.html +0 -784
- package/html/prompts/markdown-document-standards.html +0 -422
- package/html/prompts/project-rename-strategy-sasha-publish.html +0 -530
- package/html/robots.txt +0 -9
- package/html/sitemap.xml +0 -357
- package/html/test-questions/how-does-it-work%3F.html +0 -294
- package/html/test-questions/step-1%3A%20getting-started.html +0 -289
- package/html/test-questions/what-is-the-purpose.html +0 -293
- package/html/test-status.html +0 -281
- package/html/vercel-cli-setup-guide.html +0 -495
- package/html/vercel-first-time-setup-guide.html +0 -454
- package/html/vercel.json +0 -29
- package/html-static/11.png +0 -0
- package/html-static/404.html +0 -115
- package/html-static/README.html +0 -609
- package/html-static/Screenshot 2025-08-12 at 21.35.07.png +0 -0
- package/html-static/about-doc-builder.html +0 -578
- package/html-static/css/notion-style.css +0 -2502
- package/html-static/documentation-index.html +0 -558
- package/html-static/guides/authentication-default-change.html +0 -457
- package/html-static/guides/authentication-guide.html +0 -596
- package/html-static/guides/claude-workflow-guide.html +0 -1161
- package/html-static/guides/configuration-guide.html +0 -559
- package/html-static/guides/documentation-standards.html +0 -781
- package/html-static/guides/html-embedding-guide.html +0 -548
- package/html-static/guides/image-modal-guide.html +0 -602
- package/html-static/guides/phosphor-icons-guide.html +0 -671
- package/html-static/guides/private-directory-authentication-troubleshooting.html +0 -642
- package/html-static/guides/private-directory-authentication.html +0 -628
- package/html-static/guides/public-site-deployment.html +0 -518
- package/html-static/guides/search-engine-verification-guide.html +0 -629
- package/html-static/guides/seo-guide.html +0 -748
- package/html-static/guides/seo-optimization-guide.html +0 -974
- package/html-static/guides/supabase-authentication-complete-guide.html +0 -953
- package/html-static/guides/troubleshooting-guide.html +0 -720
- package/html-static/guides/windows-setup-guide.html +0 -946
- package/html-static/image-modal-test.html +0 -405
- package/html-static/index.html +0 -609
- package/html-static/js/main.js +0 -1754
- package/html-static/prompts/Screenshot 2025-08-02 at 08.49.55.png +0 -0
- package/html-static/prompts/beautiful-documentation-design.html +0 -871
- package/html-static/prompts/markdown-document-standards.html +0 -509
- package/html-static/prompts/project-rename-strategy-sasha-publish.html +0 -617
- package/html-static/robots.txt +0 -5
- package/html-static/sitemap.xml +0 -195
- package/html-static/test-questions/how-does-it-work%3F.html +0 -381
- package/html-static/test-questions/step-1%3A%20getting-started.html +0 -376
- package/html-static/test-questions/what-is-the-purpose.html +0 -380
- package/html-static/vercel-cli-setup-guide.html +0 -582
- package/html-static/vercel-first-time-setup-guide.html +0 -541
- package/manage-users.sql +0 -191
- package/migrate-to-domain-auth.sql +0 -47
- package/package/CACHE-BUSTING-GUIDE.md +0 -82
- package/package/CHANGELOG.md +0 -902
- package/package/README.md +0 -248
- package/package/assets/css/notion-style.css +0 -2211
- package/package/assets/js/auth.js +0 -67
- package/package/assets/js/main.js +0 -1565
- package/package/cli.js +0 -764
- package/package/index.js +0 -38
- package/package/knowcode-doc-builder-1.3.15.tgz +0 -0
- package/package/lib/builder.js +0 -32
- package/package/lib/config.js +0 -278
- package/package/lib/core-builder.js +0 -957
- package/package/lib/deploy.js +0 -497
- package/package/lib/dev-server.js +0 -96
- package/package/package.json +0 -34
- package/package/scripts/npx-runner.js +0 -27
- package/package/scripts/setup.js +0 -56
- package/package/test-cache-bust.sh +0 -43
- package/public-config.js +0 -22
- package/public-html/404.html +0 -115
- package/public-html/README.html +0 -149
- package/public-html/css/notion-style.css +0 -2036
- package/public-html/index.html +0 -149
- package/public-html/js/auth.js +0 -67
- package/public-html/js/main.js +0 -1485
- package/quick-test-commands.md +0 -40
- package/recordings/Screenshot 2025-07-24 at 18.22.01.png +0 -0
- package/recordings/mh-ls-22jul.txt +0 -2305
- package/screenshot.png +0 -0
- package/scripts/Screenshot 2025-07-23 at 15.39.41.png +0 -0
- package/setup-database-v2.sql +0 -53
- package/setup-database.sql +0 -41
- package/test-auth-config.js +0 -17
- package/test-cache-bust.sh +0 -43
- package/test-docs/README.md +0 -39
- package/test-html/404.html +0 -115
- package/test-html/README.html +0 -172
- package/test-html/auth.js +0 -97
- package/test-html/css/notion-style.css +0 -2036
- package/test-html/index.html +0 -172
- package/test-html/js/auth.js +0 -97
- package/test-html/js/main.js +0 -1485
- package/test-html/login.html +0 -102
- package/test-html/logout.html +0 -18
- package/update-domain.sql +0 -9
- package/user-access-view.sql +0 -49
- package/user-management/README.md +0 -301
- package/user-management/add-users.sh +0 -776
- package/user-management/create-user.js +0 -65
- package/user-management/users.txt +0 -15
- package/view-all-users.sql +0 -40
- package/wru-auth-config.js +0 -17
|
@@ -1,957 +0,0 @@
|
|
|
1
|
-
const fs = require('fs-extra');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const marked = require('marked');
|
|
4
|
-
const chalk = require('chalk');
|
|
5
|
-
|
|
6
|
-
// Configure marked options
|
|
7
|
-
marked.setOptions({
|
|
8
|
-
highlight: function(code, lang) {
|
|
9
|
-
return `<code class="language-${lang}">${escapeHtml(code)}</code>`;
|
|
10
|
-
},
|
|
11
|
-
breaks: true,
|
|
12
|
-
gfm: true
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
// Helper function to escape HTML
|
|
16
|
-
function escapeHtml(text) {
|
|
17
|
-
const map = {
|
|
18
|
-
'&': '&',
|
|
19
|
-
'<': '<',
|
|
20
|
-
'>': '>',
|
|
21
|
-
'"': '"',
|
|
22
|
-
"'": '''
|
|
23
|
-
};
|
|
24
|
-
return text.replace(/[&<>"']/g, m => map[m]);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Process markdown content
|
|
28
|
-
function processMarkdownContent(content) {
|
|
29
|
-
// Convert mermaid code blocks to mermaid divs with titles
|
|
30
|
-
content = content.replace(/```mermaid\n([\s\S]*?)```/g, (match, mermaidContent) => {
|
|
31
|
-
// Try to extract title from mermaid content
|
|
32
|
-
let title = 'Diagram';
|
|
33
|
-
|
|
34
|
-
// Look for title in various mermaid formats
|
|
35
|
-
const titlePatterns = [
|
|
36
|
-
/title\s+([^\n]+)/i, // gantt charts: title My Title
|
|
37
|
-
/graph\s+\w+\[["']([^"']+)["']\]/, // graph TD["My Title"]
|
|
38
|
-
/flowchart\s+\w+\[["']([^"']+)["']\]/, // flowchart TD["My Title"]
|
|
39
|
-
/---\s*title:\s*([^\n]+)\s*---/, // frontmatter style
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
for (const pattern of titlePatterns) {
|
|
43
|
-
const match = mermaidContent.match(pattern);
|
|
44
|
-
if (match) {
|
|
45
|
-
title = match[1].trim();
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return `<div class="mermaid-wrapper">
|
|
51
|
-
<div class="mermaid-title">${escapeHtml(title)}</div>
|
|
52
|
-
<div class="mermaid">${escapeHtml(mermaidContent)}</div>
|
|
53
|
-
</div>`;
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
return marked.parse(content);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Generate HTML from template
|
|
60
|
-
function generateHTML(title, content, navigation, currentPath = '', config = {}) {
|
|
61
|
-
const depth = currentPath.split('/').filter(p => p).length;
|
|
62
|
-
const relativePath = depth > 0 ? '../'.repeat(depth) : '';
|
|
63
|
-
|
|
64
|
-
const siteName = config.siteName || 'Documentation';
|
|
65
|
-
const siteDescription = config.siteDescription || 'Documentation site';
|
|
66
|
-
|
|
67
|
-
return `<!DOCTYPE html>
|
|
68
|
-
<html lang="en">
|
|
69
|
-
<head>
|
|
70
|
-
<meta charset="UTF-8">
|
|
71
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
72
|
-
<meta name="description" content="${siteDescription}">
|
|
73
|
-
<title>${title} - ${siteName}</title>
|
|
74
|
-
|
|
75
|
-
<!-- Fonts -->
|
|
76
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
77
|
-
|
|
78
|
-
<!-- Icons -->
|
|
79
|
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
|
80
|
-
|
|
81
|
-
<!-- Mermaid -->
|
|
82
|
-
<script src="https://cdn.jsdelivr.net/npm/mermaid@10.6.1/dist/mermaid.min.js"></script>
|
|
83
|
-
|
|
84
|
-
<!-- Styles -->
|
|
85
|
-
<link rel="stylesheet" href="/css/notion-style.css">
|
|
86
|
-
<link rel="stylesheet" href="/css/style.css">
|
|
87
|
-
|
|
88
|
-
<!-- Favicon -->
|
|
89
|
-
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📚</text></svg>">
|
|
90
|
-
</head>
|
|
91
|
-
<body>
|
|
92
|
-
<!-- Header -->
|
|
93
|
-
<header class="header">
|
|
94
|
-
<div class="header-content">
|
|
95
|
-
<a href="/index.html" class="logo">${siteName}</a>
|
|
96
|
-
|
|
97
|
-
<div class="header-actions">
|
|
98
|
-
<div class="deployment-info">
|
|
99
|
-
<span class="deployment-date">Last updated: ${new Date().toLocaleDateString('en-US', {
|
|
100
|
-
year: 'numeric',
|
|
101
|
-
month: 'short',
|
|
102
|
-
day: 'numeric',
|
|
103
|
-
hour: '2-digit',
|
|
104
|
-
minute: '2-digit',
|
|
105
|
-
timeZone: 'UTC'
|
|
106
|
-
})} UTC</span>
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
|
-
${config.features?.authentication ? `
|
|
110
|
-
<a href="${relativePath}logout.html" class="logout-btn" title="Logout">
|
|
111
|
-
<i class="fas fa-sign-out-alt"></i>
|
|
112
|
-
</a>
|
|
113
|
-
` : ''}
|
|
114
|
-
|
|
115
|
-
<button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme">
|
|
116
|
-
<i class="fas fa-moon"></i>
|
|
117
|
-
</button>
|
|
118
|
-
|
|
119
|
-
<button id="menu-toggle" class="menu-toggle" aria-label="Toggle menu">
|
|
120
|
-
<i class="fas fa-bars"></i>
|
|
121
|
-
</button>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
</header>
|
|
125
|
-
|
|
126
|
-
<!-- Preview Banner -->
|
|
127
|
-
<div id="preview-banner" class="preview-banner">
|
|
128
|
-
<div class="banner-content">
|
|
129
|
-
<i class="fas fa-exclamation-triangle banner-icon"></i>
|
|
130
|
-
<span class="banner-text">This documentation is a preview version - some content may be incomplete</span>
|
|
131
|
-
<button id="dismiss-banner" class="banner-dismiss" aria-label="Dismiss banner">
|
|
132
|
-
<i class="fas fa-times"></i>
|
|
133
|
-
</button>
|
|
134
|
-
</div>
|
|
135
|
-
</div>
|
|
136
|
-
|
|
137
|
-
<!-- Breadcrumbs -->
|
|
138
|
-
<nav class="breadcrumbs" id="breadcrumbs">
|
|
139
|
-
<!-- Breadcrumbs will be generated by JavaScript -->
|
|
140
|
-
</nav>
|
|
141
|
-
|
|
142
|
-
<!-- Main Content -->
|
|
143
|
-
<div class="main-wrapper">
|
|
144
|
-
<!-- Sidebar -->
|
|
145
|
-
<aside class="sidebar">
|
|
146
|
-
<div class="sidebar-header">
|
|
147
|
-
<div class="sidebar-breadcrumbs">
|
|
148
|
-
<a href="/index.html" class="sidebar-home-link">
|
|
149
|
-
<i class="fas fa-home"></i>
|
|
150
|
-
<span>Home</span>
|
|
151
|
-
</a>
|
|
152
|
-
</div>
|
|
153
|
-
<div class="filter-box">
|
|
154
|
-
<input type="text" placeholder="Filter items..." class="filter-input" id="nav-filter">
|
|
155
|
-
<i class="fas fa-search filter-icon"></i>
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
<nav class="navigation">
|
|
159
|
-
${navigation}
|
|
160
|
-
</nav>
|
|
161
|
-
<div class="resize-handle"></div>
|
|
162
|
-
</aside>
|
|
163
|
-
|
|
164
|
-
<!-- Content Area -->
|
|
165
|
-
<main class="content">
|
|
166
|
-
<div class="content-inner">
|
|
167
|
-
${content}
|
|
168
|
-
</div>
|
|
169
|
-
</main>
|
|
170
|
-
</div>
|
|
171
|
-
|
|
172
|
-
<!-- Scripts -->
|
|
173
|
-
<script src="/js/main.js"></script>
|
|
174
|
-
${config.features?.authentication ? `<script src="/js/auth.js"></script>` : ''}
|
|
175
|
-
</body>
|
|
176
|
-
</html>`;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Define folder descriptions for tooltips
|
|
180
|
-
const folderDescriptions = {
|
|
181
|
-
'product-roadmap': 'Strategic vision, timeline, and feature planning',
|
|
182
|
-
'product-requirements': 'Detailed product specifications, requirements documents, and feature definitions',
|
|
183
|
-
'architecture': 'System design, data flows, and technical infrastructure documentation',
|
|
184
|
-
'system-analysis': 'Comprehensive system analysis, functional requirements, and cross-component documentation',
|
|
185
|
-
'bubble': 'Core application platform - business logic, UI/UX, and user workflows',
|
|
186
|
-
'quickbase': 'Database schema, data management, and backend operations',
|
|
187
|
-
'activecampaign': 'Marketing automation integration and lead management system',
|
|
188
|
-
'doc-signer': 'Document signing service for digital signatures and PDF generation',
|
|
189
|
-
'api-deprecated': 'Legacy API documentation (deprecated, for reference only)',
|
|
190
|
-
'postman': 'API testing tools, collections, and test automation',
|
|
191
|
-
'mcp': 'Model Context Protocol integration and configuration',
|
|
192
|
-
'team': 'Team structure, roles, and responsibilities',
|
|
193
|
-
'thought-leadership': 'Strategic insights and industry perspectives',
|
|
194
|
-
'middleware': 'Integration layers and data transformation services',
|
|
195
|
-
'paths': 'User journey flows and process workflows',
|
|
196
|
-
'testing': 'Test strategies, scenarios, and quality assurance processes',
|
|
197
|
-
'api': 'API documentation and integration guides'
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
// Build navigation structure with rich functionality
|
|
201
|
-
function buildNavigationStructure(files, currentFile) {
|
|
202
|
-
const tree = { files: [], folders: {} };
|
|
203
|
-
|
|
204
|
-
files.forEach(file => {
|
|
205
|
-
const parts = file.urlPath.split('/');
|
|
206
|
-
let current = tree;
|
|
207
|
-
|
|
208
|
-
// Navigate/create folder structure
|
|
209
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
210
|
-
const folder = parts[i];
|
|
211
|
-
if (!current.folders[folder]) {
|
|
212
|
-
current.folders[folder] = { files: [], folders: {} };
|
|
213
|
-
}
|
|
214
|
-
current = current.folders[folder];
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Add file to current folder
|
|
218
|
-
current.files.push(file);
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
// Helper function to check if a node has active child
|
|
222
|
-
const checkActiveChild = (node, currentFile) => {
|
|
223
|
-
// Check files
|
|
224
|
-
if (node.files.some(f => f.urlPath === currentFile)) return true;
|
|
225
|
-
|
|
226
|
-
// Check folders recursively
|
|
227
|
-
return Object.values(node.folders).some(folder => checkActiveChild(folder, currentFile));
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
// Helper function to generate file title
|
|
231
|
-
const generateFileTitle = (file, parentDisplayName, level) => {
|
|
232
|
-
let title = file.displayName;
|
|
233
|
-
|
|
234
|
-
if (file.displayName === 'README') {
|
|
235
|
-
return level === 0 ? 'Overview' : `${parentDisplayName} Overview`;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Clean up title by removing common prefixes and improving formatting
|
|
239
|
-
title = title
|
|
240
|
-
.replace(/^(bubble|system|quickbase|middleware|product-roadmap)-?/, '')
|
|
241
|
-
.replace(/-/g, ' ')
|
|
242
|
-
.replace(/\b\w/g, l => l.toUpperCase());
|
|
243
|
-
|
|
244
|
-
return title;
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
// Helper function to render a section
|
|
248
|
-
const renderSection = (folderName, folderData, level = 0, parentPath = '') => {
|
|
249
|
-
const icons = {
|
|
250
|
-
'root': 'fas fa-home',
|
|
251
|
-
'product-roadmap': 'fas fa-road',
|
|
252
|
-
'product-requirements': 'fas fa-clipboard-list',
|
|
253
|
-
'architecture': 'fas fa-sitemap',
|
|
254
|
-
'system-analysis': 'fas fa-chart-line',
|
|
255
|
-
'system': 'fas fa-cogs',
|
|
256
|
-
'bubble': 'fas fa-circle',
|
|
257
|
-
'quickbase': 'fas fa-database',
|
|
258
|
-
'activecampaign': 'fas fa-envelope',
|
|
259
|
-
'doc-signer': 'fas fa-signature',
|
|
260
|
-
'api-deprecated': 'fas fa-archive',
|
|
261
|
-
'postman': 'fas fa-flask',
|
|
262
|
-
'mcp': 'fas fa-puzzle-piece',
|
|
263
|
-
'team': 'fas fa-users',
|
|
264
|
-
'thought-leadership': 'fas fa-lightbulb',
|
|
265
|
-
'middleware': 'fas fa-layer-group',
|
|
266
|
-
'paths': 'fas fa-route',
|
|
267
|
-
'testing': 'fas fa-vial',
|
|
268
|
-
'api': 'fas fa-plug',
|
|
269
|
-
'documentation-tool': 'fas fa-tools'
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
const displayName = folderName === 'root' ? 'Documentation' :
|
|
273
|
-
folderName.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
|
|
274
|
-
const icon = icons[folderName] || 'fas fa-folder';
|
|
275
|
-
|
|
276
|
-
if (!folderData.files.length && !Object.keys(folderData.folders).length) {
|
|
277
|
-
return '';
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// Include parent path in section ID to make it unique
|
|
281
|
-
const pathParts = parentPath ? [parentPath, folderName].join('-') : folderName;
|
|
282
|
-
const sectionId = `nav-${pathParts}-${level}`;
|
|
283
|
-
const isCollapsible = level > 0 || folderName !== 'root';
|
|
284
|
-
const collapseIcon = isCollapsible ? '<i class="fas fa-chevron-right collapse-icon"></i>' : '';
|
|
285
|
-
|
|
286
|
-
// Check if this folder has a README.md file to link to
|
|
287
|
-
const readmeFile = folderData.files.find(f => f.displayName === 'README');
|
|
288
|
-
const folderLink = readmeFile ? `href="/${readmeFile.urlPath}"` : 'href="#"';
|
|
289
|
-
|
|
290
|
-
// Get folder description for tooltip
|
|
291
|
-
const folderDescription = folderDescriptions[folderName] || '';
|
|
292
|
-
const tooltipAttr = folderDescription ? `data-tooltip="${escapeHtml(folderDescription)}"` : '';
|
|
293
|
-
|
|
294
|
-
// Start all sections collapsed by default (JavaScript will expand sections containing active items)
|
|
295
|
-
const hasActiveChild = checkActiveChild(folderData, currentFile);
|
|
296
|
-
|
|
297
|
-
let html = `
|
|
298
|
-
<div class="nav-section" data-level="${level}">
|
|
299
|
-
<a class="nav-title${isCollapsible ? ' collapsible' : ''}${hasActiveChild ? ' expanded' : ''}" ${folderLink} ${isCollapsible ? `data-target="${sectionId}"` : ''} ${tooltipAttr}>
|
|
300
|
-
${collapseIcon}<i class="${icon}"></i> ${displayName}
|
|
301
|
-
</a>
|
|
302
|
-
<div class="nav-content${isCollapsible ? (hasActiveChild ? '' : ' collapsed') : ''}" ${isCollapsible ? `id="${sectionId}"` : ''}>`;
|
|
303
|
-
|
|
304
|
-
// Sort and render files
|
|
305
|
-
const sortedFiles = [...folderData.files].sort((a, b) => {
|
|
306
|
-
if (a.displayName === 'README') return -1;
|
|
307
|
-
if (b.displayName === 'README') return 1;
|
|
308
|
-
return a.displayName.localeCompare(b.displayName);
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
sortedFiles.forEach(file => {
|
|
312
|
-
const title = generateFileTitle(file, displayName, level);
|
|
313
|
-
|
|
314
|
-
// Check if this file is active
|
|
315
|
-
let isActive = '';
|
|
316
|
-
if (currentFile === file.urlPath) {
|
|
317
|
-
isActive = ' active';
|
|
318
|
-
} else if (currentFile === 'index.html' && file.displayName === 'README' && folderName === 'root') {
|
|
319
|
-
// Mark root README as active when viewing index.html
|
|
320
|
-
isActive = ' active';
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
const linkPath = '/' + file.urlPath;
|
|
324
|
-
|
|
325
|
-
html += `
|
|
326
|
-
<a href="${linkPath}" class="nav-item${isActive}"><i class="fas fa-file-alt"></i> ${title}</a>`;
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
html += `</div></div>`;
|
|
330
|
-
|
|
331
|
-
// Render subfolders AFTER closing the parent section
|
|
332
|
-
Object.keys(folderData.folders)
|
|
333
|
-
.sort()
|
|
334
|
-
.forEach(subFolder => {
|
|
335
|
-
// Build the path for the subfolder including current folder
|
|
336
|
-
const currentPath = parentPath ? `${parentPath}-${folderName}` : folderName;
|
|
337
|
-
html += renderSection(subFolder, folderData.folders[subFolder], level + 1, currentPath);
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
return html;
|
|
341
|
-
};
|
|
342
|
-
|
|
343
|
-
// Check if this is a flat structure
|
|
344
|
-
const hasFolders = Object.keys(tree.folders).length > 0;
|
|
345
|
-
|
|
346
|
-
if (!hasFolders) {
|
|
347
|
-
// Generate simple flat navigation for all files in root
|
|
348
|
-
return renderSection('root', { files: tree.files, folders: {} }, 0);
|
|
349
|
-
} else {
|
|
350
|
-
// Generate hierarchical navigation
|
|
351
|
-
let nav = '';
|
|
352
|
-
|
|
353
|
-
// Render root files first
|
|
354
|
-
if (tree.files.length > 0) {
|
|
355
|
-
nav += renderSection('root', { files: tree.files, folders: {} }, 0);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// Add other top-level folders in logical order
|
|
359
|
-
const folderOrder = [
|
|
360
|
-
'product-roadmap',
|
|
361
|
-
'product-requirements',
|
|
362
|
-
'architecture',
|
|
363
|
-
'system-analysis',
|
|
364
|
-
'bubble',
|
|
365
|
-
'quickbase',
|
|
366
|
-
'activecampaign',
|
|
367
|
-
'doc-signer',
|
|
368
|
-
'api-deprecated',
|
|
369
|
-
'postman',
|
|
370
|
-
'mcp',
|
|
371
|
-
'team',
|
|
372
|
-
'thought-leadership',
|
|
373
|
-
'documentation-tool'
|
|
374
|
-
];
|
|
375
|
-
|
|
376
|
-
folderOrder.forEach(folderName => {
|
|
377
|
-
if (tree.folders[folderName]) {
|
|
378
|
-
nav += renderSection(folderName, tree.folders[folderName], 1);
|
|
379
|
-
delete tree.folders[folderName]; // Remove so we don't render it again
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
// Render any remaining folders not in the predefined order
|
|
384
|
-
Object.keys(tree.folders)
|
|
385
|
-
.sort()
|
|
386
|
-
.forEach(folderName => {
|
|
387
|
-
nav += renderSection(folderName, tree.folders[folderName], 1);
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
return nav;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// Process single markdown file
|
|
395
|
-
async function processMarkdownFile(filePath, outputPath, allFiles, config) {
|
|
396
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
397
|
-
const fileName = path.basename(filePath, '.md');
|
|
398
|
-
const relativePath = path.relative(config.docsDir, filePath);
|
|
399
|
-
const urlPath = relativePath.replace(/\.md$/, '.html').replace(/\\/g, '/');
|
|
400
|
-
|
|
401
|
-
// Extract title from content
|
|
402
|
-
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
403
|
-
const title = titleMatch ? titleMatch[1] : fileName;
|
|
404
|
-
|
|
405
|
-
// Process content
|
|
406
|
-
const htmlContent = processMarkdownContent(content);
|
|
407
|
-
|
|
408
|
-
// Build navigation
|
|
409
|
-
const navigation = buildNavigationStructure(allFiles, urlPath);
|
|
410
|
-
|
|
411
|
-
// Generate full HTML
|
|
412
|
-
const html = generateHTML(title, htmlContent, navigation, urlPath, config);
|
|
413
|
-
|
|
414
|
-
// Write file
|
|
415
|
-
await fs.ensureDir(path.dirname(outputPath));
|
|
416
|
-
await fs.writeFile(outputPath, html);
|
|
417
|
-
|
|
418
|
-
return { title, urlPath };
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// Get all markdown files
|
|
422
|
-
async function getAllMarkdownFiles(dir, baseDir = dir) {
|
|
423
|
-
const files = [];
|
|
424
|
-
const items = await fs.readdir(dir);
|
|
425
|
-
|
|
426
|
-
for (const item of items) {
|
|
427
|
-
const fullPath = path.join(dir, item);
|
|
428
|
-
const stat = await fs.stat(fullPath);
|
|
429
|
-
|
|
430
|
-
if (stat.isDirectory() && !item.startsWith('.')) {
|
|
431
|
-
const subFiles = await getAllMarkdownFiles(fullPath, baseDir);
|
|
432
|
-
files.push(...subFiles);
|
|
433
|
-
} else if (item.endsWith('.md')) {
|
|
434
|
-
const relativePath = path.relative(baseDir, fullPath);
|
|
435
|
-
const urlPath = relativePath.replace(/\.md$/, '.html').replace(/\\/g, '/');
|
|
436
|
-
const displayName = path.basename(item, '.md')
|
|
437
|
-
.replace(/[-_]/g, ' ')
|
|
438
|
-
.replace(/\b\w/g, l => l.toUpperCase());
|
|
439
|
-
|
|
440
|
-
files.push({
|
|
441
|
-
path: fullPath,
|
|
442
|
-
relativePath,
|
|
443
|
-
urlPath,
|
|
444
|
-
displayName
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
return files;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// Main build function
|
|
453
|
-
async function buildDocumentation(config) {
|
|
454
|
-
const docsDir = path.join(process.cwd(), config.docsDir);
|
|
455
|
-
const outputDir = path.join(process.cwd(), config.outputDir);
|
|
456
|
-
|
|
457
|
-
// Log version for debugging
|
|
458
|
-
const packageJson = require('../package.json');
|
|
459
|
-
console.log(chalk.blue(`📦 Using @knowcode/doc-builder v${packageJson.version}`));
|
|
460
|
-
|
|
461
|
-
// Check and create placeholder README.md if missing
|
|
462
|
-
console.log(chalk.blue('📋 Checking documentation structure...'));
|
|
463
|
-
const readmeGenerated = await createPlaceholderReadme(docsDir, config);
|
|
464
|
-
|
|
465
|
-
console.log(chalk.blue('📄 Scanning for markdown files...'));
|
|
466
|
-
const files = await getAllMarkdownFiles(docsDir);
|
|
467
|
-
console.log(chalk.green(`✅ Found ${files.length} markdown files${readmeGenerated ? ' (including auto-generated README)' : ''}`));
|
|
468
|
-
|
|
469
|
-
// Log the files found
|
|
470
|
-
if (files.length > 0) {
|
|
471
|
-
console.log(chalk.gray(' Found files:'));
|
|
472
|
-
files.forEach(file => {
|
|
473
|
-
console.log(chalk.gray(` - ${file.relativePath} → ${file.urlPath}`));
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
console.log(chalk.blue('📝 Processing files...'));
|
|
478
|
-
for (const file of files) {
|
|
479
|
-
const outputPath = path.join(outputDir, file.urlPath);
|
|
480
|
-
await processMarkdownFile(file.path, outputPath, files, config);
|
|
481
|
-
console.log(chalk.green(`✅ Generated: ${outputPath}`));
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// Copy assets
|
|
485
|
-
const assetsDir = path.join(__dirname, '../assets');
|
|
486
|
-
const cssSource = path.join(assetsDir, 'css');
|
|
487
|
-
const jsSource = path.join(assetsDir, 'js');
|
|
488
|
-
|
|
489
|
-
if (fs.existsSync(cssSource)) {
|
|
490
|
-
await fs.copy(cssSource, path.join(outputDir, 'css'), { overwrite: true });
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
if (fs.existsSync(jsSource)) {
|
|
494
|
-
await fs.copy(jsSource, path.join(outputDir, 'js'), { overwrite: true });
|
|
495
|
-
|
|
496
|
-
// Copy auth.js to root if authentication is enabled
|
|
497
|
-
if (config.features?.authentication) {
|
|
498
|
-
const authSource = path.join(jsSource, 'auth.js');
|
|
499
|
-
const authDest = path.join(outputDir, 'auth.js');
|
|
500
|
-
if (fs.existsSync(authSource)) {
|
|
501
|
-
await fs.copy(authSource, authDest, { overwrite: true });
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// Create auth pages if needed
|
|
507
|
-
if (config.features?.authentication) {
|
|
508
|
-
await createAuthPages(outputDir, config);
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
// Create index.html from index.html, README.html, or generate default
|
|
512
|
-
const indexPath = path.join(outputDir, 'index.html');
|
|
513
|
-
const indexSourcePath = path.join(outputDir, 'index.html'); // from index.md
|
|
514
|
-
const readmePath = path.join(outputDir, 'README.html');
|
|
515
|
-
|
|
516
|
-
console.log(chalk.blue('\n📄 Checking for index.html creation...'));
|
|
517
|
-
console.log(chalk.gray(` - Output directory: ${outputDir}`));
|
|
518
|
-
console.log(chalk.gray(` - Index path: ${indexPath}`));
|
|
519
|
-
console.log(chalk.gray(` - README path: ${readmePath}`));
|
|
520
|
-
console.log(chalk.gray(` - index.html exists: ${fs.existsSync(indexPath)}`));
|
|
521
|
-
console.log(chalk.gray(` - README.html exists: ${fs.existsSync(readmePath)}`));
|
|
522
|
-
|
|
523
|
-
// List all HTML files in output directory
|
|
524
|
-
if (fs.existsSync(outputDir)) {
|
|
525
|
-
const htmlFiles = fs.readdirSync(outputDir).filter(f => f.endsWith('.html'));
|
|
526
|
-
console.log(chalk.gray(` - HTML files in output: [${htmlFiles.join(', ')}]`));
|
|
527
|
-
} else {
|
|
528
|
-
console.log(chalk.red(` - ERROR: Output directory does not exist!`));
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// Check if we need to create/replace index.html
|
|
532
|
-
let shouldCreateIndex = false;
|
|
533
|
-
|
|
534
|
-
if (!fs.existsSync(indexPath)) {
|
|
535
|
-
console.log(chalk.yellow('⚠️ index.html does not exist, need to create it'));
|
|
536
|
-
shouldCreateIndex = true;
|
|
537
|
-
} else {
|
|
538
|
-
// Check if existing index.html is likely a directory listing or outdated
|
|
539
|
-
const indexStats = fs.statSync(indexPath);
|
|
540
|
-
const indexContent = fs.readFileSync(indexPath, 'utf8');
|
|
541
|
-
|
|
542
|
-
// Check if it's a small file (likely directory listing) or contains directory listing markers
|
|
543
|
-
if (indexStats.size < 3000 || indexContent.includes('<title>Documentation</title>') && indexContent.includes('<ul>') && !indexContent.includes('class="navigation"')) {
|
|
544
|
-
console.log(chalk.yellow('⚠️ Existing index.html appears to be a directory listing (size: ' + indexStats.size + ' bytes), will replace it'));
|
|
545
|
-
shouldCreateIndex = true;
|
|
546
|
-
} else if (!indexContent.includes('@knowcode/doc-builder')) {
|
|
547
|
-
console.log(chalk.yellow('⚠️ Existing index.html was not created by doc-builder, will replace it'));
|
|
548
|
-
shouldCreateIndex = true;
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
if (shouldCreateIndex) {
|
|
553
|
-
if (fs.existsSync(readmePath)) {
|
|
554
|
-
console.log(chalk.blue(' → Found README.html, copying to index.html'));
|
|
555
|
-
try {
|
|
556
|
-
await fs.copy(readmePath, indexPath);
|
|
557
|
-
console.log(chalk.green('✅ Successfully created index.html from README.html'));
|
|
558
|
-
|
|
559
|
-
// Verify the copy worked
|
|
560
|
-
if (fs.existsSync(indexPath)) {
|
|
561
|
-
const stats = fs.statSync(indexPath);
|
|
562
|
-
console.log(chalk.gray(` - index.html size: ${stats.size} bytes`));
|
|
563
|
-
} else {
|
|
564
|
-
console.log(chalk.red(' - ERROR: index.html was not created!'));
|
|
565
|
-
}
|
|
566
|
-
} catch (error) {
|
|
567
|
-
console.log(chalk.red(` - ERROR copying README.html: ${error.message}`));
|
|
568
|
-
}
|
|
569
|
-
} else {
|
|
570
|
-
// No README.html, create informative default page
|
|
571
|
-
console.log(chalk.yellow('⚠️ No README.html found, creating default index.html'));
|
|
572
|
-
try {
|
|
573
|
-
const defaultIndex = await createDefaultIndexPage(outputDir, config, packageJson.version);
|
|
574
|
-
await fs.writeFile(indexPath, defaultIndex);
|
|
575
|
-
console.log(chalk.green('✅ Created default index.html with instructions'));
|
|
576
|
-
|
|
577
|
-
// Verify the write worked
|
|
578
|
-
if (fs.existsSync(indexPath)) {
|
|
579
|
-
const stats = fs.statSync(indexPath);
|
|
580
|
-
console.log(chalk.gray(` - index.html size: ${stats.size} bytes`));
|
|
581
|
-
} else {
|
|
582
|
-
console.log(chalk.red(' - ERROR: default index.html was not created!'));
|
|
583
|
-
}
|
|
584
|
-
} catch (error) {
|
|
585
|
-
console.log(chalk.red(` - ERROR creating default index.html: ${error.message}`));
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
} else {
|
|
589
|
-
console.log(chalk.gray('ℹ️ index.html already exists and appears valid'));
|
|
590
|
-
const stats = fs.statSync(indexPath);
|
|
591
|
-
console.log(chalk.gray(` - Existing index.html size: ${stats.size} bytes`));
|
|
592
|
-
console.log(chalk.gray(` - Keeping existing index.html (likely from index.md or custom page)`));
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// Final verification
|
|
596
|
-
console.log(chalk.blue('\n📋 Final index.html check:'));
|
|
597
|
-
if (fs.existsSync(indexPath)) {
|
|
598
|
-
console.log(chalk.green(` ✅ index.html exists at: ${indexPath}`));
|
|
599
|
-
} else {
|
|
600
|
-
console.log(chalk.red(` ❌ index.html is MISSING at: ${indexPath}`));
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
console.log(chalk.green('✅ Documentation build complete!'));
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
// Create placeholder README.md if missing
|
|
607
|
-
async function createPlaceholderReadme(docsDir, config) {
|
|
608
|
-
const readmePath = path.join(docsDir, 'README.md');
|
|
609
|
-
const indexPath = path.join(docsDir, 'index.md');
|
|
610
|
-
|
|
611
|
-
// Check if README.md or index.md already exists
|
|
612
|
-
if (fs.existsSync(readmePath)) {
|
|
613
|
-
console.log(chalk.gray(' ✓ README.md found'));
|
|
614
|
-
return false; // README already exists, no need to create
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
if (fs.existsSync(indexPath)) {
|
|
618
|
-
console.log(chalk.gray(' ✓ index.md found'));
|
|
619
|
-
return false; // index.md exists, no need for README
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
const siteName = config.siteName || 'Documentation';
|
|
623
|
-
const currentDate = new Date().toISOString().split('T')[0];
|
|
624
|
-
|
|
625
|
-
const placeholderContent = `# Welcome to ${siteName}
|
|
626
|
-
|
|
627
|
-
**Generated**: ${currentDate} UTC
|
|
628
|
-
**Status**: Placeholder - Ready for customization
|
|
629
|
-
**Verified**: ❓ (Auto-generated content)
|
|
630
|
-
|
|
631
|
-
## Overview
|
|
632
|
-
|
|
633
|
-
This documentation site was built with @knowcode/doc-builder. This is an auto-generated placeholder to help you get started.
|
|
634
|
-
|
|
635
|
-
## Getting Started
|
|
636
|
-
|
|
637
|
-
1. **Replace this file**: Edit \`docs/README.md\` with your project's actual documentation
|
|
638
|
-
2. **Add content**: Create additional markdown files in the \`docs/\` directory
|
|
639
|
-
3. **Organize with folders**: Use subfolders to structure your documentation
|
|
640
|
-
4. **Rebuild**: Run \`npx @knowcode/doc-builder build\` to regenerate the site
|
|
641
|
-
|
|
642
|
-
## Documentation Structure
|
|
643
|
-
|
|
644
|
-
Your documentation can include:
|
|
645
|
-
|
|
646
|
-
- **Overview**: Main project description (this file)
|
|
647
|
-
- **Guides**: Step-by-step tutorials
|
|
648
|
-
- **API Reference**: Technical documentation
|
|
649
|
-
- **Examples**: Code samples and usage
|
|
650
|
-
- **Architecture**: System design and technical details
|
|
651
|
-
|
|
652
|
-
## Next Steps
|
|
653
|
-
|
|
654
|
-
1. Edit this README.md file with your project information
|
|
655
|
-
2. Create additional markdown files for your content
|
|
656
|
-
3. Organize files into logical folders
|
|
657
|
-
4. Use Mermaid diagrams for visual explanations
|
|
658
|
-
5. Deploy with \`npx @knowcode/doc-builder deploy\`
|
|
659
|
-
|
|
660
|
-
## Documentation Standards
|
|
661
|
-
|
|
662
|
-
This project follows structured documentation conventions:
|
|
663
|
-
|
|
664
|
-
### File Organization
|
|
665
|
-
- Use descriptive filenames with hyphens (e.g., \`user-guide.md\`)
|
|
666
|
-
- Organize related content in folders
|
|
667
|
-
- Include a README.md in each major folder
|
|
668
|
-
|
|
669
|
-
### Content Format
|
|
670
|
-
- Start each document with metadata (Generated date, Status, Verified status)
|
|
671
|
-
- Use clear headings and consistent structure
|
|
672
|
-
- Include diagrams where helpful to explain concepts
|
|
673
|
-
- Mark information as verified (✅) or speculated (❓)
|
|
674
|
-
|
|
675
|
-
### Mermaid Diagrams
|
|
676
|
-
Include visual diagrams to explain complex concepts:
|
|
677
|
-
|
|
678
|
-
\`\`\`mermaid
|
|
679
|
-
graph TD
|
|
680
|
-
A[Start Documentation] --> B{Have Content?}
|
|
681
|
-
B -->|Yes| C[Edit README.md]
|
|
682
|
-
B -->|No| D[Create Content Files]
|
|
683
|
-
C --> E[Build & Deploy]
|
|
684
|
-
D --> E
|
|
685
|
-
E --> F[Share Documentation]
|
|
686
|
-
\`\`\`
|
|
687
|
-
|
|
688
|
-
## Support
|
|
689
|
-
|
|
690
|
-
For help with @knowcode/doc-builder:
|
|
691
|
-
- Check the documentation at your package source
|
|
692
|
-
- Use \`npx @knowcode/doc-builder --help\` for CLI options
|
|
693
|
-
- Review the generated configuration guide if available
|
|
694
|
-
`;
|
|
695
|
-
|
|
696
|
-
try {
|
|
697
|
-
await fs.writeFile(readmePath, placeholderContent);
|
|
698
|
-
console.log(chalk.yellow('📄 Auto-generated placeholder README.md - please customize it!'));
|
|
699
|
-
return true; // Successfully created placeholder
|
|
700
|
-
} catch (error) {
|
|
701
|
-
console.warn(chalk.yellow(`Warning: Could not create placeholder README.md: ${error.message}`));
|
|
702
|
-
return false;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
// Create login/logout pages
|
|
707
|
-
async function createAuthPages(outputDir, config) {
|
|
708
|
-
// Login page
|
|
709
|
-
const loginHTML = `<!DOCTYPE html>
|
|
710
|
-
<html lang="en">
|
|
711
|
-
<head>
|
|
712
|
-
<meta charset="UTF-8">
|
|
713
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
714
|
-
<title>Login - ${config.siteName}</title>
|
|
715
|
-
<link rel="stylesheet" href="css/notion-style.css">
|
|
716
|
-
</head>
|
|
717
|
-
<body>
|
|
718
|
-
<div class="auth-container">
|
|
719
|
-
<div class="auth-box">
|
|
720
|
-
<h1>Login to ${config.siteName}</h1>
|
|
721
|
-
<form id="login-form">
|
|
722
|
-
<div class="form-group">
|
|
723
|
-
<label for="username">Username</label>
|
|
724
|
-
<input type="text" id="username" name="username" required>
|
|
725
|
-
</div>
|
|
726
|
-
<div class="form-group">
|
|
727
|
-
<label for="password">Password</label>
|
|
728
|
-
<input type="password" id="password" name="password" required>
|
|
729
|
-
</div>
|
|
730
|
-
<button type="submit" class="auth-button">Login</button>
|
|
731
|
-
</form>
|
|
732
|
-
<div id="error-message" class="error-message"></div>
|
|
733
|
-
</div>
|
|
734
|
-
</div>
|
|
735
|
-
<script>
|
|
736
|
-
document.getElementById('login-form').addEventListener('submit', function(e) {
|
|
737
|
-
e.preventDefault();
|
|
738
|
-
const username = document.getElementById('username').value;
|
|
739
|
-
const password = document.getElementById('password').value;
|
|
740
|
-
|
|
741
|
-
// Validate credentials
|
|
742
|
-
if (username === '${config.auth.username}' && password === '${config.auth.password}') {
|
|
743
|
-
// Set auth cookie
|
|
744
|
-
const token = btoa(username + ':' + password);
|
|
745
|
-
document.cookie = 'doc-auth=' + token + '; path=/';
|
|
746
|
-
|
|
747
|
-
// Redirect
|
|
748
|
-
const params = new URLSearchParams(window.location.search);
|
|
749
|
-
const redirect = params.get('redirect') || '/';
|
|
750
|
-
window.location.href = redirect;
|
|
751
|
-
} else {
|
|
752
|
-
document.getElementById('error-message').textContent = 'Invalid username or password';
|
|
753
|
-
}
|
|
754
|
-
});
|
|
755
|
-
</script>
|
|
756
|
-
</body>
|
|
757
|
-
</html>`;
|
|
758
|
-
|
|
759
|
-
await fs.writeFile(path.join(outputDir, 'login.html'), loginHTML);
|
|
760
|
-
|
|
761
|
-
// Logout page
|
|
762
|
-
const logoutHTML = `<!DOCTYPE html>
|
|
763
|
-
<html lang="en">
|
|
764
|
-
<head>
|
|
765
|
-
<meta charset="UTF-8">
|
|
766
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
767
|
-
<title>Logged Out - ${config.siteName}</title>
|
|
768
|
-
<link rel="stylesheet" href="css/notion-style.css">
|
|
769
|
-
</head>
|
|
770
|
-
<body>
|
|
771
|
-
<div class="auth-container">
|
|
772
|
-
<div class="auth-box">
|
|
773
|
-
<h1>You have been logged out</h1>
|
|
774
|
-
<p>Thank you for using ${config.siteName}.</p>
|
|
775
|
-
<a href="login.html" class="auth-button">Login Again</a>
|
|
776
|
-
</div>
|
|
777
|
-
</div>
|
|
778
|
-
</body>
|
|
779
|
-
</html>`;
|
|
780
|
-
|
|
781
|
-
await fs.writeFile(path.join(outputDir, 'logout.html'), logoutHTML);
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
// Create default index page when no documentation exists
|
|
785
|
-
async function createDefaultIndexPage(outputDir, config, version) {
|
|
786
|
-
const siteName = config.siteName || 'Documentation';
|
|
787
|
-
const currentDate = new Date().toISOString();
|
|
788
|
-
|
|
789
|
-
// List all HTML files in the output directory
|
|
790
|
-
const htmlFiles = [];
|
|
791
|
-
async function findHtmlFiles(dir, baseDir = dir) {
|
|
792
|
-
const items = await fs.readdir(dir);
|
|
793
|
-
for (const item of items) {
|
|
794
|
-
const fullPath = path.join(dir, item);
|
|
795
|
-
const stat = await fs.stat(fullPath);
|
|
796
|
-
if (stat.isDirectory() && !item.startsWith('.')) {
|
|
797
|
-
await findHtmlFiles(fullPath, baseDir);
|
|
798
|
-
} else if (item.endsWith('.html') && item !== 'index.html' && item !== 'login.html' && item !== 'logout.html') {
|
|
799
|
-
const relativePath = path.relative(baseDir, fullPath);
|
|
800
|
-
htmlFiles.push(relativePath);
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
await findHtmlFiles(outputDir);
|
|
806
|
-
|
|
807
|
-
let fileListHtml = '';
|
|
808
|
-
if (htmlFiles.length > 0) {
|
|
809
|
-
fileListHtml = `
|
|
810
|
-
<div class="existing-files">
|
|
811
|
-
<h2>📁 Available Documentation</h2>
|
|
812
|
-
<p>The following documentation files were found:</p>
|
|
813
|
-
<ul>
|
|
814
|
-
${htmlFiles.map(file => `<li><a href="${file}">${file}</a></li>`).join('\n ')}
|
|
815
|
-
</ul>
|
|
816
|
-
</div>`;
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
return `<!DOCTYPE html>
|
|
820
|
-
<html lang="en">
|
|
821
|
-
<head>
|
|
822
|
-
<meta charset="UTF-8">
|
|
823
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
824
|
-
<title>Welcome to ${siteName}</title>
|
|
825
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
826
|
-
<link rel="stylesheet" href="/css/notion-style.css">
|
|
827
|
-
<link rel="stylesheet" href="/css/style.css">
|
|
828
|
-
<style>
|
|
829
|
-
.welcome-container {
|
|
830
|
-
max-width: 800px;
|
|
831
|
-
margin: 50px auto;
|
|
832
|
-
padding: 40px;
|
|
833
|
-
background: var(--bg-secondary);
|
|
834
|
-
border-radius: 12px;
|
|
835
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
836
|
-
}
|
|
837
|
-
.welcome-container h1 {
|
|
838
|
-
color: var(--text-primary);
|
|
839
|
-
margin-bottom: 20px;
|
|
840
|
-
}
|
|
841
|
-
.welcome-container h2 {
|
|
842
|
-
color: var(--text-primary);
|
|
843
|
-
margin-top: 30px;
|
|
844
|
-
margin-bottom: 15px;
|
|
845
|
-
}
|
|
846
|
-
.welcome-container p {
|
|
847
|
-
color: var(--text-secondary);
|
|
848
|
-
line-height: 1.6;
|
|
849
|
-
margin-bottom: 15px;
|
|
850
|
-
}
|
|
851
|
-
.welcome-container pre {
|
|
852
|
-
background: var(--bg-tertiary);
|
|
853
|
-
padding: 20px;
|
|
854
|
-
border-radius: 8px;
|
|
855
|
-
overflow-x: auto;
|
|
856
|
-
margin: 20px 0;
|
|
857
|
-
}
|
|
858
|
-
.welcome-container code {
|
|
859
|
-
font-family: 'JetBrains Mono', monospace;
|
|
860
|
-
font-size: 14px;
|
|
861
|
-
}
|
|
862
|
-
.welcome-container ul {
|
|
863
|
-
margin: 20px 0;
|
|
864
|
-
padding-left: 30px;
|
|
865
|
-
}
|
|
866
|
-
.welcome-container li {
|
|
867
|
-
margin: 8px 0;
|
|
868
|
-
}
|
|
869
|
-
.version-info {
|
|
870
|
-
margin-top: 40px;
|
|
871
|
-
padding-top: 20px;
|
|
872
|
-
border-top: 1px solid var(--border-color);
|
|
873
|
-
font-size: 12px;
|
|
874
|
-
color: var(--text-tertiary);
|
|
875
|
-
}
|
|
876
|
-
.existing-files {
|
|
877
|
-
background: var(--bg-primary);
|
|
878
|
-
padding: 20px;
|
|
879
|
-
border-radius: 8px;
|
|
880
|
-
margin: 30px 0;
|
|
881
|
-
}
|
|
882
|
-
.existing-files a {
|
|
883
|
-
color: var(--link-color);
|
|
884
|
-
text-decoration: none;
|
|
885
|
-
}
|
|
886
|
-
.existing-files a:hover {
|
|
887
|
-
text-decoration: underline;
|
|
888
|
-
}
|
|
889
|
-
</style>
|
|
890
|
-
</head>
|
|
891
|
-
<body>
|
|
892
|
-
<div class="welcome-container">
|
|
893
|
-
<h1>📚 Welcome to ${siteName}</h1>
|
|
894
|
-
|
|
895
|
-
<p>This documentation site was generated by <strong>@knowcode/doc-builder</strong>. To add your own content, follow the instructions below.</p>
|
|
896
|
-
|
|
897
|
-
<h2>🚀 Getting Started</h2>
|
|
898
|
-
|
|
899
|
-
<p>To create your documentation homepage, create either of these files in your <code>docs/</code> directory:</p>
|
|
900
|
-
|
|
901
|
-
<ul>
|
|
902
|
-
<li><code>index.md</code> - Primary homepage (highest priority)</li>
|
|
903
|
-
<li><code>README.md</code> - Alternative homepage</li>
|
|
904
|
-
</ul>
|
|
905
|
-
|
|
906
|
-
<h2>📝 Example Content</h2>
|
|
907
|
-
|
|
908
|
-
<p>Create <code>docs/index.md</code> with content like:</p>
|
|
909
|
-
|
|
910
|
-
<pre><code># Welcome to My Project
|
|
911
|
-
|
|
912
|
-
This is the homepage for my documentation.
|
|
913
|
-
|
|
914
|
-
## Features
|
|
915
|
-
|
|
916
|
-
- Feature 1
|
|
917
|
-
- Feature 2
|
|
918
|
-
- Feature 3
|
|
919
|
-
|
|
920
|
-
## Getting Started
|
|
921
|
-
|
|
922
|
-
1. Install the package
|
|
923
|
-
2. Configure your settings
|
|
924
|
-
3. Start building!</code></pre>
|
|
925
|
-
|
|
926
|
-
<h2>🔧 Next Steps</h2>
|
|
927
|
-
|
|
928
|
-
<ol>
|
|
929
|
-
<li>Create <code>docs/index.md</code> or <code>docs/README.md</code></li>
|
|
930
|
-
<li>Add more markdown files for additional pages</li>
|
|
931
|
-
<li>Rebuild: <code>npx @knowcode/doc-builder build</code></li>
|
|
932
|
-
<li>Deploy: <code>npx @knowcode/doc-builder deploy</code></li>
|
|
933
|
-
</ol>
|
|
934
|
-
|
|
935
|
-
${fileListHtml}
|
|
936
|
-
|
|
937
|
-
<div class="version-info">
|
|
938
|
-
<p><strong>Debug Information:</strong></p>
|
|
939
|
-
<ul>
|
|
940
|
-
<li>doc-builder version: ${version}</li>
|
|
941
|
-
<li>Generated: ${currentDate}</li>
|
|
942
|
-
<li>Site name: ${siteName}</li>
|
|
943
|
-
<li>No index.md or README.md found in docs directory</li>
|
|
944
|
-
</ul>
|
|
945
|
-
</div>
|
|
946
|
-
</div>
|
|
947
|
-
</body>
|
|
948
|
-
</html>`;
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
module.exports = {
|
|
952
|
-
buildDocumentation,
|
|
953
|
-
processMarkdownContent,
|
|
954
|
-
generateHTML,
|
|
955
|
-
createPlaceholderReadme,
|
|
956
|
-
createDefaultIndexPage
|
|
957
|
-
};
|