@knowcode/doc-builder 1.3.15 → 1.4.1

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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,46 @@ All notable changes to @knowcode/doc-builder will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.4.1] - 2025-07-20
9
+
10
+ ### Fixed
11
+ - **Critical CSS layout fix** - Content no longer appears too far right when sidebar is hidden
12
+ - Removed incorrect `margin-left: var(--sidebar-width)` from `.content` class
13
+ - Fixed responsive layout issues where content had excessive right spacing
14
+ - Simplified responsive styles to match original working version
15
+ - Fixed mobile padding to use single value `var(--space-4)` instead of directional padding
16
+
17
+ ### Technical Details
18
+ - Content now uses flexbox `flex: 1` without margin-left
19
+ - Removed unnecessary `transition: margin-left` from content
20
+ - Mobile styles simplified to only adjust padding, no margin overrides needed
21
+ - Layout now properly responds when sidebar is hidden on mobile/tablet
22
+
23
+ ## [1.4.0] - 2025-07-20
24
+
25
+ ### Added
26
+ - **Tooltip functionality restored** - Added summary extraction from markdown files
27
+ - Tooltips now appear on hover for navigation items showing content preview
28
+ - `extractSummary()` function looks for Overview/Summary sections or first paragraph
29
+ - Summaries are collected in first pass and added as `data-tooltip` attributes
30
+
31
+ ### Fixed
32
+ - **CSS layout restored to match original** - Reverted all layout changes to original values
33
+ - Header height restored to 64px (was 56px)
34
+ - Main wrapper uses margin-top approach (not absolute positioning)
35
+ - Content uses original padding values (var(--space-6) var(--space-8))
36
+ - Content-inner uses centered layout (margin: 0 auto)
37
+ - Navigation padding restored to all sides
38
+
39
+ ### Removed
40
+ - Removed unused style.css file - only notion-style.css is used
41
+ - Eliminated dual CSS file confusion
42
+
43
+ ### Technical Details
44
+ - Summary extraction matches original build.js implementation
45
+ - Navigation generation passes summaries through recursive renderSection calls
46
+ - Tooltips use same CSS implementation as original with fixed positioning
47
+
8
48
  ## [1.3.14] - 2025-07-20
9
49
 
10
50
  ### Fixed
@@ -125,7 +125,7 @@
125
125
  /* Layout */
126
126
  --container-padding-mobile: 20px;
127
127
  --container-padding-desktop: 40px;
128
- --header-height: 56px;
128
+ --header-height: 64px;
129
129
  --breadcrumb-height: 40px;
130
130
  --sidebar-width: 280px;
131
131
  }
