@knowcode/doc-builder 1.9.20 → 1.9.22

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 (88) hide show
  1. package/cli.js +15 -1
  2. package/doc-builder.config.js +4 -2
  3. package/doc-builder.config.js.backup.1754567425847 +124 -0
  4. package/doc-builder.config.js.backup.1754568137859 +126 -0
  5. package/html/README.html +3 -3
  6. package/html/about-doc-builder.html +3 -3
  7. package/html/documentation-index.html +3 -3
  8. package/html/guides/authentication-default-change.html +3 -3
  9. package/html/guides/authentication-guide.html +3 -3
  10. package/html/guides/claude-workflow-guide.html +3 -3
  11. package/html/guides/configuration-guide.html +3 -3
  12. package/html/guides/documentation-standards.html +3 -3
  13. package/html/guides/html-embedding-guide.html +3 -3
  14. package/html/guides/image-modal-guide.html +3 -3
  15. package/html/guides/phosphor-icons-guide.html +3 -3
  16. package/html/guides/private-directory-authentication-troubleshooting.html +3 -3
  17. package/html/guides/private-directory-authentication.html +3 -3
  18. package/html/guides/public-site-deployment.html +3 -3
  19. package/html/guides/search-engine-verification-guide.html +3 -3
  20. package/html/guides/seo-guide.html +3 -3
  21. package/html/guides/seo-optimization-guide.html +3 -3
  22. package/html/guides/supabase-authentication-complete-guide.html +3 -3
  23. package/html/guides/troubleshooting-guide.html +3 -3
  24. package/html/guides/windows-setup-guide.html +3 -3
  25. package/html/image-modal-test.html +3 -3
  26. package/html/index.html +3 -3
  27. package/html/private/cache-control-anti-pattern.html +3 -3
  28. package/html/private/launch/README.html +3 -3
  29. package/html/private/launch/auth-cleanup-summary.html +3 -3
  30. package/html/private/launch/bubble-plugin-specification.html +3 -3
  31. package/html/private/launch/go-to-market-strategy.html +3 -3
  32. package/html/private/launch/launch-announcements.html +3 -3
  33. package/html/private/launch/vercel-deployment-auth-setup.html +3 -3
  34. package/html/private/next-steps-walkthrough.html +3 -3
  35. package/html/private/supabase-auth-implementation-completed.html +3 -3
  36. package/html/private/supabase-auth-implementation-plan.html +3 -3
  37. package/html/private/supabase-auth-integration-plan.html +3 -3
  38. package/html/private/supabase-auth-setup-guide.html +3 -3
  39. package/html/private/test-private-doc.html +3 -3
  40. package/html/private/user-management-tooling.html +3 -3
  41. package/html/prompts/beautiful-documentation-design.html +3 -3
  42. package/html/prompts/markdown-document-standards.html +3 -3
  43. package/html/prompts/project-rename-strategy-sasha-publish.html +3 -3
  44. package/html/sitemap.xml +59 -59
  45. package/html/test-questions/how-does-it-work%3F.html +3 -3
  46. package/html/test-questions/step-1%3A%20getting-started.html +3 -3
  47. package/html/test-questions/what-is-the-purpose.html +3 -3
  48. package/html/vercel-cli-setup-guide.html +3 -3
  49. package/html/vercel-first-time-setup-guide.html +3 -3
  50. package/html-static/404.html +115 -0
  51. package/html-static/README.html +456 -0
  52. package/html-static/about-doc-builder.html +425 -0
  53. package/html-static/css/notion-style.css +2426 -0
  54. package/html-static/documentation-index.html +405 -0
  55. package/html-static/guides/authentication-default-change.html +304 -0
  56. package/html-static/guides/authentication-guide.html +443 -0
  57. package/html-static/guides/claude-workflow-guide.html +1008 -0
  58. package/html-static/guides/configuration-guide.html +406 -0
  59. package/html-static/guides/documentation-standards.html +628 -0
  60. package/html-static/guides/html-embedding-guide.html +395 -0
  61. package/html-static/guides/image-modal-guide.html +449 -0
  62. package/html-static/guides/phosphor-icons-guide.html +518 -0
  63. package/html-static/guides/private-directory-authentication-troubleshooting.html +489 -0
  64. package/html-static/guides/private-directory-authentication.html +475 -0
  65. package/html-static/guides/public-site-deployment.html +365 -0
  66. package/html-static/guides/search-engine-verification-guide.html +476 -0
  67. package/html-static/guides/seo-guide.html +595 -0
  68. package/html-static/guides/seo-optimization-guide.html +821 -0
  69. package/html-static/guides/supabase-authentication-complete-guide.html +800 -0
  70. package/html-static/guides/troubleshooting-guide.html +567 -0
  71. package/html-static/guides/windows-setup-guide.html +793 -0
  72. package/html-static/image-modal-test.html +252 -0
  73. package/html-static/index.html +456 -0
  74. package/html-static/js/main.js +1692 -0
  75. package/html-static/prompts/Screenshot 2025-08-02 at 08.49.55.png +0 -0
  76. package/html-static/prompts/beautiful-documentation-design.html +718 -0
  77. package/html-static/prompts/markdown-document-standards.html +356 -0
  78. package/html-static/prompts/project-rename-strategy-sasha-publish.html +464 -0
  79. package/html-static/robots.txt +5 -0
  80. package/html-static/sitemap.xml +195 -0
  81. package/html-static/test-questions/how-does-it-work%3F.html +228 -0
  82. package/html-static/test-questions/step-1%3A%20getting-started.html +223 -0
  83. package/html-static/test-questions/what-is-the-purpose.html +227 -0
  84. package/html-static/vercel-cli-setup-guide.html +429 -0
  85. package/html-static/vercel-first-time-setup-guide.html +388 -0
  86. package/lib/config.js +9 -2
  87. package/lib/core-builder.js +177 -14
  88. package/package.json +1 -1
