@knowcode/doc-builder 1.10.5 → 1.10.7

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.
@@ -605,19 +605,19 @@ pre code {
605
605
  }
606
606
 
607
607
  .nav-section[data-level="1"] {
608
- margin-left: var(--space-4);
608
+ margin-left: var(--space-2);
609
609
  margin-bottom: var(--space-0-5);
610
610
  }
611
611
 
612
612
  .nav-section[data-level="2"] {
613
- margin-left: var(--space-8);
613
+ margin-left: var(--space-4);
614
614
  margin-bottom: var(--space-0-5);
615
615
  }
616
616
 
617
617
  .nav-title {
618
618
  display: flex;
619
619
  align-items: center;
620
- padding: var(--space-1-5) var(--space-3);
620
+ padding: var(--space-0-5) var(--space-3);
621
621
  font-size: var(--text-sm);
622
622
  font-weight: var(--font-medium);
623
623
  color: var(--color-text-secondary);
@@ -629,11 +629,11 @@ pre code {
629
629
 
630
630
  /* Indent nav titles based on their level */
631
631
  .nav-section[data-level="1"] .nav-title {
632
- padding-left: calc(var(--space-3) + var(--space-4));
632
+ padding-left: calc(var(--space-3) + var(--space-2));
633
633
  }
634
634
 
635
635
  .nav-section[data-level="2"] .nav-title {
636
- padding-left: calc(var(--space-3) + var(--space-8));
636
+ padding-left: calc(var(--space-3) + var(--space-4));
637
637
  }
638
638
 
639
639
  .nav-title:hover {
@@ -668,27 +668,27 @@ pre code {
668
668
  .nav-item {
669
669
  display: flex;
670
670
  align-items: center;
671
- padding: var(--space-1-5) var(--space-3);
671
+ padding: var(--space-0-5) var(--space-3);
672
672
  font-size: var(--text-sm);
673
673
  color: var(--color-text-primary);
674
674
  text-decoration: none;
675
675
  border-radius: var(--radius-md);
676
676
  transition: all var(--duration-fast) var(--easing-out);
677
677
  margin-bottom: 0;
678
- gap: var(--space-2);
678
+ gap: var(--space-1);
679
679
  }
680
680
 
681
681
  /* Indent nav items based on their parent section level */
682
682
  .nav-section[data-level="0"] .nav-item {
683
- padding-left: calc(var(--space-3) + var(--space-6));
683
+ padding-left: calc(var(--space-3) + var(--space-3));
684
684
  }
685
685
 
686
686
  .nav-section[data-level="1"] .nav-item {
687
- padding-left: calc(var(--space-3) + var(--space-10));
687
+ padding-left: calc(var(--space-3) + var(--space-5));
688
688
  }
689
689
 
690
690
  .nav-section[data-level="2"] .nav-item {
691
- padding-left: calc(var(--space-3) + var(--space-12));
691
+ padding-left: calc(var(--space-3) + var(--space-6));
692
692
  }
693
693
 
694
694
  .nav-item:hover {
@@ -1031,7 +1031,8 @@ tr:hover {
1031
1031
  white-space: nowrap;
1032
1032
  }
1033
1033
 
1034
- /* PDF button in breadcrumbs */
1034
+ /* MD and PDF buttons in breadcrumbs */
1035
+ .breadcrumb-md-btn,
1035
1036
  .breadcrumb-pdf-btn {
1036
1037
  background: none;
1037
1038
  border: none;
@@ -1043,6 +1044,7 @@ tr:hover {
1043
1044
  font-size: 1rem;
1044
1045
  }
1045
1046
 
1047
+ .breadcrumb-md-btn:hover,
1046
1048
  .breadcrumb-pdf-btn:hover {
1047
1049
  background: var(--color-bg-tertiary);
1048
1050
  color: var(--color-text-primary);
@@ -1979,8 +1981,8 @@ tr:hover {
1979
1981
  .nav-title {
1980
1982
  display: flex;
1981
1983
  align-items: center;
1982
- gap: var(--space-2);
1983
- padding: var(--space-2);
1984
+ gap: var(--space-1);
1985
+ padding: var(--space-1);
1984
1986
  color: var(--color-text-primary);
1985
1987
  text-decoration: none;
1986
1988
  font-size: var(--text-sm);
@@ -2029,14 +2031,14 @@ tr:hover {
2029
2031
  .nav-item {
2030
2032
  display: flex;
2031
2033
  align-items: center;
2032
- gap: var(--space-2);
2033
- padding: var(--space-1-5) var(--space-2);
2034
+ gap: var(--space-1);
2035
+ padding: var(--space-0-5) var(--space-2);
2034
2036
  color: var(--color-text-secondary);
2035
2037
  text-decoration: none;
2036
2038
  font-size: var(--text-sm);
2037
2039
  border-radius: var(--radius-md);
2038
2040
  transition: all var(--duration-fast);
2039
- margin-bottom: var(--space-0-5);
2041
+ margin-bottom: 0;
2040
2042
  }
2041
2043
 
2042
2044
  .nav-item:hover {
package/assets/js/main.js CHANGED
@@ -1296,6 +1296,31 @@ function initNavigationFilter() {
1296
1296
  });
1297
1297
  }
1298
1298
 
1299
+ // Markdown Download functionality
1300
+ function downloadMarkdown() {
1301
+ // Get current page path and convert to .md
1302
+ let currentPath = window.location.pathname;
1303
+
1304
+ // Handle different path formats
1305
+ if (currentPath.endsWith('/')) {
1306
+ currentPath += 'index.html';
1307
+ }
1308
+ if (!currentPath.endsWith('.html')) {
1309
+ currentPath += '.html';
1310
+ }
1311
+
1312
+ // Replace .html with .md
1313
+ const mdPath = currentPath.replace(/\.html$/, '.md');
1314
+
1315
+ // Create a link and trigger download
1316
+ const link = document.createElement('a');
1317
+ link.href = mdPath;
1318
+ link.download = mdPath.split('/').pop(); // Get filename
1319
+ document.body.appendChild(link);
1320
+ link.click();
1321
+ document.body.removeChild(link);
1322
+ }
1323
+
1299
1324
  // PDF Export functionality
1300
1325
  function exportToPDF() {
1301
1326
  // Hide UI elements for printing
@@ -1588,6 +1613,9 @@ function generateBreadcrumbs() {
1588
1613
  <div class="breadcrumbs-content breadcrumbs-homepage">
1589
1614
  <div class="breadcrumbs-right">
1590
1615
  <span class="breadcrumb-date" title="Built with doc-builder v${docBuilderVersion || ''}">Last updated: ${displayDate}</span>
1616
+ <button class="breadcrumb-md-btn" onclick="downloadMarkdown()" title="Download Markdown" aria-label="Download Markdown">
1617
+ <i class="fas fa-file-code"></i>
1618
+ </button>
1591
1619
  <button class="breadcrumb-pdf-btn" onclick="exportToPDF()" title="Export to PDF" aria-label="Export to PDF">
1592
1620
  <i class="fas fa-file-pdf"></i>
1593
1621
  </button>
@@ -1605,6 +1633,9 @@ function generateBreadcrumbs() {
1605
1633
  </div>
1606
1634
  <div class="breadcrumbs-right">
1607
1635
  <span class="breadcrumb-date" title="Built with doc-builder v${docBuilderVersion || ''}">Last updated: ${displayDate}</span>
1636
+ <button class="breadcrumb-md-btn" onclick="downloadMarkdown()" title="Download Markdown" aria-label="Download Markdown">
1637
+ <i class="fas fa-file-code"></i>
1638
+ </button>
1608
1639
  <button class="breadcrumb-pdf-btn" onclick="exportToPDF()" title="Export to PDF" aria-label="Export to PDF">
1609
1640
  <i class="fas fa-file-pdf"></i>
1610
1641
  </button>
@@ -349,21 +349,16 @@ function processMarkdownContent(content, config = {}) {
349
349
 
350
350
  // Parse the markdown
351
351
  let html = marked.parse(processedContent);
352
-
352
+
353
353
  // Replace placeholders with actual mermaid blocks
354
354
  mermaidBlocks.forEach((block, index) => {
355
355
  html = html.replace(`<p>MERMAID_BLOCK_${index}</p>`, block);
356
356
  html = html.replace(`MERMAID_BLOCK_${index}`, block);
357
357
  });
358
-
359
- // Convert internal .md links to .html links
360
- // Matches href="...md" or href='...md' and converts to .html
361
- // Handles: file.md, path/file.md, file.md#anchor, file.md?query
362
- html = html.replace(/href=(["'])([^"']*?)\.md((?:#[^"']*)?(?:\?[^"']*)?)\1/gi, 'href=$1$2.html$3$1');
363
-
358
+
364
359
  // Replace emojis with Phosphor icons if enabled
365
360
  html = replaceEmojisWithIcons(html, config);
366
-
361
+
367
362
  return html;
368
363
  }
369
364
 
@@ -418,7 +413,12 @@ function generateHTML(title, content, navigation, currentPath = '', config = {},
418
413
  // Get doc-builder version from package.json
419
414
  const packageJson = require('../package.json');
420
415
  const docBuilderVersion = packageJson.version;
421
-
416
+
417
+ // Extract source metadata if available
418
+ const sourceMetadata = config._sourceMetadata || {};
419
+ const sourcePath = sourceMetadata.sourcePath || '';
420
+ const generatedAt = sourceMetadata.generatedAt || new Date().toISOString();
421
+
422
422
  // SEO preparation
423
423
  let seoTags = '';
424
424
  let jsonLd = '';
@@ -503,7 +503,11 @@ function generateHTML(title, content, navigation, currentPath = '', config = {},
503
503
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
504
504
  <meta name="description" content="${escapeHtml(pageDescription || generateDescription(originalContent || content) || siteDescription)}">
505
505
  <title>${escapeHtml(finalSeoTitle || `${title} - ${siteName}`)}</title>
506
-
506
+
507
+ <!-- Source metadata -->
508
+ ${sourcePath ? `<meta name="md-source" content="${escapeHtml(sourcePath)}">` : ''}
509
+ <meta name="doc-generated" content="${escapeHtml(generatedAt)}">
510
+
507
511
  ${seoTags}
508
512
 
509
513
  <!-- Fonts -->
@@ -796,6 +800,9 @@ ${seoTags}
796
800
  minute: '2-digit',
797
801
  timeZone: 'UTC'
798
802
  })} UTC</span>
803
+ <button class="breadcrumb-md-btn" onclick="downloadMarkdown()" title="Download Markdown" aria-label="Download Markdown">
804
+ <i class="fas fa-file-code"></i>
805
+ </button>
799
806
  <button class="breadcrumb-pdf-btn" onclick="if(typeof exportToPDF !== 'undefined') exportToPDF(); else window.print();" title="Export to PDF" aria-label="Export to PDF">
800
807
  <i class="fas fa-file-pdf"></i>
801
808
  </button>
@@ -838,6 +845,13 @@ ${seoTags}
838
845
  mermaidEnhanced: ${config.features?.mermaidEnhanced !== false}
839
846
  }
840
847
  };
848
+
849
+ // Source metadata for JS consumers
850
+ window.__DOC_SOURCE__ = {
851
+ mdSource: ${sourcePath ? `"${escapeHtml(sourcePath)}"` : 'null'},
852
+ generatedAt: "${escapeHtml(generatedAt)}",
853
+ docBuilderVersion: "${docBuilderVersion}"
854
+ };
841
855
  </script>
842
856
  <script src="${resourcePath}js/main.js"></script>
843
857
  ${(config.features?.authentication === 'supabase' || config.features?.privateDirectoryAuth === true) ? `<script src="https://unpkg.com/@supabase/supabase-js@2"></script>
@@ -1145,21 +1159,35 @@ async function processMarkdownFile(filePath, outputPath, allFiles, config, useSt
1145
1159
 
1146
1160
  // Process content
1147
1161
  const htmlContent = processMarkdownContent(content, config);
1148
-
1162
+
1163
+ // Create config with source metadata for HTML generation
1164
+ const generationTimestamp = new Date().toISOString();
1165
+ const htmlConfig = {
1166
+ ...config,
1167
+ _sourceMetadata: {
1168
+ sourcePath: relativePath, // e.g., "docs/technical/local-dev-troubleshooting.md"
1169
+ generatedAt: generationTimestamp
1170
+ }
1171
+ };
1172
+
1149
1173
  // Build navigation - pass config to handle private file filtering
1150
1174
  // For static HTML, we need to build navigation with relative paths
1151
- const navConfig = useStaticHTML ? { ...config, isStaticOutput: true } : config;
1175
+ const navConfig = useStaticHTML ? { ...htmlConfig, isStaticOutput: true } : htmlConfig;
1152
1176
  const navigation = buildNavigationStructure(allFiles, urlPath, navConfig);
1153
-
1177
+
1154
1178
  // Generate full HTML (pass original content and front matter for SEO)
1155
- const html = useStaticHTML
1156
- ? generateStaticHTML(title, htmlContent, navigation, urlPath, config, content, frontMatter)
1157
- : generateHTML(title, htmlContent, navigation, urlPath, config, content, frontMatter);
1179
+ const html = useStaticHTML
1180
+ ? generateStaticHTML(title, htmlContent, navigation, urlPath, htmlConfig, content, frontMatter)
1181
+ : generateHTML(title, htmlContent, navigation, urlPath, htmlConfig, content, frontMatter);
1158
1182
 
1159
1183
  // Write file
1160
1184
  await fs.ensureDir(path.dirname(outputPath));
1161
1185
  await fs.writeFile(outputPath, html);
1162
-
1186
+
1187
+ // Copy source .md file alongside HTML for download
1188
+ const mdOutputPath = outputPath.replace(/\.html$/, '.md');
1189
+ await fs.copyFile(filePath, mdOutputPath);
1190
+
1163
1191
  return { title, urlPath, summary, frontMatter };
1164
1192
  }
1165
1193
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowcode/doc-builder",
3
- "version": "1.10.5",
3
+ "version": "1.10.7",
4
4
  "description": "Reusable documentation builder for markdown-based sites with Vercel deployment support",
5
5
  "main": "index.js",
6
6
  "bin": {