@knowcode/doc-builder 1.1.11 → 1.2.0
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 +58 -0
- package/assets/css/notion-style.css +282 -32
- package/lib/core-builder.js +217 -66
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,64 @@ 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.2.0] - 2025-07-19
|
|
9
|
+
|
|
10
|
+
### Added (MAJOR FEATURE RELEASE)
|
|
11
|
+
- **Complete feature parity** with original JUNO documentation system
|
|
12
|
+
- **Preview banner** with dismissible functionality and localStorage
|
|
13
|
+
- **Breadcrumb navigation** automatically generated from URL structure
|
|
14
|
+
- **Advanced sidebar** with filter/search functionality
|
|
15
|
+
- **Hierarchical navigation** with collapsible folders and proper icons
|
|
16
|
+
- **Rich tooltip system** with folder descriptions and hover information
|
|
17
|
+
- **Resize handle** for adjustable sidebar width
|
|
18
|
+
- **Icon mapping** for different content types and folders
|
|
19
|
+
- **Folder descriptions** for better UX and navigation
|
|
20
|
+
- **Logical folder ordering** (strategic content first, technical content later)
|
|
21
|
+
|
|
22
|
+
### Enhanced Navigation Features
|
|
23
|
+
- **Smart folder detection** and hierarchical structuring
|
|
24
|
+
- **Active section auto-expansion** for current page context
|
|
25
|
+
- **Collapsible navigation sections** with smooth animations
|
|
26
|
+
- **File type icons** (documents, folders, special content types)
|
|
27
|
+
- **Improved file naming** and title generation
|
|
28
|
+
- **README.md as folder overviews** with proper linking
|
|
29
|
+
- **Filter/search** through navigation items
|
|
30
|
+
|
|
31
|
+
### Layout Improvements
|
|
32
|
+
- **Complete layout restructure** matching original design
|
|
33
|
+
- **Fixed positioning** for banner, breadcrumbs, and sidebar
|
|
34
|
+
- **Responsive design** with mobile-friendly collapsible layout
|
|
35
|
+
- **Proper content area** with max-width and centered layout
|
|
36
|
+
- **Smooth transitions** and hover effects throughout
|
|
37
|
+
- **Dark mode support** for all new components
|
|
38
|
+
|
|
39
|
+
### Technical Enhancements
|
|
40
|
+
- **Rich HTML structure** with semantic navigation
|
|
41
|
+
- **CSS Grid and Flexbox** layout system
|
|
42
|
+
- **Modern CSS variables** and consistent spacing
|
|
43
|
+
- **Optimized mobile experience** with adaptive layouts
|
|
44
|
+
- **Performance optimized** animations and transitions
|
|
45
|
+
|
|
46
|
+
## [1.1.12] - 2025-07-19
|
|
47
|
+
|
|
48
|
+
### Fixed (MAJOR)
|
|
49
|
+
- **Fixed sidebar layout** - Navigation now appears as fixed-width left sidebar instead of above content
|
|
50
|
+
- Added proper flexbox container layout with fixed sidebar positioning
|
|
51
|
+
- Navigation is now 280px fixed width on left side with proper scrolling
|
|
52
|
+
- Content area properly offset to account for sidebar width
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
- Container flexbox layout for proper sidebar + content structure
|
|
56
|
+
- Fixed navigation positioning with proper z-index and boundaries
|
|
57
|
+
- Mobile responsive layout - sidebar becomes horizontal bar on mobile
|
|
58
|
+
- Proper scrolling for both navigation and content areas
|
|
59
|
+
|
|
60
|
+
### Visual Changes
|
|
61
|
+
- Navigation background set to secondary color with right border
|
|
62
|
+
- Content area now takes full remaining width after sidebar
|
|
63
|
+
- Proper spacing and padding for both sidebar and content
|
|
64
|
+
- Mobile layout stacks navigation above content
|
|
65
|
+
|
|
8
66
|
## [1.1.11] - 2025-07-19
|
|
9
67
|
|
|
10
68
|
### Fixed (MAJOR)
|
|
@@ -372,19 +372,194 @@ pre code {
|
|
|
372
372
|
font-size: var(--text-sm);
|
|
373
373
|
}
|
|
374
374
|
|
|
375
|
+
/* Preview Banner */
|
|
376
|
+
.preview-banner {
|
|
377
|
+
background: var(--color-accent-yellow-bg);
|
|
378
|
+
border-bottom: 1px solid var(--color-accent-yellow);
|
|
379
|
+
color: var(--color-text-primary);
|
|
380
|
+
padding: var(--space-2) 0;
|
|
381
|
+
position: fixed;
|
|
382
|
+
top: var(--header-height);
|
|
383
|
+
left: 0;
|
|
384
|
+
right: 0;
|
|
385
|
+
z-index: 1000;
|
|
386
|
+
transition: transform var(--duration-normal);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.preview-banner.hidden {
|
|
390
|
+
transform: translateY(-100%);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.banner-content {
|
|
394
|
+
display: flex;
|
|
395
|
+
align-items: center;
|
|
396
|
+
justify-content: center;
|
|
397
|
+
gap: var(--space-2);
|
|
398
|
+
max-width: 1400px;
|
|
399
|
+
margin: 0 auto;
|
|
400
|
+
padding: 0 var(--space-4);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.banner-icon {
|
|
404
|
+
color: var(--color-accent-yellow);
|
|
405
|
+
font-size: var(--text-sm);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.banner-text {
|
|
409
|
+
font-size: var(--text-sm);
|
|
410
|
+
font-weight: var(--font-medium);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.banner-dismiss {
|
|
414
|
+
background: none;
|
|
415
|
+
border: none;
|
|
416
|
+
color: var(--color-text-secondary);
|
|
417
|
+
cursor: pointer;
|
|
418
|
+
padding: var(--space-1);
|
|
419
|
+
margin-left: auto;
|
|
420
|
+
border-radius: var(--radius-sm);
|
|
421
|
+
transition: all var(--duration-fast);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.banner-dismiss:hover {
|
|
425
|
+
background: var(--color-bg-hover);
|
|
426
|
+
color: var(--color-text-primary);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/* Breadcrumbs */
|
|
430
|
+
.breadcrumbs {
|
|
431
|
+
background: var(--color-bg-default);
|
|
432
|
+
border-bottom: 1px solid var(--color-border-default);
|
|
433
|
+
padding: var(--space-2) 0;
|
|
434
|
+
position: fixed;
|
|
435
|
+
top: calc(var(--header-height) + 3.5rem);
|
|
436
|
+
left: 0;
|
|
437
|
+
right: 0;
|
|
438
|
+
z-index: 900;
|
|
439
|
+
transition: top var(--duration-normal);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.breadcrumbs.banner-visible {
|
|
443
|
+
top: calc(var(--header-height) + 3.5rem);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.breadcrumbs:not(.banner-visible) {
|
|
447
|
+
top: var(--header-height);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.breadcrumb-item {
|
|
451
|
+
display: inline-flex;
|
|
452
|
+
align-items: center;
|
|
453
|
+
gap: var(--space-1);
|
|
454
|
+
color: var(--color-text-secondary);
|
|
455
|
+
text-decoration: none;
|
|
456
|
+
font-size: var(--text-sm);
|
|
457
|
+
padding: var(--space-1) var(--space-2);
|
|
458
|
+
border-radius: var(--radius-sm);
|
|
459
|
+
transition: all var(--duration-fast);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.breadcrumb-item:hover {
|
|
463
|
+
background: var(--color-bg-hover);
|
|
464
|
+
color: var(--color-text-primary);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.breadcrumb-item.current {
|
|
468
|
+
color: var(--color-text-primary);
|
|
469
|
+
font-weight: var(--font-medium);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.breadcrumb-separator {
|
|
473
|
+
color: var(--color-text-tertiary);
|
|
474
|
+
font-size: var(--text-xs);
|
|
475
|
+
margin: 0 var(--space-1);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/* Main Wrapper */
|
|
479
|
+
.main-wrapper {
|
|
480
|
+
display: flex;
|
|
481
|
+
height: calc(100vh - var(--header-height) - var(--breadcrumb-height));
|
|
482
|
+
margin-top: calc(var(--header-height) + var(--breadcrumb-height));
|
|
483
|
+
overflow: hidden;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.main-wrapper.banner-visible {
|
|
487
|
+
height: calc(100vh - var(--header-height) - var(--breadcrumb-height) - 3.5rem);
|
|
488
|
+
margin-top: calc(var(--header-height) + var(--breadcrumb-height) + 3.5rem);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/* Sidebar */
|
|
492
|
+
.sidebar {
|
|
493
|
+
width: var(--sidebar-width);
|
|
494
|
+
background: var(--color-bg-secondary);
|
|
495
|
+
border-right: 1px solid var(--color-border-default);
|
|
496
|
+
display: flex;
|
|
497
|
+
flex-direction: column;
|
|
498
|
+
position: relative;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.sidebar-header {
|
|
502
|
+
padding: var(--space-3);
|
|
503
|
+
border-bottom: 1px solid var(--color-border-default);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.filter-box {
|
|
507
|
+
position: relative;
|
|
508
|
+
display: flex;
|
|
509
|
+
align-items: center;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.filter-input {
|
|
513
|
+
width: 100%;
|
|
514
|
+
padding: var(--space-2) var(--space-8) var(--space-2) var(--space-3);
|
|
515
|
+
border: 1px solid var(--color-border-default);
|
|
516
|
+
border-radius: var(--radius-md);
|
|
517
|
+
background: var(--color-bg-default);
|
|
518
|
+
color: var(--color-text-primary);
|
|
519
|
+
font-size: var(--text-sm);
|
|
520
|
+
transition: all var(--duration-fast);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.filter-input:focus {
|
|
524
|
+
outline: none;
|
|
525
|
+
border-color: var(--color-border-focus);
|
|
526
|
+
box-shadow: 0 0 0 2px var(--color-accent-blue-bg);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.filter-icon {
|
|
530
|
+
position: absolute;
|
|
531
|
+
right: var(--space-3);
|
|
532
|
+
color: var(--color-text-tertiary);
|
|
533
|
+
pointer-events: none;
|
|
534
|
+
}
|
|
535
|
+
|
|
375
536
|
/* Navigation */
|
|
376
537
|
.navigation {
|
|
538
|
+
flex: 1;
|
|
377
539
|
padding: var(--space-2);
|
|
378
540
|
overflow-y: auto;
|
|
379
541
|
overflow-x: visible;
|
|
380
|
-
flex: 1;
|
|
381
|
-
position: relative;
|
|
382
542
|
|
|
383
543
|
/* Scrollbar styling */
|
|
384
544
|
scrollbar-width: thin;
|
|
385
545
|
scrollbar-color: var(--color-border-default) transparent;
|
|
386
546
|
}
|
|
387
547
|
|
|
548
|
+
.resize-handle {
|
|
549
|
+
width: 4px;
|
|
550
|
+
background: transparent;
|
|
551
|
+
cursor: col-resize;
|
|
552
|
+
position: absolute;
|
|
553
|
+
top: 0;
|
|
554
|
+
right: 0;
|
|
555
|
+
bottom: 0;
|
|
556
|
+
transition: background var(--duration-fast);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.resize-handle:hover {
|
|
560
|
+
background: var(--color-border-focus);
|
|
561
|
+
}
|
|
562
|
+
|
|
388
563
|
.navigation::-webkit-scrollbar {
|
|
389
564
|
width: 6px;
|
|
390
565
|
}
|
|
@@ -530,14 +705,14 @@ pre code {
|
|
|
530
705
|
|
|
531
706
|
.content {
|
|
532
707
|
flex: 1;
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
transition: margin-left var(--duration-normal);
|
|
708
|
+
padding: var(--space-6) var(--space-8);
|
|
709
|
+
overflow-y: auto;
|
|
710
|
+
background: var(--color-bg-default);
|
|
537
711
|
}
|
|
538
712
|
|
|
539
713
|
.content-inner {
|
|
540
714
|
max-width: 65rem;
|
|
715
|
+
margin: 0 auto;
|
|
541
716
|
}
|
|
542
717
|
|
|
543
718
|
/* Tables */
|
|
@@ -1459,50 +1634,125 @@ tr:hover {
|
|
|
1459
1634
|
[data-tooltip]::after {
|
|
1460
1635
|
display: none;
|
|
1461
1636
|
}
|
|
1637
|
+
|
|
1638
|
+
.main-wrapper {
|
|
1639
|
+
flex-direction: column;
|
|
1640
|
+
height: auto;
|
|
1641
|
+
min-height: calc(100vh - var(--header-height) - var(--breadcrumb-height));
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
.sidebar {
|
|
1645
|
+
width: 100%;
|
|
1646
|
+
max-height: 250px;
|
|
1647
|
+
border-right: none;
|
|
1648
|
+
border-bottom: 1px solid var(--color-border-default);
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
.content {
|
|
1652
|
+
padding: var(--space-4);
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
.content-inner {
|
|
1656
|
+
max-width: none;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
.preview-banner {
|
|
1660
|
+
position: relative;
|
|
1661
|
+
top: 0;
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
.breadcrumbs {
|
|
1665
|
+
position: relative;
|
|
1666
|
+
top: 0;
|
|
1667
|
+
}
|
|
1462
1668
|
}
|
|
1463
1669
|
|
|
1464
|
-
/* Navigation
|
|
1465
|
-
.nav-
|
|
1466
|
-
margin-bottom: var(--space-
|
|
1670
|
+
/* Navigation Sections */
|
|
1671
|
+
.nav-section {
|
|
1672
|
+
margin-bottom: var(--space-1);
|
|
1467
1673
|
}
|
|
1468
1674
|
|
|
1469
|
-
.nav-
|
|
1470
|
-
display:
|
|
1471
|
-
|
|
1472
|
-
|
|
1675
|
+
.nav-title {
|
|
1676
|
+
display: flex;
|
|
1677
|
+
align-items: center;
|
|
1678
|
+
gap: var(--space-2);
|
|
1679
|
+
padding: var(--space-2);
|
|
1680
|
+
color: var(--color-text-primary);
|
|
1473
1681
|
text-decoration: none;
|
|
1474
|
-
border-radius: var(--border-radius-md);
|
|
1475
|
-
transition: all 0.2s ease;
|
|
1476
1682
|
font-size: var(--text-sm);
|
|
1477
|
-
font-weight:
|
|
1683
|
+
font-weight: var(--font-medium);
|
|
1684
|
+
border-radius: var(--radius-md);
|
|
1685
|
+
transition: all var(--duration-fast);
|
|
1686
|
+
cursor: pointer;
|
|
1478
1687
|
}
|
|
1479
1688
|
|
|
1480
|
-
.nav-
|
|
1689
|
+
.nav-title:hover {
|
|
1481
1690
|
background: var(--color-bg-hover);
|
|
1482
|
-
color: var(--color-text-primary);
|
|
1483
1691
|
}
|
|
1484
1692
|
|
|
1485
|
-
.nav-
|
|
1486
|
-
|
|
1487
|
-
background: var(--color-accent-blue-bg);
|
|
1488
|
-
color: var(--color-accent-blue);
|
|
1489
|
-
font-weight: 500;
|
|
1693
|
+
.nav-title.collapsible {
|
|
1694
|
+
position: relative;
|
|
1490
1695
|
}
|
|
1491
1696
|
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1697
|
+
.nav-title .collapse-icon {
|
|
1698
|
+
transition: transform var(--duration-fast);
|
|
1699
|
+
color: var(--color-text-tertiary);
|
|
1700
|
+
font-size: var(--text-xs);
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
.nav-title.expanded .collapse-icon {
|
|
1704
|
+
transform: rotate(90deg);
|
|
1495
1705
|
}
|
|
1496
1706
|
|
|
1497
1707
|
.nav-content {
|
|
1498
|
-
padding-left: var(--space-
|
|
1708
|
+
padding-left: var(--space-4);
|
|
1709
|
+
overflow: hidden;
|
|
1710
|
+
transition: max-height var(--duration-normal), opacity var(--duration-normal);
|
|
1499
1711
|
}
|
|
1500
1712
|
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1713
|
+
.nav-content.collapsed {
|
|
1714
|
+
max-height: 0;
|
|
1715
|
+
opacity: 0;
|
|
1716
|
+
pointer-events: none;
|
|
1504
1717
|
}
|
|
1505
1718
|
|
|
1506
|
-
.
|
|
1507
|
-
|
|
1719
|
+
.nav-content:not(.collapsed) {
|
|
1720
|
+
max-height: 1000px;
|
|
1721
|
+
opacity: 1;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
/* Navigation Items */
|
|
1725
|
+
.nav-item {
|
|
1726
|
+
display: flex;
|
|
1727
|
+
align-items: center;
|
|
1728
|
+
gap: var(--space-2);
|
|
1729
|
+
padding: var(--space-1-5) var(--space-2);
|
|
1730
|
+
color: var(--color-text-secondary);
|
|
1731
|
+
text-decoration: none;
|
|
1732
|
+
font-size: var(--text-sm);
|
|
1733
|
+
border-radius: var(--radius-md);
|
|
1734
|
+
transition: all var(--duration-fast);
|
|
1735
|
+
margin-bottom: var(--space-0-5);
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
.nav-item:hover {
|
|
1739
|
+
background: var(--color-bg-hover);
|
|
1740
|
+
color: var(--color-text-primary);
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
.nav-item.active {
|
|
1744
|
+
background: var(--color-accent-blue-bg);
|
|
1745
|
+
color: var(--color-accent-blue);
|
|
1746
|
+
font-weight: var(--font-medium);
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
.nav-item i {
|
|
1750
|
+
color: var(--color-text-tertiary);
|
|
1751
|
+
font-size: var(--text-xs);
|
|
1752
|
+
width: 12px;
|
|
1753
|
+
text-align: center;
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
.nav-item.active i {
|
|
1757
|
+
color: var(--color-accent-blue);
|
|
1508
1758
|
}
|
package/lib/core-builder.js
CHANGED
|
@@ -123,18 +123,43 @@ function generateHTML(title, content, navigation, currentPath = '', config = {})
|
|
|
123
123
|
</div>
|
|
124
124
|
</header>
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<
|
|
129
|
-
<
|
|
130
|
-
|
|
126
|
+
<!-- Preview Banner -->
|
|
127
|
+
<div id="preview-banner" class="preview-banner">
|
|
128
|
+
<div class="banner-content">
|
|
129
|
+
<i class="fas fa-exclamation-triangle banner-icon"></i>
|
|
130
|
+
<span class="banner-text">This documentation is a preview version - some content may be incomplete</span>
|
|
131
|
+
<button id="dismiss-banner" class="banner-dismiss" aria-label="Dismiss banner">
|
|
132
|
+
<i class="fas fa-times"></i>
|
|
133
|
+
</button>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<!-- Breadcrumbs -->
|
|
138
|
+
<nav class="breadcrumbs" id="breadcrumbs">
|
|
139
|
+
<!-- Breadcrumbs will be generated by JavaScript -->
|
|
140
|
+
</nav>
|
|
141
|
+
|
|
142
|
+
<!-- Main Content -->
|
|
143
|
+
<div class="main-wrapper">
|
|
144
|
+
<!-- Sidebar -->
|
|
145
|
+
<aside class="sidebar">
|
|
146
|
+
<div class="sidebar-header">
|
|
147
|
+
<div class="filter-box">
|
|
148
|
+
<input type="text" placeholder="Filter items..." class="filter-input" id="nav-filter">
|
|
149
|
+
<i class="fas fa-search filter-icon"></i>
|
|
150
|
+
</div>
|
|
131
151
|
</div>
|
|
132
|
-
|
|
133
|
-
|
|
152
|
+
<nav class="navigation">
|
|
153
|
+
${navigation}
|
|
154
|
+
</nav>
|
|
155
|
+
<div class="resize-handle"></div>
|
|
156
|
+
</aside>
|
|
134
157
|
|
|
135
|
-
<!--
|
|
158
|
+
<!-- Content Area -->
|
|
136
159
|
<main class="content">
|
|
137
|
-
|
|
160
|
+
<div class="content-inner">
|
|
161
|
+
${content}
|
|
162
|
+
</div>
|
|
138
163
|
</main>
|
|
139
164
|
</div>
|
|
140
165
|
|
|
@@ -145,7 +170,28 @@ function generateHTML(title, content, navigation, currentPath = '', config = {})
|
|
|
145
170
|
</html>`;
|
|
146
171
|
}
|
|
147
172
|
|
|
148
|
-
//
|
|
173
|
+
// Define folder descriptions for tooltips
|
|
174
|
+
const folderDescriptions = {
|
|
175
|
+
'product-roadmap': 'Strategic vision, timeline, and feature planning',
|
|
176
|
+
'product-requirements': 'Detailed product specifications, requirements documents, and feature definitions',
|
|
177
|
+
'architecture': 'System design, data flows, and technical infrastructure documentation',
|
|
178
|
+
'system-analysis': 'Comprehensive system analysis, functional requirements, and cross-component documentation',
|
|
179
|
+
'bubble': 'Core application platform - business logic, UI/UX, and user workflows',
|
|
180
|
+
'quickbase': 'Database schema, data management, and backend operations',
|
|
181
|
+
'activecampaign': 'Marketing automation integration and lead management system',
|
|
182
|
+
'juno-signer': 'Document signing service for digital signatures and PDF generation',
|
|
183
|
+
'juno-api-deprecated': 'Legacy API documentation (deprecated, for reference only)',
|
|
184
|
+
'postman': 'API testing tools, collections, and test automation',
|
|
185
|
+
'mcp': 'Model Context Protocol integration and configuration',
|
|
186
|
+
'team': 'Team structure, roles, and responsibilities',
|
|
187
|
+
'thought-leadership': 'Strategic insights and industry perspectives',
|
|
188
|
+
'middleware': 'Integration layers and data transformation services',
|
|
189
|
+
'paths': 'User journey flows and process workflows',
|
|
190
|
+
'testing': 'Test strategies, scenarios, and quality assurance processes',
|
|
191
|
+
'juno-api': 'API documentation and integration guides'
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// Build navigation structure with rich functionality
|
|
149
195
|
function buildNavigationStructure(files, currentFile) {
|
|
150
196
|
const tree = { files: [], folders: {} };
|
|
151
197
|
|
|
@@ -166,71 +212,176 @@ function buildNavigationStructure(files, currentFile) {
|
|
|
166
212
|
current.files.push(file);
|
|
167
213
|
});
|
|
168
214
|
|
|
169
|
-
//
|
|
170
|
-
const
|
|
215
|
+
// Helper function to check if a node has active child
|
|
216
|
+
const checkActiveChild = (node, currentFile) => {
|
|
217
|
+
// Check files
|
|
218
|
+
if (node.files.some(f => f.urlPath === currentFile)) return true;
|
|
219
|
+
|
|
220
|
+
// Check folders recursively
|
|
221
|
+
return Object.values(node.folders).some(folder => checkActiveChild(folder, currentFile));
|
|
222
|
+
};
|
|
171
223
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
let
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
224
|
+
// Helper function to generate file title
|
|
225
|
+
const generateFileTitle = (file, parentDisplayName, level) => {
|
|
226
|
+
let title = file.displayName;
|
|
227
|
+
|
|
228
|
+
if (file.displayName === 'README') {
|
|
229
|
+
return level === 0 ? 'Overview' : `${parentDisplayName} Overview`;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Clean up title by removing common prefixes and improving formatting
|
|
233
|
+
title = title
|
|
234
|
+
.replace(/^(bubble|system|quickbase|middleware|product-roadmap)-?/, '')
|
|
235
|
+
.replace(/-/g, ' ')
|
|
236
|
+
.replace(/\b\w/g, l => l.toUpperCase());
|
|
237
|
+
|
|
238
|
+
return title;
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// Helper function to render a section
|
|
242
|
+
const renderSection = (folderName, folderData, level = 0, parentPath = '') => {
|
|
243
|
+
const icons = {
|
|
244
|
+
'root': 'fas fa-home',
|
|
245
|
+
'product-roadmap': 'fas fa-road',
|
|
246
|
+
'product-requirements': 'fas fa-clipboard-list',
|
|
247
|
+
'architecture': 'fas fa-sitemap',
|
|
248
|
+
'system-analysis': 'fas fa-chart-line',
|
|
249
|
+
'system': 'fas fa-cogs',
|
|
250
|
+
'bubble': 'fas fa-circle',
|
|
251
|
+
'quickbase': 'fas fa-database',
|
|
252
|
+
'activecampaign': 'fas fa-envelope',
|
|
253
|
+
'juno-signer': 'fas fa-signature',
|
|
254
|
+
'juno-api-deprecated': 'fas fa-archive',
|
|
255
|
+
'postman': 'fas fa-flask',
|
|
256
|
+
'mcp': 'fas fa-puzzle-piece',
|
|
257
|
+
'team': 'fas fa-users',
|
|
258
|
+
'thought-leadership': 'fas fa-lightbulb',
|
|
259
|
+
'middleware': 'fas fa-layer-group',
|
|
260
|
+
'paths': 'fas fa-route',
|
|
261
|
+
'testing': 'fas fa-vial',
|
|
262
|
+
'juno-api': 'fas fa-plug',
|
|
263
|
+
'documentation-tool': 'fas fa-tools'
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const displayName = folderName === 'root' ? 'Documentation' :
|
|
267
|
+
folderName.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
|
|
268
|
+
const icon = icons[folderName] || 'fas fa-folder';
|
|
269
|
+
|
|
270
|
+
if (!folderData.files.length && !Object.keys(folderData.folders).length) {
|
|
271
|
+
return '';
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Include parent path in section ID to make it unique
|
|
275
|
+
const pathParts = parentPath ? [parentPath, folderName].join('-') : folderName;
|
|
276
|
+
const sectionId = `nav-${pathParts}-${level}`;
|
|
277
|
+
const isCollapsible = level > 0 || folderName !== 'root';
|
|
278
|
+
const collapseIcon = isCollapsible ? '<i class="fas fa-chevron-right collapse-icon"></i>' : '';
|
|
279
|
+
|
|
280
|
+
// Check if this folder has a README.md file to link to
|
|
281
|
+
const readmeFile = folderData.files.find(f => f.displayName === 'README');
|
|
282
|
+
const folderLink = readmeFile ? `href="/${readmeFile.urlPath}"` : 'href="#"';
|
|
283
|
+
|
|
284
|
+
// Get folder description for tooltip
|
|
285
|
+
const folderDescription = folderDescriptions[folderName] || '';
|
|
286
|
+
const tooltipAttr = folderDescription ? `data-tooltip="${escapeHtml(folderDescription)}"` : '';
|
|
287
|
+
|
|
288
|
+
// Start all sections collapsed by default (JavaScript will expand sections containing active items)
|
|
289
|
+
const hasActiveChild = checkActiveChild(folderData, currentFile);
|
|
290
|
+
|
|
291
|
+
let html = `
|
|
292
|
+
<div class="nav-section" data-level="${level}">
|
|
293
|
+
<a class="nav-title${isCollapsible ? ' collapsible' : ''}${hasActiveChild ? ' expanded' : ''}" ${folderLink} ${isCollapsible ? `data-target="${sectionId}"` : ''} ${tooltipAttr}>
|
|
294
|
+
${collapseIcon}<i class="${icon}"></i> ${displayName}
|
|
183
295
|
</a>
|
|
184
|
-
|
|
296
|
+
<div class="nav-content${isCollapsible ? (hasActiveChild ? '' : ' collapsed') : ''}" ${isCollapsible ? `id="${sectionId}"` : ''}>`;
|
|
297
|
+
|
|
298
|
+
// Sort and render files
|
|
299
|
+
const sortedFiles = [...folderData.files].sort((a, b) => {
|
|
300
|
+
if (a.displayName === 'README') return -1;
|
|
301
|
+
if (b.displayName === 'README') return 1;
|
|
302
|
+
return a.displayName.localeCompare(b.displayName);
|
|
185
303
|
});
|
|
186
304
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
} else {
|
|
190
|
-
// Generate collapsible navigation for folder structures
|
|
191
|
-
const generateNavHTML = (node, path = '', level = 0) => {
|
|
192
|
-
let html = '';
|
|
305
|
+
sortedFiles.forEach(file => {
|
|
306
|
+
const title = generateFileTitle(file, displayName, level);
|
|
193
307
|
|
|
194
|
-
//
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
<i class="fas fa-chevron-${hasActiveChild ? 'down' : 'right'}"></i>
|
|
203
|
-
<span class="nav-text">${folderName}</span>
|
|
204
|
-
</div>
|
|
205
|
-
<div class="nav-content ${hasActiveChild ? '' : 'collapsed'}" id="${sectionId}">
|
|
206
|
-
${generateNavHTML(folderNode, folderPath, level + 1)}
|
|
207
|
-
</div>
|
|
208
|
-
</div>`;
|
|
209
|
-
});
|
|
308
|
+
// Check if this file is active
|
|
309
|
+
let isActive = '';
|
|
310
|
+
if (currentFile === file.urlPath) {
|
|
311
|
+
isActive = ' active';
|
|
312
|
+
} else if (currentFile === 'index.html' && file.displayName === 'README' && folderName === 'root') {
|
|
313
|
+
// Mark root README as active when viewing index.html
|
|
314
|
+
isActive = ' active';
|
|
315
|
+
}
|
|
210
316
|
|
|
211
|
-
|
|
212
|
-
node.files.forEach(file => {
|
|
213
|
-
const isActive = file.urlPath === currentFile;
|
|
214
|
-
const href = file.urlPath.replace(/\\/g, '/');
|
|
215
|
-
html += `<div class="nav-item ${isActive ? 'active' : ''}">
|
|
216
|
-
<a href="${href}" class="nav-link ${isActive ? 'active' : ''}">
|
|
217
|
-
<span class="nav-text">${file.displayName}</span>
|
|
218
|
-
</a>
|
|
219
|
-
</div>`;
|
|
220
|
-
});
|
|
317
|
+
const linkPath = '/' + file.urlPath;
|
|
221
318
|
|
|
222
|
-
|
|
223
|
-
|
|
319
|
+
html += `
|
|
320
|
+
<a href="${linkPath}" class="nav-item${isActive}"><i class="fas fa-file-alt"></i> ${title}</a>`;
|
|
321
|
+
});
|
|
224
322
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
323
|
+
html += `</div></div>`;
|
|
324
|
+
|
|
325
|
+
// Render subfolders AFTER closing the parent section
|
|
326
|
+
Object.keys(folderData.folders)
|
|
327
|
+
.sort()
|
|
328
|
+
.forEach(subFolder => {
|
|
329
|
+
// Build the path for the subfolder including current folder
|
|
330
|
+
const currentPath = parentPath ? `${parentPath}-${folderName}` : folderName;
|
|
331
|
+
html += renderSection(subFolder, folderData.folders[subFolder], level + 1, currentPath);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
return html;
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
// Check if this is a flat structure
|
|
338
|
+
const hasFolders = Object.keys(tree.folders).length > 0;
|
|
339
|
+
|
|
340
|
+
if (!hasFolders) {
|
|
341
|
+
// Generate simple flat navigation for all files in root
|
|
342
|
+
return renderSection('root', { files: tree.files, folders: {} }, 0);
|
|
343
|
+
} else {
|
|
344
|
+
// Generate hierarchical navigation
|
|
345
|
+
let nav = '';
|
|
346
|
+
|
|
347
|
+
// Render root files first
|
|
348
|
+
if (tree.files.length > 0) {
|
|
349
|
+
nav += renderSection('root', { files: tree.files, folders: {} }, 0);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Add other top-level folders in logical order
|
|
353
|
+
const folderOrder = [
|
|
354
|
+
'product-roadmap',
|
|
355
|
+
'product-requirements',
|
|
356
|
+
'architecture',
|
|
357
|
+
'system-analysis',
|
|
358
|
+
'bubble',
|
|
359
|
+
'quickbase',
|
|
360
|
+
'activecampaign',
|
|
361
|
+
'juno-signer',
|
|
362
|
+
'juno-api-deprecated',
|
|
363
|
+
'postman',
|
|
364
|
+
'mcp',
|
|
365
|
+
'team',
|
|
366
|
+
'thought-leadership',
|
|
367
|
+
'documentation-tool'
|
|
368
|
+
];
|
|
369
|
+
|
|
370
|
+
folderOrder.forEach(folderName => {
|
|
371
|
+
if (tree.folders[folderName]) {
|
|
372
|
+
nav += renderSection(folderName, tree.folders[folderName], 1);
|
|
373
|
+
delete tree.folders[folderName]; // Remove so we don't render it again
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// Render any remaining folders not in the predefined order
|
|
378
|
+
Object.keys(tree.folders)
|
|
379
|
+
.sort()
|
|
380
|
+
.forEach(folderName => {
|
|
381
|
+
nav += renderSection(folderName, tree.folders[folderName], 1);
|
|
382
|
+
});
|
|
232
383
|
|
|
233
|
-
return
|
|
384
|
+
return nav;
|
|
234
385
|
}
|
|
235
386
|
}
|
|
236
387
|
|