@@ -361,10 +361,38 @@ function generateFaviconTag(favicon) {
361
361
  return `<link rel="icon" href="${favicon}">`;
362
362
  }
363
363
 
364
+ // Generate static HTML (without authentication and with relative paths)
365
+ function generateStaticHTML(title, content, navigation, currentPath = '', config = {}, originalContent = '', frontMatter = {}) {
366
+ // Use regular generateHTML but force disable auth features and use relative paths
367
+ const staticConfig = {
368
+ ...config,
369
+ features: {
370
+ ...config.features,
371
+ authentication: false,
372
+ privateDirectoryAuth: false
373
+ },
374
+ // Special flag to indicate this is static output (for relative paths)
375
+ isStaticOutput: true
376
+ };
377
+
378
+ return generateHTML(title, content, navigation, currentPath, staticConfig, originalContent, frontMatter);
379
+ }
380
+
364
381
  // Generate HTML from template
365
382
  function generateHTML(title, content, navigation, currentPath = '', config = {}, originalContent = '', frontMatter = {}) {
366
- const depth = currentPath.split('/').filter(p => p).length;
367
- const relativePath = depth > 0 ? '../'.repeat(depth) : '';
383
+ // For normal output, use standard depth calculation
384
+ const pathParts = currentPath.split('/').filter(p => p);
385
+ let depth = pathParts.length;
386
+ let relativePath = depth > 0 ? '../'.repeat(depth) : '';
387
+
388
+ // For static output, calculate depth differently (exclude the filename)
389
+ if (config.isStaticOutput) {
390
+ depth = pathParts.length > 1 ? pathParts.length - 1 : 0;
391
+ relativePath = depth > 0 ? '../'.repeat(depth) : '';
392
+ }
393
+
394
+ // For static output, use relative paths; for normal output, use absolute paths
395
+ const resourcePath = config.isStaticOutput ? relativePath : '/';
368
396
 
369
397
  const siteName = config.siteName || 'Documentation';
370
398
  const siteDescription = config.siteDescription || 'Documentation site';
@@ -471,7 +499,7 @@ ${seoTags}
471
499
  <script src="https://cdn.jsdelivr.net/npm/mermaid@10.6.1/dist/mermaid.min.js"></script>
472
500
 
473
501
  <!-- Styles -->
474
- <link rel="stylesheet" href="/css/notion-style.css">
502
+ <link rel="stylesheet" href="${resourcePath}css/notion-style.css">
475
503
 
476
504
  ${(config.features?.authentication === 'supabase' || config.features?.privateDirectoryAuth === true) ? `
477
505
  <!-- Hide content until auth check -->
@@ -517,7 +545,7 @@ ${seoTags}
517
545
  <!-- Header -->
518
546
  <header class="header">
519
547
  <div class="header-content">
520
- <a href="/index.html" class="logo">${siteName}</a>
548
+ <a href="${config.isStaticOutput ? relativePath + 'index.html' : '/index.html'}" class="logo">${siteName}</a>
521
549
 
522
550
  <div class="header-actions">
523
551
  <div class="deployment-info">
@@ -603,9 +631,9 @@ ${seoTags}
603
631
  }
604
632
  };
605
633
  </script>
606
- <script src="/js/main.js"></script>
634
+ <script src="${resourcePath}js/main.js"></script>
607
635
  ${(config.features?.authentication === 'supabase' || config.features?.privateDirectoryAuth === true) ? `<script src="https://unpkg.com/@supabase/supabase-js@2"></script>
608
- <script src="/js/auth.js"></script>` : ''}
636
+ <script src="${resourcePath}js/auth.js"></script>` : ''}
609
637
  </body>
610
638
  </html>`;
611
639
  }
@@ -733,7 +761,9 @@ function buildNavigationStructure(files, currentFile, config = {}) {
733
761
 
734
762
  // Check if this folder has a README.md file to link to
735
763
  const readmeFile = folderData.files.find(f => f.displayName === 'README');
736
- const folderLink = readmeFile ? `href="/${readmeFile.urlPath}"` : 'href="#"';
764
+ const folderLink = readmeFile ?
765
+ `href="${config.isStaticOutput ? readmeFile.urlPath : '/' + readmeFile.urlPath}"` :
766
+ 'href="#"';
737
767
 
738
768
  // Get folder description for tooltip
739
769
  const folderDescription = folderDescriptions[folderName] || '';
@@ -789,7 +819,8 @@ function buildNavigationStructure(files, currentFile, config = {}) {
789
819
  isActive = ' active';
790
820
  }
791
821
 
792
- const linkPath = '/' + file.urlPath;
822
+ // Use relative paths for static output
823
+ const linkPath = config.isStaticOutput ? file.urlPath : '/' + file.urlPath;
793
824
  const tooltip = file.summary ? ` data-tooltip="${escapeHtml(file.summary)}"` : '';
794
825
  const icon = getIconForStatus(file.status || 'default', false, config);
795
826
 
@@ -854,7 +885,8 @@ function buildNavigationStructure(files, currentFile, config = {}) {
854
885
  if (currentFile === file.urlPath) {
855
886
  isActive = ' active';
856
887
  }
857
- const linkPath = '/' + file.urlPath;
888
+ // Use relative paths for static output
889
+ const linkPath = config.isStaticOutput ? file.urlPath : '/' + file.urlPath;
858
890
  const tooltip = file.summary ? ` data-tooltip="${escapeHtml(file.summary)}"` : '';
859
891
  const icon = getIconForStatus(file.status || 'default', false, config);
860
892
  additionalFiles += `
@@ -873,7 +905,7 @@ function buildNavigationStructure(files, currentFile, config = {}) {
873
905
  }
874
906
 
875
907
  // Process single markdown file
876
- async function processMarkdownFile(filePath, outputPath, allFiles, config) {
908
+ async function processMarkdownFile(filePath, outputPath, allFiles, config, useStaticHTML = false) {
877
909
  const rawContent = await fs.readFile(filePath, 'utf-8');
878
910
  const fileName = path.basename(filePath, '.md');
879
911
  const relativePath = path.relative(config.docsDir, filePath);
@@ -903,10 +935,14 @@ async function processMarkdownFile(filePath, outputPath, allFiles, config) {
903
935
  const htmlContent = processMarkdownContent(content, config);
904
936
 
905
937
  // Build navigation - pass config to handle private file filtering
906
- const navigation = buildNavigationStructure(allFiles, urlPath, config);
938
+ // For static HTML, we need to build navigation with relative paths
939
+ const navConfig = useStaticHTML ? { ...config, isStaticOutput: true } : config;
940
+ const navigation = buildNavigationStructure(allFiles, urlPath, navConfig);
907
941
 
908
942
  // Generate full HTML (pass original content and front matter for SEO)
909
- const html = generateHTML(title, htmlContent, navigation, urlPath, config, content, frontMatter);
943
+ const html = useStaticHTML
944
+ ? generateStaticHTML(title, htmlContent, navigation, urlPath, config, content, frontMatter)
945
+ : generateHTML(title, htmlContent, navigation, urlPath, config, content, frontMatter);
910
946
 
911
947
  // Write file
912
948
  await fs.ensureDir(path.dirname(outputPath));
@@ -916,7 +952,7 @@ async function processMarkdownFile(filePath, outputPath, allFiles, config) {
916
952
  }
917
953
 
918
954
  // Get all markdown files
919
- async function getAllMarkdownFiles(dir, baseDir = dir) {
955
+ async function getAllMarkdownFiles(dir, baseDir = dir, options = {}) {
920
956
  const files = [];
921
957
  const items = await fs.readdir(dir);
922
958
 
@@ -924,8 +960,13 @@ async function getAllMarkdownFiles(dir, baseDir = dir) {
924
960
  const fullPath = path.join(dir, item);
925
961
  const stat = await fs.stat(fullPath);
926
962
 
963
+ // Skip private directories if excludePrivate is true
964
+ if (stat.isDirectory() && options.excludePrivate && item === 'private') {
965
+ continue;
966
+ }
967
+
927
968
  if (stat.isDirectory() && !item.startsWith('.') && !item.startsWith('_')) {
928
- const subFiles = await getAllMarkdownFiles(fullPath, baseDir);
969
+ const subFiles = await getAllMarkdownFiles(fullPath, baseDir, options);
929
970
  files.push(...subFiles);
930
971
  } else if (item.endsWith('.md') && !item.startsWith('_')) {
931
972
  const relativePath = path.relative(baseDir, fullPath);
@@ -950,6 +991,11 @@ async function getAllMarkdownFiles(dir, baseDir = dir) {
950
991
  relativePath.startsWith('private/') ||
951
992
  relativePath.startsWith('private\\');
952
993
 
994
+ // Skip private files if excludePrivate is true
995
+ if (options.excludePrivate && isPrivate) {
996
+ continue;
997
+ }
998
+
953
999
  files.push({
954
1000
  path: fullPath,
955
1001
  relativePath,
@@ -1251,6 +1297,122 @@ async function buildDocumentation(config) {
1251
1297
  }
1252
1298
  }
1253
1299
 
1300
+ // Generate static version if enabled
1301
+ if (config.features?.staticOutput !== false) {
1302
+ console.log(chalk.blue('\n🌐 Generating static version (no auth, no private content)...'));
1303
+
1304
+ const staticOutputDir = path.join(process.cwd(), config.staticOutputDir || 'html-static');
1305
+
1306
+ // Ensure static output directory exists
1307
+ await fs.ensureDir(staticOutputDir);
1308
+
1309
+ // Get files excluding private directories
1310
+ const staticFiles = await getAllMarkdownFiles(docsDir, docsDir, { excludePrivate: true });
1311
+ console.log(chalk.gray(` Found ${staticFiles.length} public files (private files excluded)`));
1312
+
1313
+ // Process files for static output
1314
+ for (const file of staticFiles) {
1315
+ const outputPath = path.join(staticOutputDir, file.urlPath);
1316
+ await processMarkdownFile(file.path, outputPath, staticFiles, config, true);
1317
+ }
1318
+
1319
+ // Copy assets to static directory
1320
+ const assetsDir = path.join(__dirname, '../assets');
1321
+ const cssSource = path.join(assetsDir, 'css');
1322
+ const jsSource = path.join(assetsDir, 'js');
1323
+
1324
+ if (fs.existsSync(cssSource)) {
1325
+ await fs.copy(cssSource, path.join(staticOutputDir, 'css'), { overwrite: true });
1326
+ }
1327
+
1328
+ if (fs.existsSync(jsSource)) {
1329
+ await fs.copy(jsSource, path.join(staticOutputDir, 'js'), { overwrite: true });
1330
+ // Don't generate auth.js for static version
1331
+ }
1332
+
1333
+ // Copy 404.html for handling .md redirects
1334
+ const notFoundSource = path.join(assetsDir, '404.html');
1335
+ if (fs.existsSync(notFoundSource)) {
1336
+ await fs.copy(notFoundSource, path.join(staticOutputDir, '404.html'), { overwrite: true });
1337
+ }
1338
+
1339
+ // Create index.html from README.html or generate default
1340
+ const staticIndexPath = path.join(staticOutputDir, 'index.html');
1341
+ const staticReadmePath = path.join(staticOutputDir, 'README.html');
1342
+
1343
+ if (fs.existsSync(staticReadmePath)) {
1344
+ await fs.copy(staticReadmePath, staticIndexPath);
1345
+ } else if (staticFiles.length > 0) {
1346
+ // Generate a default index that lists available pages
1347
+ const defaultIndex = await createDefaultIndexPage(staticOutputDir, config, packageJson.version);
1348
+ await fs.writeFile(staticIndexPath, defaultIndex);
1349
+ }
1350
+
1351
+ // Copy attachments to static directory if enabled
1352
+ if (config.features?.attachments !== false) {
1353
+ const attachmentTypes = config.attachmentTypes || [
1354
+ '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.csv', '.ppt', '.pptx', '.txt', '.rtf',
1355
+ '.html', '.htm',
1356
+ '.zip', '.tar', '.gz', '.7z', '.rar',
1357
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico', '.bmp',
1358
+ '.json', '.xml', '.yaml', '.yml', '.toml',
1359
+ '.mp4', '.mp3', '.wav', '.avi', '.mov'
1360
+ ];
1361
+
1362
+ try {
1363
+ // Get attachment files excluding private directories
1364
+ const allAttachmentFiles = await getAllAttachmentFiles(docsDir, docsDir, attachmentTypes);
1365
+ const staticAttachmentFiles = [];
1366
+ for (const file of allAttachmentFiles) {
1367
+ if (!file.relativePath.startsWith('private/') && !file.relativePath.startsWith('private\\')) {
1368
+ staticAttachmentFiles.push(file);
1369
+ }
1370
+ }
1371
+
1372
+ if (staticAttachmentFiles.length > 0) {
1373
+ await copyAttachmentFiles(staticAttachmentFiles, docsDir, staticOutputDir);
1374
+ }
1375
+ } catch (error) {
1376
+ console.warn(chalk.yellow(`Warning: Error copying attachments to static output: ${error.message}`));
1377
+ }
1378
+ }
1379
+
1380
+ // Generate SEO files for static version if enabled
1381
+ if (config.seo?.enabled && config.seo?.siteUrl) {
1382
+ // Collect all HTML files for sitemap
1383
+ const staticPages = [];
1384
+ const walkDir = (dir, baseDir = '') => {
1385
+ const items = fs.readdirSync(dir);
1386
+ items.forEach(item => {
1387
+ const fullPath = path.join(dir, item);
1388
+ const stat = fs.statSync(fullPath);
1389
+ if (stat.isDirectory()) {
1390
+ walkDir(fullPath, path.join(baseDir, item));
1391
+ } else if (item.endsWith('.html')) {
1392
+ staticPages.push({
1393
+ path: baseDir ? path.join(baseDir, item) : item,
1394
+ modified: stat.mtime
1395
+ });
1396
+ }
1397
+ });
1398
+ };
1399
+
1400
+ walkDir(staticOutputDir);
1401
+
1402
+ if (config.seo.generateSitemap) {
1403
+ await generateSitemap(staticPages, config.seo.siteUrl, staticOutputDir);
1404
+ }
1405
+
1406
+ if (config.seo.generateRobotsTxt) {
1407
+ await generateRobotsTxt(config.seo.siteUrl, staticOutputDir, {
1408
+ hasAuthentication: false
1409
+ });
1410
+ }
1411
+ }
1412
+
1413
+ console.log(chalk.green(`āœ… Static version generated in ${config.staticOutputDir || 'html-static'}/`));
1414
+ }
1415
+
1254
1416
  console.log(chalk.green('\nāœ… Documentation build complete!'));
1255
1417
  }
1256
1418
 
@@ -1571,6 +1733,7 @@ module.exports = {
1571
1733
  buildDocumentation,
1572
1734
  processMarkdownContent,
1573
1735
  generateHTML,
1736
+ generateStaticHTML,
1574
1737
  createPlaceholderReadme,
1575
1738
  createDefaultIndexPage
1576
1739
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowcode/doc-builder",
3
- "version": "1.9.20",
3
+ "version": "1.9.22",
4
4
  "description": "Reusable documentation builder for markdown-based sites with Vercel deployment support",
5
5
  "main": "index.js",
6
6
  "bin": {