@knowcode/doc-builder 1.9.29 → 1.9.31

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.
Files changed (197) hide show
  1. package/assets/js/main.js +7 -0
  2. package/lib/core-builder.js +18 -1
  3. package/package.json +12 -2
  4. package/.claude/settings.local.json +0 -56
  5. package/CACHE-BUSTING-GUIDE.md +0 -82
  6. package/CLAUDE.md +0 -86
  7. package/CONTRIBUTING.md +0 -148
  8. package/GITHUB_SETUP.md +0 -203
  9. package/RELEASE-NOTES-1.7.5.md +0 -64
  10. package/Screenshot 2025-07-22 at 19.51.21.png +0 -0
  11. package/Screenshot 2025-07-26 at 17.06.49.png +0 -0
  12. package/add-user-clive.sql +0 -35
  13. package/add-user-lindsay-fixed.sql +0 -85
  14. package/add-user-lindsay.sql +0 -68
  15. package/add-user-pmorgan.sql +0 -35
  16. package/add-user-robbie.sql +0 -35
  17. package/add-wru-users.sql +0 -105
  18. package/debug-login.sql +0 -30
  19. package/doc-builder.config.js +0 -126
  20. package/doc-builder.config.js.backup.1753793768283 +0 -47
  21. package/doc-builder.config.js.backup.1753803964423 +0 -114
  22. package/doc-builder.config.js.backup.1753945707032 +0 -115
  23. package/doc-builder.config.js.backup.1754059241330 +0 -115
  24. package/doc-builder.config.js.backup.1754119567787 +0 -123
  25. package/doc-builder.config.js.backup.1754120048862 +0 -124
  26. package/doc-builder.config.js.backup.1754120529913 +0 -124
  27. package/doc-builder.config.js.backup.1754218469785 +0 -124
  28. package/doc-builder.config.js.backup.1754384764054 +0 -124
  29. package/doc-builder.config.js.backup.1754567425847 +0 -124
  30. package/doc-builder.config.js.backup.1754568137859 +0 -126
  31. package/doc-builder.config.js.backup.1754569388252 +0 -126
  32. package/doc-builder.config.js.backup.1754576694123 +0 -126
  33. package/doc-builder.config.js.backup.1755031374829 +0 -126
  34. package/doc-builder.config.js.backup.1755034500990 +0 -126
  35. package/grant-access.sql +0 -15
  36. package/html/11.png +0 -0
  37. package/html/404.html +0 -115
  38. package/html/README.html +0 -522
  39. package/html/Screenshot 2025-08-12 at 21.35.07.png +0 -0
  40. package/html/about-doc-builder.html +0 -491
  41. package/html/auth.js +0 -157
  42. package/html/claude-workflow-guide.html +0 -525
  43. package/html/css/notion-style.css +0 -2502
  44. package/html/documentation-index.html +0 -471
  45. package/html/guides/authentication-default-change.html +0 -370
  46. package/html/guides/authentication-guide.html +0 -509
  47. package/html/guides/cache-control-anti-pattern.html +0 -361
  48. package/html/guides/claude-workflow-guide.html +0 -1074
  49. package/html/guides/configuration-guide.html +0 -472
  50. package/html/guides/document-standards.html +0 -518
  51. package/html/guides/documentation-standards.html +0 -694
  52. package/html/guides/html-embedding-guide.html +0 -461
  53. package/html/guides/image-modal-guide.html +0 -515
  54. package/html/guides/next-steps-walkthrough.html +0 -638
  55. package/html/guides/phosphor-icons-guide.html +0 -584
  56. package/html/guides/private-directory-authentication-troubleshooting.html +0 -555
  57. package/html/guides/private-directory-authentication.html +0 -541
  58. package/html/guides/public-site-deployment.html +0 -431
  59. package/html/guides/search-engine-verification-guide.html +0 -542
  60. package/html/guides/seo-guide.html +0 -661
  61. package/html/guides/seo-optimization-guide.html +0 -887
  62. package/html/guides/supabase-auth-implementation-plan.html +0 -543
  63. package/html/guides/supabase-auth-integration-plan.html +0 -671
  64. package/html/guides/supabase-auth-setup-guide.html +0 -498
  65. package/html/guides/supabase-authentication-complete-guide.html +0 -866
  66. package/html/guides/troubleshooting-guide.html +0 -633
  67. package/html/guides/vercel-deployment-auth-setup.html +0 -337
  68. package/html/guides/windows-setup-guide.html +0 -859
  69. package/html/image-modal-test.html +0 -318
  70. package/html/index.html +0 -522
  71. package/html/js/auth.js +0 -157
  72. package/html/js/main.js +0 -1747
  73. package/html/launch/README.html +0 -297
  74. package/html/launch/bubble-plugin-specification.html +0 -933
  75. package/html/launch/go-to-market-strategy.html +0 -663
  76. package/html/launch/launch-announcements.html +0 -593
  77. package/html/login.html +0 -102
  78. package/html/logout.html +0 -18
  79. package/html/private/cache-control-anti-pattern.html +0 -429
  80. package/html/private/launch/README.html +0 -371
  81. package/html/private/launch/auth-cleanup-summary.html +0 -361
  82. package/html/private/launch/bubble-plugin-specification.html +0 -1007
  83. package/html/private/launch/go-to-market-strategy.html +0 -737
  84. package/html/private/launch/launch-announcements.html +0 -667
  85. package/html/private/launch/vercel-deployment-auth-setup.html +0 -417
  86. package/html/private/next-steps-walkthrough.html +0 -679
  87. package/html/private/supabase-auth-implementation-completed.html +0 -454
  88. package/html/private/supabase-auth-implementation-plan.html +0 -594
  89. package/html/private/supabase-auth-integration-plan.html +0 -704
  90. package/html/private/supabase-auth-setup-guide.html +0 -555
  91. package/html/private/test-private-doc.html +0 -302
  92. package/html/private/user-management-tooling.html +0 -601
  93. package/html/prompts/Screenshot 2025-08-02 at 08.49.55.png +0 -0
  94. package/html/prompts/beautiful-documentation-design.html +0 -784
  95. package/html/prompts/markdown-document-standards.html +0 -422
  96. package/html/prompts/project-rename-strategy-sasha-publish.html +0 -530
  97. package/html/robots.txt +0 -9
  98. package/html/sitemap.xml +0 -357
  99. package/html/test-questions/how-does-it-work%3F.html +0 -294
  100. package/html/test-questions/step-1%3A%20getting-started.html +0 -289
  101. package/html/test-questions/what-is-the-purpose.html +0 -293
  102. package/html/test-status.html +0 -281
  103. package/html/vercel-cli-setup-guide.html +0 -495
  104. package/html/vercel-first-time-setup-guide.html +0 -454
  105. package/html/vercel.json +0 -29
  106. package/html-static/11.png +0 -0
  107. package/html-static/404.html +0 -115
  108. package/html-static/README.html +0 -599
  109. package/html-static/Screenshot 2025-08-12 at 21.35.07.png +0 -0
  110. package/html-static/about-doc-builder.html +0 -568
  111. package/html-static/css/notion-style.css +0 -2502
  112. package/html-static/documentation-index.html +0 -548
  113. package/html-static/guides/authentication-default-change.html +0 -447
  114. package/html-static/guides/authentication-guide.html +0 -586
  115. package/html-static/guides/claude-workflow-guide.html +0 -1151
  116. package/html-static/guides/configuration-guide.html +0 -549
  117. package/html-static/guides/documentation-standards.html +0 -771
  118. package/html-static/guides/html-embedding-guide.html +0 -538
  119. package/html-static/guides/image-modal-guide.html +0 -592
  120. package/html-static/guides/phosphor-icons-guide.html +0 -661
  121. package/html-static/guides/private-directory-authentication-troubleshooting.html +0 -632
  122. package/html-static/guides/private-directory-authentication.html +0 -618
  123. package/html-static/guides/public-site-deployment.html +0 -508
  124. package/html-static/guides/search-engine-verification-guide.html +0 -619
  125. package/html-static/guides/seo-guide.html +0 -738
  126. package/html-static/guides/seo-optimization-guide.html +0 -964
  127. package/html-static/guides/supabase-authentication-complete-guide.html +0 -943
  128. package/html-static/guides/troubleshooting-guide.html +0 -710
  129. package/html-static/guides/windows-setup-guide.html +0 -936
  130. package/html-static/image-modal-test.html +0 -395
  131. package/html-static/index.html +0 -599
  132. package/html-static/js/main.js +0 -1747
  133. package/html-static/prompts/Screenshot 2025-08-02 at 08.49.55.png +0 -0
  134. package/html-static/prompts/beautiful-documentation-design.html +0 -861
  135. package/html-static/prompts/markdown-document-standards.html +0 -499
  136. package/html-static/prompts/project-rename-strategy-sasha-publish.html +0 -607
  137. package/html-static/robots.txt +0 -5
  138. package/html-static/sitemap.xml +0 -195
  139. package/html-static/test-questions/how-does-it-work%3F.html +0 -371
  140. package/html-static/test-questions/step-1%3A%20getting-started.html +0 -366
  141. package/html-static/test-questions/what-is-the-purpose.html +0 -370
  142. package/html-static/vercel-cli-setup-guide.html +0 -572
  143. package/html-static/vercel-first-time-setup-guide.html +0 -531
  144. package/manage-users.sql +0 -191
  145. package/migrate-to-domain-auth.sql +0 -47
  146. package/package/CACHE-BUSTING-GUIDE.md +0 -82
  147. package/package/CHANGELOG.md +0 -902
  148. package/package/README.md +0 -248
  149. package/package/assets/css/notion-style.css +0 -2211
  150. package/package/assets/js/auth.js +0 -67
  151. package/package/assets/js/main.js +0 -1565
  152. package/package/cli.js +0 -764
  153. package/package/index.js +0 -38
  154. package/package/knowcode-doc-builder-1.3.15.tgz +0 -0
  155. package/package/lib/builder.js +0 -32
  156. package/package/lib/config.js +0 -278
  157. package/package/lib/core-builder.js +0 -957
  158. package/package/lib/deploy.js +0 -497
  159. package/package/lib/dev-server.js +0 -96
  160. package/package/package.json +0 -34
  161. package/package/scripts/npx-runner.js +0 -27
  162. package/package/scripts/setup.js +0 -56
  163. package/package/test-cache-bust.sh +0 -43
  164. package/public-config.js +0 -22
  165. package/public-html/404.html +0 -115
  166. package/public-html/README.html +0 -149
  167. package/public-html/css/notion-style.css +0 -2036
  168. package/public-html/index.html +0 -149
  169. package/public-html/js/auth.js +0 -67
  170. package/public-html/js/main.js +0 -1485
  171. package/quick-test-commands.md +0 -40
  172. package/recordings/Screenshot 2025-07-24 at 18.22.01.png +0 -0
  173. package/recordings/mh-ls-22jul.txt +0 -2305
  174. package/screenshot.png +0 -0
  175. package/scripts/Screenshot 2025-07-23 at 15.39.41.png +0 -0
  176. package/setup-database-v2.sql +0 -53
  177. package/setup-database.sql +0 -41
  178. package/test-auth-config.js +0 -17
  179. package/test-cache-bust.sh +0 -43
  180. package/test-docs/README.md +0 -39
  181. package/test-html/404.html +0 -115
  182. package/test-html/README.html +0 -172
  183. package/test-html/auth.js +0 -97
  184. package/test-html/css/notion-style.css +0 -2036
  185. package/test-html/index.html +0 -172
  186. package/test-html/js/auth.js +0 -97
  187. package/test-html/js/main.js +0 -1485
  188. package/test-html/login.html +0 -102
  189. package/test-html/logout.html +0 -18
  190. package/update-domain.sql +0 -9
  191. package/user-access-view.sql +0 -49
  192. package/user-management/README.md +0 -301
  193. package/user-management/add-users.sh +0 -776
  194. package/user-management/create-user.js +0 -65
  195. package/user-management/users.txt +0 -15
  196. package/view-all-users.sql +0 -40
  197. 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
- '&': '&amp;',
19
- '<': '&lt;',
20
- '>': '&gt;',
21
- '"': '&quot;',
22
- "'": '&#039;'
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
- };