@knowcode/doc-builder 1.9.19 → 1.9.21

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 (87) hide show
  1. package/cli.js +15 -1
  2. package/doc-builder.config.js +4 -2
  3. package/doc-builder.config.js.backup.1754384764054 +124 -0
  4. package/doc-builder.config.js.backup.1754567425847 +124 -0
  5. package/html/README.html +12 -4
  6. package/html/about-doc-builder.html +12 -4
  7. package/html/documentation-index.html +12 -4
  8. package/html/guides/authentication-default-change.html +12 -4
  9. package/html/guides/authentication-guide.html +12 -4
  10. package/html/guides/claude-workflow-guide.html +12 -4
  11. package/html/guides/configuration-guide.html +12 -4
  12. package/html/guides/documentation-standards.html +12 -4
  13. package/html/guides/html-embedding-guide.html +12 -4
  14. package/html/guides/image-modal-guide.html +12 -4
  15. package/html/guides/phosphor-icons-guide.html +12 -4
  16. package/html/guides/private-directory-authentication-troubleshooting.html +12 -4
  17. package/html/guides/private-directory-authentication.html +12 -4
  18. package/html/guides/public-site-deployment.html +12 -4
  19. package/html/guides/search-engine-verification-guide.html +12 -4
  20. package/html/guides/seo-guide.html +12 -4
  21. package/html/guides/seo-optimization-guide.html +12 -4
  22. package/html/guides/supabase-authentication-complete-guide.html +12 -4
  23. package/html/guides/troubleshooting-guide.html +12 -4
  24. package/html/guides/windows-setup-guide.html +12 -4
  25. package/html/image-modal-test.html +12 -4
  26. package/html/index.html +12 -4
  27. package/html/private/cache-control-anti-pattern.html +12 -4
  28. package/html/private/launch/README.html +12 -4
  29. package/html/private/launch/auth-cleanup-summary.html +12 -4
  30. package/html/private/launch/bubble-plugin-specification.html +12 -4
  31. package/html/private/launch/go-to-market-strategy.html +12 -4
  32. package/html/private/launch/launch-announcements.html +12 -4
  33. package/html/private/launch/vercel-deployment-auth-setup.html +12 -4
  34. package/html/private/next-steps-walkthrough.html +12 -4
  35. package/html/private/supabase-auth-implementation-completed.html +12 -4
  36. package/html/private/supabase-auth-implementation-plan.html +12 -4
  37. package/html/private/supabase-auth-integration-plan.html +12 -4
  38. package/html/private/supabase-auth-setup-guide.html +12 -4
  39. package/html/private/test-private-doc.html +12 -4
  40. package/html/private/user-management-tooling.html +12 -4
  41. package/html/prompts/beautiful-documentation-design.html +12 -4
  42. package/html/prompts/markdown-document-standards.html +12 -4
  43. package/html/prompts/project-rename-strategy-sasha-publish.html +12 -4
  44. package/html/sitemap.xml +74 -56
  45. package/html/test-questions/how-does-it-work%3F.html +290 -0
  46. package/html/test-questions/step-1%3A%20getting-started.html +285 -0
  47. package/html/test-questions/what-is-the-purpose.html +289 -0
  48. package/html/vercel-cli-setup-guide.html +12 -4
  49. package/html/vercel-first-time-setup-guide.html +12 -4
  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/beautiful-documentation-design.html +718 -0
  76. package/html-static/prompts/markdown-document-standards.html +356 -0
  77. package/html-static/prompts/project-rename-strategy-sasha-publish.html +464 -0
  78. package/html-static/robots.txt +5 -0
  79. package/html-static/sitemap.xml +189 -0
  80. package/html-static/test-questions/how-does-it-work%3F.html +228 -0
  81. package/html-static/test-questions/step-1%3A%20getting-started.html +223 -0
  82. package/html-static/test-questions/what-is-the-purpose.html +227 -0
  83. package/html-static/vercel-cli-setup-guide.html +429 -0
  84. package/html-static/vercel-first-time-setup-guide.html +388 -0
  85. package/lib/config.js +9 -2
  86. package/lib/core-builder.js +167 -6
  87. package/package.json +1 -1
