@knowcode/doc-builder 1.9.8 → 1.9.9

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.
@@ -1,5 +1,5 @@
1
1
  module.exports = {
2
- "configVersion": "1.9.7",
2
+ "configVersion": "1.9.8",
3
3
  "docsDir": "docs",
4
4
  "outputDir": "html",
5
5
  "siteName": "@knowcode/doc-builder",
@@ -20,7 +20,8 @@ module.exports = {
20
20
  "menuDefaultOpen": false,
21
21
  "attachments": true,
22
22
  "dynamicNavIcons": true,
23
- "subtleColors": true
23
+ "subtleColors": true,
24
+ "privateDirectoryAuth": false
24
25
  },
25
26
  "auth": {
26
27
  "supabaseUrl": "https://xcihhnfcitjrwbynxmka.supabase.co",
@@ -0,0 +1,114 @@
1
+ module.exports = {
2
+ "configVersion": "1.9.7",
3
+ "docsDir": "docs",
4
+ "outputDir": "html",
5
+ "siteName": "@knowcode/doc-builder",
6
+ "siteDescription": "Beautiful documentation with the least effort possible",
7
+ "favicon": "✨",
8
+ "features": {
9
+ "authentication": false,
10
+ "changelog": true,
11
+ "mermaid": true,
12
+ "tooltips": true,
13
+ "search": false,
14
+ "darkMode": true,
15
+ "phosphorIcons": true,
16
+ "phosphorWeight": "regular",
17
+ "phosphorSize": "1.2em",
18
+ "normalizeTitle": true,
19
+ "showPdfDownload": true,
20
+ "menuDefaultOpen": false,
21
+ "attachments": true,
22
+ "dynamicNavIcons": true,
23
+ "subtleColors": true
24
+ },
25
+ "auth": {
26
+ "supabaseUrl": "https://xcihhnfcitjrwbynxmka.supabase.co",
27
+ "supabaseAnonKey": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InhjaWhobmZjaXRqcndieW54bWthIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTM0Mzc2MzcsImV4cCI6MjA2OTAxMzYzN30.zvWp3JFIR8fBIiwuFF5gqOR_Kxb42baZS5fsBz60XOY"
28
+ },
29
+ "changelog": {
30
+ "daysBack": 14,
31
+ "enabled": true
32
+ },
33
+ "folderOrder": [],
34
+ "folderDescriptions": {},
35
+ "folderIcons": {},
36
+ "deployment": {
37
+ "platform": "vercel",
38
+ "outputDirectory": "html"
39
+ },
40
+ "seo": {
41
+ "enabled": true,
42
+ "siteUrl": "https://doc-builder-delta.vercel.app",
43
+ "author": "Lindsay Smith",
44
+ "twitterHandle": "@planbbackups",
45
+ "language": "en-US",
46
+ "keywords": [
47
+ "documentation",
48
+ "markdown",
49
+ "static site generator",
50
+ "vercel",
51
+ "notion-style"
52
+ ],
53
+ "titleTemplate": "{pageTitle} | {siteName}",
54
+ "autoKeywords": true,
55
+ "keywordLimit": 7,
56
+ "descriptionFallback": "smart",
57
+ "organization": {
58
+ "name": "Knowcode Ltd",
59
+ "url": "https://knowcode.tech",
60
+ "logo": ""
61
+ },
62
+ "ogImage": "/og-default.png",
63
+ "generateSitemap": true,
64
+ "generateRobotsTxt": true,
65
+ "customMetaTags": [
66
+ {
67
+ "name": "google-site-verification",
68
+ "content": "FtzcDTf5BQ9K5EfnGazQkgU2U4FiN3ITzM7gHwqUAqQ"
69
+ },
70
+ {
71
+ "name": "msvalidate.01",
72
+ "content": "B2D8C4C12C530D47AA962B24CAA09630"
73
+ }
74
+ ]
75
+ },
76
+ "attachmentTypes": [
77
+ ".pdf",
78
+ ".doc",
79
+ ".docx",
80
+ ".xls",
81
+ ".xlsx",
82
+ ".csv",
83
+ ".ppt",
84
+ ".pptx",
85
+ ".txt",
86
+ ".rtf",
87
+ ".html",
88
+ ".htm",
89
+ ".zip",
90
+ ".tar",
91
+ ".gz",
92
+ ".7z",
93
+ ".rar",
94
+ ".png",
95
+ ".jpg",
96
+ ".jpeg",
97
+ ".gif",
98
+ ".svg",
99
+ ".webp",
100
+ ".ico",
101
+ ".bmp",
102
+ ".json",
103
+ ".xml",
104
+ ".yaml",
105
+ ".yml",
106
+ ".toml",
107
+ ".mp4",
108
+ ".mp3",
109
+ ".wav",
110
+ ".avi",
111
+ ".mov"
112
+ ],
113
+ "productionUrl": "https://doc-builder-delta.vercel.app"
114
+ };
package/lib/config.js CHANGED
@@ -38,7 +38,8 @@ const defaultConfig = {
38
38
  menuDefaultOpen: true, // Menu/sidebar open by default
39
39
  attachments: true, // Copy attachments (Excel, PDF, etc.) to output
40
40
  dynamicNavIcons: true, // Use status-based icons in navigation
41
- subtleColors: true // Apply subtle colors to status icons
41
+ subtleColors: true, // Apply subtle colors to status icons
42
+ privateDirectoryAuth: false // Enable auth for private directories only (auto-detected)
42
43
  },
43
44
 
44
45
  // Authentication - Supabase only (basic auth removed for security)
@@ -427,15 +428,19 @@ async function loadConfig(configPath, options = {}) {
427
428
  }
428
429
  // Don't throw error - let commands handle missing directories appropriately
429
430
  } else {
430
- // Check for private directory and auto-enable authentication if found
431
+ // Check for private directory to inform user about authentication options
431
432
  const privatePath = path.join(docsPath, 'private');
432
433
  if (fs.existsSync(privatePath) && fs.statSync(privatePath).isDirectory()) {
433
- // Auto-enable authentication when private directory exists
434
- // This overrides any config setting to ensure private directories are always protected
435
- console.log(chalk.blue('🔐 Found private directory - automatically enabling Supabase authentication'));
436
- config.features.authentication = 'supabase';
437
- config.features.autoAuthEnabled = true; // Track that this was auto-enabled
438
- console.log(chalk.yellow(' Note: Grant users access by adding domain to the docbuilder_access table'));
434
+ if (config.features.authentication === 'supabase') {
435
+ console.log(chalk.blue('🔐 Found private directory - global Supabase authentication is enabled'));
436
+ console.log(chalk.yellow(' Note: Grant users access by adding domain to the docbuilder_access table'));
437
+ } else {
438
+ console.log(chalk.blue('🔐 Found private directory - will be protected with Supabase authentication'));
439
+ console.log(chalk.gray(' Public pages remain accessible, only /private/ pages require login'));
440
+ console.log(chalk.yellow(' Note: Grant users access by adding domain to the docbuilder_access table'));
441
+ // Set a flag to indicate private directory authentication is needed
442
+ config.features.privateDirectoryAuth = true;
443
+ }
439
444
  }
440
445
  }
441
446
 
@@ -452,7 +452,7 @@ ${seoTags}
452
452
  <!-- Styles -->
453
453
  <link rel="stylesheet" href="/css/notion-style.css">
454
454
 
455
- ${config.features?.authentication === 'supabase' ? `
455
+ ${(config.features?.authentication === 'supabase' || config.features?.privateDirectoryAuth === true) ? `
456
456
  <!-- Hide content until auth check -->
457
457
  <style>
458
458
  body {
@@ -510,7 +510,7 @@ ${seoTags}
510
510
  })} UTC</span>
