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