@@ -361,6 +361,21 @@ function generateFaviconTag(favicon) {
361
361
  return `<link rel="icon" href="${favicon}">`;
362
362
  }
363
363
 
364
+ // Generate static HTML (without authentication)
365
+ function generateStaticHTML(title, content, navigation, currentPath = '', config = {}, originalContent = '', frontMatter = {}) {
366
+ // Use regular generateHTML but force disable auth features
367
+ const staticConfig = {
368
+ ...config,
369
+ features: {
370
+ ...config.features,
371
+ authentication: false,
372
+ privateDirectoryAuth: false
373
+ }
374
+ };
375
+
376
+ return generateHTML(title, content, navigation, currentPath, staticConfig, originalContent, frontMatter);
377
+ }
378
+
364
379
  // Generate HTML from template
365
380
  function generateHTML(title, content, navigation, currentPath = '', config = {}, originalContent = '', frontMatter = {}) {
366
381
  const depth = currentPath.split('/').filter(p => p).length;
@@ -668,6 +683,11 @@ function buildNavigationStructure(files, currentFile, config = {}) {
668
683
 
669
684
  // Helper function to generate file title
670
685
  const generateFileTitle = (file, parentDisplayName, level) => {
686
+ // First check for front matter title
687
+ if (file.frontMatter?.title) {
688
+ return file.frontMatter.title;
689
+ }
690
+
671
691
  let title = file.displayName;
672
692
 
673
693
  if (file.displayName === 'README') {
@@ -868,11 +888,17 @@ function buildNavigationStructure(files, currentFile, config = {}) {
868
888
  }
869
889
 
870
890
  // Process single markdown file
871
- async function processMarkdownFile(filePath, outputPath, allFiles, config) {
891
+ async function processMarkdownFile(filePath, outputPath, allFiles, config, useStaticHTML = false) {
872
892
  const rawContent = await fs.readFile(filePath, 'utf-8');
873
893
  const fileName = path.basename(filePath, '.md');
874
894
  const relativePath = path.relative(config.docsDir, filePath);
875
- const urlPath = relativePath.replace(/\.md$/, '.html').replace(/\\/g, '/');
895
+ // Encode special characters in URL but keep slashes
896
+ const urlPath = relativePath
897
+ .replace(/\.md$/, '.html')
898
+ .replace(/\\/g, '/')
899
+ .split('/')
900
+ .map(segment => encodeURIComponent(segment))
901
+ .join('/');
876
902
 
877
903
  // Parse front matter
878
904
  const { data: frontMatter, content } = matter(rawContent);
@@ -895,7 +921,9 @@ async function processMarkdownFile(filePath, outputPath, allFiles, config) {
895
921
  const navigation = buildNavigationStructure(allFiles, urlPath, config);
896
922
 
897
923
  // Generate full HTML (pass original content and front matter for SEO)
898
- const html = generateHTML(title, htmlContent, navigation, urlPath, config, content, frontMatter);
924
+ const html = useStaticHTML
925
+ ? generateStaticHTML(title, htmlContent, navigation, urlPath, config, content, frontMatter)
926
+ : generateHTML(title, htmlContent, navigation, urlPath, config, content, frontMatter);
899
927
 
900
928
  // Write file
901
929
  await fs.ensureDir(path.dirname(outputPath));
@@ -905,7 +933,7 @@ async function processMarkdownFile(filePath, outputPath, allFiles, config) {
905
933
  }
906
934
 
907
935
  // Get all markdown files
908
- async function getAllMarkdownFiles(dir, baseDir = dir) {
936
+ async function getAllMarkdownFiles(dir, baseDir = dir, options = {}) {
909
937
  const files = [];
910
938
  const items = await fs.readdir(dir);
911
939
 
@@ -913,12 +941,23 @@ async function getAllMarkdownFiles(dir, baseDir = dir) {
913
941
  const fullPath = path.join(dir, item);
914
942
  const stat = await fs.stat(fullPath);
915
943
 
944
+ // Skip private directories if excludePrivate is true
945
+ if (stat.isDirectory() && options.excludePrivate && item === 'private') {
946
+ continue;
947
+ }
948
+
916
949
  if (stat.isDirectory() && !item.startsWith('.') && !item.startsWith('_')) {
917
- const subFiles = await getAllMarkdownFiles(fullPath, baseDir);
950
+ const subFiles = await getAllMarkdownFiles(fullPath, baseDir, options);
918
951
  files.push(...subFiles);
919
952
  } else if (item.endsWith('.md') && !item.startsWith('_')) {
920
953
  const relativePath = path.relative(baseDir, fullPath);
921
- const urlPath = relativePath.replace(/\.md$/, '.html').replace(/\\/g, '/');
954
+ // Encode special characters in URL but keep slashes
955
+ const urlPath = relativePath
956
+ .replace(/\.md$/, '.html')
957
+ .replace(/\\/g, '/')
958
+ .split('/')
959
+ .map(segment => encodeURIComponent(segment))
960
+ .join('/');
922
961
  const displayName = smartCapitalize(path.basename(item, '.md'));
923
962
 
924
963
  // Read file to extract summary and status
@@ -933,6 +972,11 @@ async function getAllMarkdownFiles(dir, baseDir = dir) {
933
972
  relativePath.startsWith('private/') ||
934
973
  relativePath.startsWith('private\\');
935
974
 
975
+ // Skip private files if excludePrivate is true
976
+ if (options.excludePrivate && isPrivate) {
977
+ continue;
978
+ }
979
+
936
980
  files.push({
937
981
  path: fullPath,
938
982
  relativePath,
@@ -1234,6 +1278,122 @@ async function buildDocumentation(config) {
1234
1278
  }
1235
1279
  }
1236
1280
 
1281
+ // Generate static version if enabled
1282
+ if (config.features?.staticOutput !== false) {
1283
+ console.log(chalk.blue('\n🌐 Generating static version (no auth, no private content)...'));
1284
+
1285
+ const staticOutputDir = path.join(process.cwd(), config.staticOutputDir || 'html-static');
1286
+
1287
+ // Ensure static output directory exists
1288
+ await fs.ensureDir(staticOutputDir);
1289
+
1290
+ // Get files excluding private directories
1291
+ const staticFiles = await getAllMarkdownFiles(docsDir, docsDir, { excludePrivate: true });
1292
+ console.log(chalk.gray(` Found ${staticFiles.length} public files (private files excluded)`));
1293
+
1294
+ // Process files for static output
1295
+ for (const file of staticFiles) {
1296
+ const outputPath = path.join(staticOutputDir, file.urlPath);
1297
+ await processMarkdownFile(file.path, outputPath, staticFiles, config, true);
1298
+ }
1299
+
1300
+ // Copy assets to static directory
1301
+ const assetsDir = path.join(__dirname, '../assets');
1302
+ const cssSource = path.join(assetsDir, 'css');
1303
+ const jsSource = path.join(assetsDir, 'js');
1304
+
1305
+ if (fs.existsSync(cssSource)) {
1306
+ await fs.copy(cssSource, path.join(staticOutputDir, 'css'), { overwrite: true });
1307
+ }
1308
+
1309
+ if (fs.existsSync(jsSource)) {
1310
+ await fs.copy(jsSource, path.join(staticOutputDir, 'js'), { overwrite: true });
1311
+ // Don't generate auth.js for static version
1312
+ }
1313
+
1314
+ // Copy 404.html for handling .md redirects
1315
+ const notFoundSource = path.join(assetsDir, '404.html');
1316
+ if (fs.existsSync(notFoundSource)) {
1317
+ await fs.copy(notFoundSource, path.join(staticOutputDir, '404.html'), { overwrite: true });
1318
+ }
1319
+
1320
+ // Create index.html from README.html or generate default
1321
+ const staticIndexPath = path.join(staticOutputDir, 'index.html');
1322
+ const staticReadmePath = path.join(staticOutputDir, 'README.html');
1323
+
1324
+ if (fs.existsSync(staticReadmePath)) {
1325
+ await fs.copy(staticReadmePath, staticIndexPath);
1326
+ } else if (staticFiles.length > 0) {
1327
+ // Generate a default index that lists available pages
1328
+ const defaultIndex = await createDefaultIndexPage(staticOutputDir, config, packageJson.version);
1329
+ await fs.writeFile(staticIndexPath, defaultIndex);
1330
+ }
1331
+
1332
+ // Copy attachments to static directory if enabled
1333
+ if (config.features?.attachments !== false) {
1334
+ const attachmentTypes = config.attachmentTypes || [
1335
+ '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.csv', '.ppt', '.pptx', '.txt', '.rtf',
1336
+ '.html', '.htm',
1337
+ '.zip', '.tar', '.gz', '.7z', '.rar',
1338
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico', '.bmp',
1339
+ '.json', '.xml', '.yaml', '.yml', '.toml',
1340
+ '.mp4', '.mp3', '.wav', '.avi', '.mov'
1341
+ ];
1342
+
1343
+ try {
1344
+ // Get attachment files excluding private directories
1345
+ const allAttachmentFiles = await getAllAttachmentFiles(docsDir, docsDir, attachmentTypes);
1346
+ const staticAttachmentFiles = [];
1347
+ for (const file of allAttachmentFiles) {
1348
+ if (!file.relativePath.startsWith('private/') && !file.relativePath.startsWith('private\\')) {
1349
+ staticAttachmentFiles.push(file);
1350
+ }
1351
+ }
1352
+
1353
+ if (staticAttachmentFiles.length > 0) {
1354
+ await copyAttachmentFiles(staticAttachmentFiles, docsDir, staticOutputDir);
1355
+ }
1356
+ } catch (error) {
1357
+ console.warn(chalk.yellow(`Warning: Error copying attachments to static output: ${error.message}`));
1358
+ }
1359
+ }
1360
+
1361
+ // Generate SEO files for static version if enabled
1362
+ if (config.seo?.enabled && config.seo?.siteUrl) {
1363
+ // Collect all HTML files for sitemap
1364
+ const staticPages = [];
1365
+ const walkDir = (dir, baseDir = '') => {
1366
+ const items = fs.readdirSync(dir);
1367
+ items.forEach(item => {
1368
+ const fullPath = path.join(dir, item);
1369
+ const stat = fs.statSync(fullPath);
1370
+ if (stat.isDirectory()) {
1371
+ walkDir(fullPath, path.join(baseDir, item));
1372
+ } else if (item.endsWith('.html')) {
1373
+ staticPages.push({
1374
+ path: baseDir ? path.join(baseDir, item) : item,
1375
+ modified: stat.mtime
1376
+ });
1377
+ }
1378
+ });
1379
+ };
1380
+
1381
+ walkDir(staticOutputDir);
1382
+
1383
+ if (config.seo.generateSitemap) {
1384
+ await generateSitemap(staticPages, config.seo.siteUrl, staticOutputDir);
1385
+ }
1386
+
1387
+ if (config.seo.generateRobotsTxt) {
1388
+ await generateRobotsTxt(config.seo.siteUrl, staticOutputDir, {
1389
+ hasAuthentication: false
1390
+ });
1391
+ }
1392
+ }
1393
+
1394
+ console.log(chalk.green(`āœ… Static version generated in ${config.staticOutputDir || 'html-static'}/`));
1395
+ }
1396
+
1237
1397
  console.log(chalk.green('\nāœ… Documentation build complete!'));
1238
1398
  }
1239
1399
 
@@ -1554,6 +1714,7 @@ module.exports = {
1554
1714
  buildDocumentation,
1555
1715
  processMarkdownContent,
1556
1716
  generateHTML,
1717
+ generateStaticHTML,
1557
1718
  createPlaceholderReadme,
1558
1719
  createDefaultIndexPage
1559
1720
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowcode/doc-builder",
3
- "version": "1.9.19",
3
+ "version": "1.9.21",
4
4
  "description": "Reusable documentation builder for markdown-based sites with Vercel deployment support",
5
5
  "main": "index.js",
6
6
  "bin": {