511
511
  </div>
512
512
 
513
- ${config.features?.authentication === 'supabase' ? `
513
+ ${(config.features?.authentication === 'supabase' || config.features?.privateDirectoryAuth === true) ? `
514
514
  <a href="${relativePath}login.html" class="auth-btn" title="Login/Logout">
515
515
  <i class="fas fa-sign-in-alt"></i>
516
516
  </a>
@@ -578,7 +578,7 @@ ${seoTags}
578
578
  };
579
579
  </script>
580
580
  <script src="/js/main.js"></script>
581
- ${config.features?.authentication === 'supabase' ? `<script src="https://unpkg.com/@supabase/supabase-js@2"></script>
581
+ ${(config.features?.authentication === 'supabase' || config.features?.privateDirectoryAuth === true) ? `<script src="https://unpkg.com/@supabase/supabase-js@2"></script>
582
582
  <script src="/js/auth.js"></script>` : ''}
583
583
  </body>
584
584
  </html>`;
@@ -609,8 +609,8 @@ const folderDescriptions = {
609
609
  function buildNavigationStructure(files, currentFile, config = {}) {
610
610
  const tree = { files: [], folders: {} };
611
611
 
612
- // Check if authentication is enabled
613
- const isAuthEnabled = config.features?.authentication === 'supabase';
612
+ // Check if authentication is enabled (either global or private directory)
613
+ const isAuthEnabled = config.features?.authentication === 'supabase' || config.features?.privateDirectoryAuth === true;
614
614
 
615
615
  // Include all files in navigation - we'll use CSS to show/hide based on auth state
616
616
  files.forEach(file => {
@@ -1014,8 +1014,8 @@ async function buildDocumentation(config) {
1014
1014
  if (fs.existsSync(jsSource)) {
1015
1015
  await fs.copy(jsSource, path.join(outputDir, 'js'), { overwrite: true });
1016
1016
 
1017
- // Generate Supabase auth script if authentication is enabled
1018
- if (config.features?.authentication === 'supabase') {
1017
+ // Generate Supabase auth script if authentication is needed (global or private directory)
1018
+ if (config.features?.authentication === 'supabase' || config.features?.privateDirectoryAuth === true) {
1019
1019
  await generateSupabaseAuthFiles(outputDir, config);
1020
1020
  }
1021
1021
  }
@@ -1155,7 +1155,7 @@ async function buildDocumentation(config) {
1155
1155
  // Generate robots.txt if enabled
1156
1156
  if (config.seo.generateRobotsTxt) {
1157
1157
  await generateRobotsTxt(config.seo.siteUrl, outputDir, {
1158
- hasAuthentication: config.features?.authentication === 'supabase'
1158
+ hasAuthentication: config.features?.authentication === 'supabase' || config.features?.privateDirectoryAuth === true
1159
1159
  });
1160
1160
  }
1161
1161
  }
@@ -56,8 +56,9 @@ class SupabaseAuth {
56
56
  // Check authentication and site access
57
57
  async function checkAuth() {
58
58
  try {
59
- // Check if global authentication is enabled
59
+ // Check authentication mode
60
60
  const isGlobalAuthEnabled = ${fullConfig.features?.authentication === 'supabase'};
61
+ const isPrivateDirectoryAuthEnabled = ${fullConfig.features?.privateDirectoryAuth === true};
61
62
 
62
63
  // Check if current page is in private directory
63
64
  const currentPath = window.location.pathname;
@@ -67,11 +68,11 @@ class SupabaseAuth {
67
68
  const { data: { user }, error: userError } = await supabaseClient.auth.getUser();
68
69
 
69
70
  if (userError || !user) {
70
- // Redirect if global auth is enabled OR if we're on a private page
71
- if (isGlobalAuthEnabled || isPrivatePage) {
71
+ // Redirect if global auth is enabled OR if we're on a private page with private auth enabled
72
+ if (isGlobalAuthEnabled || (isPrivateDirectoryAuthEnabled && isPrivatePage)) {
72
73
  redirectToLogin();
73
74
  } else {
74
- // Truly public page (no global auth and not private)
75
+ // Public page (no global auth and either no private auth or not on private page)
75
76
  document.body.classList.add('authenticated'); // Use same class to show body
76
77
  updateAuthButton(false);
77
78
  }
@@ -87,7 +88,7 @@ class SupabaseAuth {
87
88
  .single();
88
89
 
89
90
  if (accessError || !access) {
90
- if (isGlobalAuthEnabled || isPrivatePage) {
91
+ if (isGlobalAuthEnabled || (isPrivateDirectoryAuthEnabled && isPrivatePage)) {
91
92
  showAccessDenied();
92
93
  } else {
93
94
  // Public page, show it but don't grant private navigation access
@@ -97,16 +98,21 @@ class SupabaseAuth {
97
98
  return;
98
99
  }
99
100
 
100
- // User is authenticated and has domain access - grant full access including private nav
101
+ // User is authenticated and has domain access - grant appropriate access
101
102
  console.log('User authenticated and authorized');
102
103
  document.body.classList.add('authenticated');
103
- document.body.classList.add('has-private-access'); // Grant private navigation access
104
+
105
+ // Grant private navigation access if private directory auth is enabled
106
+ if (isPrivateDirectoryAuthEnabled || isGlobalAuthEnabled) {
107
+ document.body.classList.add('has-private-access');
108
+ }
109
+
104
110
  updateAuthButton(true);
105
111
 
106
112
  } catch (error) {
107
113
  console.error('Auth check failed:', error);
108
- const isGlobalAuthEnabled = ${fullConfig.features?.authentication === 'supabase'};
109
- if (isGlobalAuthEnabled || window.location.pathname.includes('/private/')) {
114
+ const isPrivatePage = window.location.pathname.includes('/private/');
115
+ if (isGlobalAuthEnabled || (isPrivateDirectoryAuthEnabled && isPrivatePage)) {
110
116
  redirectToLogin();
111
117
  } else {
112
118
  // Public page, show it anyway
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowcode/doc-builder",
3
- "version": "1.9.8",
3
+ "version": "1.9.9",
4
4
  "description": "Reusable documentation builder for markdown-based sites with Vercel deployment support",
5
5
  "main": "index.js",
6
6
  "bin": {