@@ -469,17 +469,15 @@ pre code {
469
469
 
470
470
  /* Main Wrapper */
471
471
  .main-wrapper {
472
- position: absolute;
473
- top: calc(var(--header-height) + var(--breadcrumb-height));
474
- left: 0;
475
- right: 0;
476
- bottom: 0;
477
472
  display: flex;
473
+ height: calc(100vh - var(--header-height) - var(--breadcrumb-height));
474
+ margin-top: calc(var(--header-height) + var(--breadcrumb-height));
478
475
  overflow: hidden;
479
476
  }
480
477
 
481
478
  .main-wrapper.banner-visible {
482
- top: calc(var(--header-height) + var(--breadcrumb-height) + 3.5rem);
479
+ height: calc(100vh - var(--header-height) - var(--breadcrumb-height) - 3.5rem);
480
+ margin-top: calc(var(--header-height) + var(--breadcrumb-height) + 3.5rem);
483
481
  }
484
482
 
485
483
  /* Sidebar */
@@ -530,7 +528,7 @@ pre code {
530
528
  /* Navigation */
531
529
  .navigation {
532
530
  flex: 1;
533
- padding: 0 var(--space-2) var(--space-2) var(--space-2); /* No top padding */
531
+ padding: var(--space-2);
534
532
  overflow-y: auto;
535
533
  overflow-x: visible;
536
534
 
@@ -689,16 +687,14 @@ pre code {
689
687
 
690
688
  .content {
691
689
  flex: 1;
692
- margin-left: var(--sidebar-width);
693
- padding: var(--space-2) var(--space-8) var(--space-4); /* Reduced top padding */
690
+ padding: var(--space-6) var(--space-8);
694
691
  overflow-y: auto;
695
692
  background: var(--color-bg-default);
696
- transition: margin-left var(--duration-normal);
697
693
  }
698
694
 
699
695
  .content-inner {
700
696
  max-width: 65rem;
701
- margin: 0; /* Left aligned instead of centered */
697
+ margin: 0 auto;
702
698
  }
703
699
 
704
700
  /* Tables */
@@ -1031,9 +1027,7 @@ tr:hover {
1031
1027
  }
1032
1028
 
1033
1029
  .content {
1034
- margin-left: 0 !important;
1035
- padding: var(--space-2) var(--space-4) var(--space-4); /* Reduced top padding */
1036
- max-width: 100%;
1030
+ padding: var(--space-6) var(--space-4);
1037
1031
  }
1038
1032
 
1039
1033
  .menu-toggle {
@@ -1660,9 +1654,8 @@ tr:hover {
1660
1654
  }
1661
1655
 
1662
1656
  .main-wrapper {
1663
- position: relative; /* Change back to relative for mobile */
1664
- top: 0;
1665
1657
  flex-direction: column;
1658
+ height: auto;
1666
1659
  min-height: calc(100vh - var(--header-height) - var(--breadcrumb-height));
1667
1660
  }
1668
1661
 
@@ -1674,9 +1667,7 @@ tr:hover {
1674
1667
  }
1675
1668
 
1676
1669
  .content {
1677
- margin-left: 0 !important;
1678
- padding: var(--space-2) var(--space-4) var(--space-4); /* Reduced top padding */
1679
- max-width: 100%;
1670
+ padding: var(--space-4);
1680
1671
  }
1681
1672
 
1682
1673
  .content-inner {
Binary file
@@ -24,6 +24,44 @@ function escapeHtml(text) {
24
24
  return text.replace(/[&<>"']/g, m => map[m]);
25
25
  }
26
26
 
27
+ // Extract summary from markdown content
28
+ function extractSummary(content) {
29
+ // Look for ## Overview or ## Summary section
30
+ const overviewMatch = content.match(/##\s+(?:Overview|Summary)\s*\n([\s\S]*?)(?=\n##|$)/i);
31
+ if (overviewMatch) {
32
+ // Get first paragraph or up to 200 characters
33
+ const text = overviewMatch[1].trim();
34
+ const firstPara = text.split('\n\n')[0];
35
+ return firstPara.length > 200 ? firstPara.substring(0, 200) + '...' : firstPara;
36
+ }
37
+
38
+ // Fallback: get first paragraph after title
39
+ const lines = content.split('\n');
40
+ let foundContent = false;
41
+ let summary = '';
42
+
43
+ for (const line of lines) {
44
+ // Skip title lines
45
+ if (line.startsWith('#')) continue;
46
+ // Skip metadata lines
47
+ if (line.includes('**Generated**:') || line.includes('**Status**:') || line.includes('**Verified**:')) continue;
48
+ // Skip empty lines until we find content
49
+ if (!foundContent && line.trim() === '') continue;
50
+
51
+ if (line.trim()) {
52
+ foundContent = true;
53
+ summary += line + ' ';
54
+ if (summary.length > 200) break;
55
+ } else if (foundContent) {
56
+ // Found end of first paragraph
57
+ break;
58
+ }
59
+ }
60
+
61
+ summary = summary.trim();
62
+ return summary.length > 200 ? summary.substring(0, 200) + '...' : summary;
63
+ }
64
+
27
65
  // Process markdown content
28
66
  function processMarkdownContent(content) {
29
67
  // Convert mermaid code blocks to mermaid divs with titles
@@ -194,7 +232,7 @@ const folderDescriptions = {
194
232
  };
195
233
 
196
234
  // Build navigation structure with rich functionality
197
- function buildNavigationStructure(files, currentFile) {
235
+ function buildNavigationStructure(files, currentFile, summaries = {}) {
198
236
  const tree = { files: [], folders: {} };
199
237
 
200
238
  files.forEach(file => {
@@ -241,7 +279,7 @@ function buildNavigationStructure(files, currentFile) {
241
279
  };
242
280
 
243
281
  // Helper function to render a section
244
- const renderSection = (folderName, folderData, level = 0, parentPath = '') => {
282
+ const renderSection = (folderName, folderData, level = 0, parentPath = '', summaries = {}) => {
245
283
  const icons = {
246
284
  'root': 'fas fa-home',
247
285
  'product-roadmap': 'fas fa-road',
@@ -318,8 +356,12 @@ function buildNavigationStructure(files, currentFile) {
318
356
 
319
357
  const linkPath = '/' + file.urlPath;
320
358
 
359
+ // Get summary for tooltip
360
+ const summary = summaries[file.urlPath] || '';
361
+ const tooltipAttr = summary ? `data-tooltip="${escapeHtml(summary)}"` : '';
362
+
321
363
  html += `
322
- <a href="${linkPath}" class="nav-item${isActive}"><i class="fas fa-file-alt"></i> ${title}</a>`;
364
+ <a href="${linkPath}" class="nav-item${isActive}" ${tooltipAttr}><i class="fas fa-file-alt"></i> ${title}</a>`;
323
365
  });
324
366
 
325
367
  html += `</div></div>`;
@@ -330,7 +372,7 @@ function buildNavigationStructure(files, currentFile) {
330
372
  .forEach(subFolder => {
331
373
  // Build the path for the subfolder including current folder
332
374
  const currentPath = parentPath ? `${parentPath}-${folderName}` : folderName;
333
- html += renderSection(subFolder, folderData.folders[subFolder], level + 1, currentPath);
375
+ html += renderSection(subFolder, folderData.folders[subFolder], level + 1, currentPath, summaries);
334
376
  });
335
377
 
336
378
  return html;
@@ -341,14 +383,14 @@ function buildNavigationStructure(files, currentFile) {
341
383
 
342
384
  if (!hasFolders) {
343
385
  // Generate simple flat navigation for all files in root
344
- return renderSection('root', { files: tree.files, folders: {} }, 0);
386
+ return renderSection('root', { files: tree.files, folders: {} }, 0, '', summaries);
345
387
  } else {
346
388
  // Generate hierarchical navigation
347
389
  let nav = '';
348
390
 
349
391
  // Render root files first
350
392
  if (tree.files.length > 0) {
351
- nav += renderSection('root', { files: tree.files, folders: {} }, 0);
393
+ nav += renderSection('root', { files: tree.files, folders: {} }, 0, '', summaries);
352
394
  }
353
395
 
354
396
  // Add other top-level folders in logical order
@@ -371,7 +413,7 @@ function buildNavigationStructure(files, currentFile) {
371
413
 
372
414
  folderOrder.forEach(folderName => {
373
415
  if (tree.folders[folderName]) {
374
- nav += renderSection(folderName, tree.folders[folderName], 1);
416
+ nav += renderSection(folderName, tree.folders[folderName], 1, '', summaries);
375
417
  delete tree.folders[folderName]; // Remove so we don't render it again
376
418
  }
377
419
  });
@@ -380,7 +422,7 @@ function buildNavigationStructure(files, currentFile) {
380
422
  Object.keys(tree.folders)
381
423
  .sort()
382
424
  .forEach(folderName => {
383
- nav += renderSection(folderName, tree.folders[folderName], 1);
425
+ nav += renderSection(folderName, tree.folders[folderName], 1, '', summaries);
384
426
  });
385
427
 
386
428
  return nav;
@@ -388,7 +430,7 @@ function buildNavigationStructure(files, currentFile) {
388
430
  }
389
431
 
390
432
  // Process single markdown file
391
- async function processMarkdownFile(filePath, outputPath, allFiles, config) {
433
+ async function processMarkdownFile(filePath, outputPath, allFiles, config, summaries = {}) {
392
434
  const content = await fs.readFile(filePath, 'utf-8');
393
435
  const fileName = path.basename(filePath, '.md');
394
436
  const relativePath = path.relative(config.docsDir, filePath);
@@ -402,7 +444,7 @@ async function processMarkdownFile(filePath, outputPath, allFiles, config) {
402
444
  const htmlContent = processMarkdownContent(content);
403
445
 
404
446
  // Build navigation
405
- const navigation = buildNavigationStructure(allFiles, urlPath);
447
+ const navigation = buildNavigationStructure(allFiles, urlPath, summaries);
406
448
 
407
449
  // Generate full HTML
408
450
  const html = generateHTML(title, htmlContent, navigation, urlPath, config);
@@ -470,10 +512,21 @@ async function buildDocumentation(config) {
470
512
  });
471
513
  }
472
514
 
515
+ // First pass: collect summaries
516
+ console.log(chalk.blue('📊 Extracting summaries...'));
517
+ const summaries = {};
518
+ for (const file of files) {
519
+ const content = await fs.readFile(file.path, 'utf-8');
520
+ const summary = extractSummary(content);
521
+ if (summary) {
522
+ summaries[file.urlPath] = summary;
523
+ }
524
+ }
525
+
473
526
  console.log(chalk.blue('📝 Processing files...'));
474
527
  for (const file of files) {
475
528
  const outputPath = path.join(outputDir, file.urlPath);
476
- await processMarkdownFile(file.path, outputPath, files, config);
529
+ await processMarkdownFile(file.path, outputPath, files, config, summaries);
477
530
  console.log(chalk.green(`✅ Generated: ${outputPath}`));
478
531
  }
479
532
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowcode/doc-builder",
3
- "version": "1.3.15",
3
+ "version": "1.4.1",
4
4
  "description": "Reusable documentation builder for markdown-based sites with Vercel deployment support",
5
5
  "main": "index.js",
6
6
  "bin": {