@knowcode/doc-builder 1.4.1 → 1.4.3
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 +20 -0
- package/assets/css/notion-style.css +62 -44
- package/assets/js/main.js +8 -42
- package/lib/core-builder.js +50 -65
- package/package/CACHE-BUSTING-GUIDE.md +82 -0
- package/package/CHANGELOG.md +902 -0
- package/package/README.md +248 -0
- package/package/assets/css/notion-style.css +1914 -0
- package/package/assets/js/auth.js +67 -0
- package/package/assets/js/main.js +1331 -0
- package/package/cli.js +764 -0
- package/package/index.js +38 -0
- package/package/lib/builder.js +32 -0
- package/package/lib/config.js +278 -0
- package/package/lib/core-builder.js +957 -0
- package/package/lib/deploy.js +497 -0
- package/package/lib/dev-server.js +96 -0
- package/package/package.json +34 -0
- package/package/scripts/npx-runner.js +27 -0
- package/package/scripts/setup.js +56 -0
- package/package/test-cache-bust.sh +43 -0
- package/package.json +1 -1
- /package/{knowcode-doc-builder-1.3.15.tgz → package/knowcode-doc-builder-1.3.15.tgz} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,26 @@ 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.3] - 2025-07-20
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Restored tooltip functionality by adding back the extractSummary function
|
|
12
|
+
- Added data-tooltip attributes to navigation items showing document summaries
|
|
13
|
+
- Removed unwanted Home link from sidebar breadcrumbs section
|
|
14
|
+
- Navigation items now display helpful summaries on hover
|
|
15
|
+
|
|
16
|
+
### Technical Details
|
|
17
|
+
- extractSummary function extracts first 150 characters of meaningful content
|
|
18
|
+
- Tooltips are properly escaped for HTML safety
|
|
19
|
+
- Sidebar header simplified by removing redundant breadcrumb navigation
|
|
20
|
+
|
|
21
|
+
## [1.4.2] - 2025-01-20
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- Fixed excessive left padding on content area by removing JavaScript margin-left assignments
|
|
25
|
+
- Content layout now properly uses flexbox spacing without manual margin adjustments
|
|
26
|
+
- The JavaScript was adding inline `style="margin-left: 200px;"` which was causing the issue
|
|
27
|
+
|
|
8
28
|
## [1.4.1] - 2025-07-20
|
|
9
29
|
|
|
10
30
|
### Fixed
|
|
@@ -125,8 +125,8 @@
|
|
|
125
125
|
/* Layout */
|
|
126
126
|
--container-padding-mobile: 20px;
|
|
127
127
|
--container-padding-desktop: 40px;
|
|
128
|
-
--header-height:
|
|
129
|
-
--breadcrumb-height:
|
|
128
|
+
--header-height: 40px;
|
|
129
|
+
--breadcrumb-height: 0px;
|
|
130
130
|
--sidebar-width: 280px;
|
|
131
131
|
}
|
|
132
132
|
|
|
@@ -169,6 +169,7 @@ h2 {
|
|
|
169
169
|
h3 {
|
|
170
170
|
font-size: var(--text-xl);
|
|
171
171
|
margin-top: var(--space-8);
|
|
172
|
+
margin-bottom: var(--space-4);
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
h4 {
|
|
@@ -332,7 +333,42 @@ pre code {
|
|
|
332
333
|
top: calc(var(--header-height) + var(--breadcrumb-height) + 3.5rem);
|
|
333
334
|
}
|
|
334
335
|
|
|
335
|
-
|
|
336
|
+
.sidebar-header {
|
|
337
|
+
padding: var(--space-4);
|
|
338
|
+
border-bottom: 1px solid var(--color-border-default);
|
|
339
|
+
margin-bottom: var(--space-4);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/* Sidebar Breadcrumbs */
|
|
343
|
+
.sidebar-breadcrumbs {
|
|
344
|
+
margin-bottom: var(--space-3);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.sidebar-home-link {
|
|
348
|
+
display: inline-flex;
|
|
349
|
+
align-items: center;
|
|
350
|
+
gap: var(--space-2);
|
|
351
|
+
padding: var(--space-2) var(--space-3);
|
|
352
|
+
color: var(--color-text-secondary);
|
|
353
|
+
text-decoration: none;
|
|
354
|
+
border-radius: var(--radius-base);
|
|
355
|
+
font-size: 0.875rem;
|
|
356
|
+
font-weight: 500;
|
|
357
|
+
transition: all 0.2s;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.sidebar-home-link:hover {
|
|
361
|
+
background: var(--color-bg-secondary);
|
|
362
|
+
color: var(--color-text-primary);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.sidebar-home-link i {
|
|
366
|
+
font-size: 1rem;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.filter-box {
|
|
370
|
+
position: relative;
|
|
371
|
+
}
|
|
336
372
|
|
|
337
373
|
.filter-input {
|
|
338
374
|
width: 100%;
|
|
@@ -493,6 +529,12 @@ pre code {
|
|
|
493
529
|
.sidebar-header {
|
|
494
530
|
padding: var(--space-3);
|
|
495
531
|
border-bottom: 1px solid var(--color-border-default);
|
|
532
|
+
margin-bottom: var(--space-4);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/* Already defined above, but ensure consistency */
|
|
536
|
+
.sidebar-breadcrumbs {
|
|
537
|
+
margin-bottom: var(--space-3);
|
|
496
538
|
}
|
|
497
539
|
|
|
498
540
|
.filter-box {
|
|
@@ -683,11 +725,21 @@ pre code {
|
|
|
683
725
|
}
|
|
684
726
|
|
|
685
727
|
/* Main Content */
|
|
686
|
-
|
|
728
|
+
.main-wrapper {
|
|
729
|
+
display: flex;
|
|
730
|
+
padding-top: calc(var(--header-height) + var(--breadcrumb-height));
|
|
731
|
+
min-height: 100vh;
|
|
732
|
+
transition: padding-top var(--duration-normal);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/* Adjust layout when banner is visible */
|
|
736
|
+
.main-wrapper.banner-visible {
|
|
737
|
+
padding-top: calc(var(--header-height) + var(--breadcrumb-height) + 3.5rem);
|
|
738
|
+
}
|
|
687
739
|
|
|
688
740
|
.content {
|
|
689
741
|
flex: 1;
|
|
690
|
-
padding:
|
|
742
|
+
padding: 40px var(--space-8);
|
|
691
743
|
overflow-y: auto;
|
|
692
744
|
background: var(--color-bg-default);
|
|
693
745
|
}
|
|
@@ -788,6 +840,7 @@ tr:hover {
|
|
|
788
840
|
border: 1px solid var(--color-border-default);
|
|
789
841
|
border-radius: var(--radius-lg);
|
|
790
842
|
padding: var(--space-6);
|
|
843
|
+
margin-bottom: var(--space-4);
|
|
791
844
|
box-shadow: var(--shadow-sm);
|
|
792
845
|
transition: all var(--duration-normal) var(--easing-out);
|
|
793
846
|
}
|
|
@@ -970,43 +1023,6 @@ tr:hover {
|
|
|
970
1023
|
cursor: pointer;
|
|
971
1024
|
color: var(--color-text-primary);
|
|
972
1025
|
padding: var(--space-2);
|
|
973
|
-
margin-left: var(--space-2);
|
|
974
|
-
transition: color var(--duration-fast);
|
|
975
|
-
z-index: 1001;
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
.menu-toggle:hover {
|
|
979
|
-
color: var(--color-accent-blue);
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
.menu-toggle.active i::before {
|
|
983
|
-
content: "\f00d"; /* fa-times icon */
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
/* Mobile Sidebar Overlay */
|
|
987
|
-
.sidebar-overlay {
|
|
988
|
-
position: fixed;
|
|
989
|
-
top: 0;
|
|
990
|
-
left: 0;
|
|
991
|
-
right: 0;
|
|
992
|
-
bottom: 0;
|
|
993
|
-
background: var(--color-bg-overlay);
|
|
994
|
-
z-index: 998;
|
|
995
|
-
opacity: 0;
|
|
996
|
-
visibility: hidden;
|
|
997
|
-
transition: opacity var(--duration-normal), visibility var(--duration-normal);
|
|
998
|
-
display: none;
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
@media (max-width: 1024px) {
|
|
1002
|
-
.sidebar-overlay {
|
|
1003
|
-
display: block;
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
.sidebar-overlay.active {
|
|
1008
|
-
opacity: 1;
|
|
1009
|
-
visibility: visible;
|
|
1010
1026
|
}
|
|
1011
1027
|
|
|
1012
1028
|
/* Responsive Design */
|
|
@@ -1014,8 +1030,6 @@ tr:hover {
|
|
|
1014
1030
|
.sidebar {
|
|
1015
1031
|
transform: translateX(-100%);
|
|
1016
1032
|
transition: transform var(--duration-normal) var(--easing-out);
|
|
1017
|
-
z-index: 999;
|
|
1018
|
-
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
|
1019
1033
|
}
|
|
1020
1034
|
|
|
1021
1035
|
.sidebar.open {
|
|
@@ -1027,6 +1041,7 @@ tr:hover {
|
|
|
1027
1041
|
}
|
|
1028
1042
|
|
|
1029
1043
|
.content {
|
|
1044
|
+
margin-left: 0;
|
|
1030
1045
|
padding: var(--space-6) var(--space-4);
|
|
1031
1046
|
}
|
|
1032
1047
|
|
|
@@ -1434,6 +1449,7 @@ tr:hover {
|
|
|
1434
1449
|
font-size: var(--text-lg);
|
|
1435
1450
|
font-weight: var(--font-semibold);
|
|
1436
1451
|
color: var(--color-text-primary);
|
|
1452
|
+
margin-bottom: var(--space-4);
|
|
1437
1453
|
padding-bottom: var(--space-2);
|
|
1438
1454
|
border-bottom: 2px solid var(--color-divider);
|
|
1439
1455
|
}
|
|
@@ -1806,9 +1822,11 @@ tr:hover {
|
|
|
1806
1822
|
.auth-box p {
|
|
1807
1823
|
color: var(--color-text-secondary);
|
|
1808
1824
|
text-align: center;
|
|
1825
|
+
margin-bottom: var(--space-4);
|
|
1809
1826
|
}
|
|
1810
1827
|
|
|
1811
1828
|
.form-group {
|
|
1829
|
+
margin-bottom: var(--space-4);
|
|
1812
1830
|
}
|
|
1813
1831
|
|
|
1814
1832
|
.form-group label {
|
package/assets/js/main.js
CHANGED
|
@@ -511,30 +511,10 @@ function updateThemeIcon(theme) {
|
|
|
511
511
|
// Mobile Menu Toggle
|
|
512
512
|
const menuToggle = document.getElementById('menu-toggle');
|
|
513
513
|
const sidebar = document.querySelector('.sidebar');
|
|
514
|
-
const sidebarOverlay = document.querySelector('.sidebar-overlay');
|
|
515
514
|
|
|
516
515
|
if (menuToggle) {
|
|
517
516
|
menuToggle.addEventListener('click', () => {
|
|
518
517
|
sidebar.classList.toggle('open');
|
|
519
|
-
sidebarOverlay.classList.toggle('active');
|
|
520
|
-
menuToggle.classList.toggle('active');
|
|
521
|
-
|
|
522
|
-
// Prevent body scroll when menu is open
|
|
523
|
-
if (sidebar.classList.contains('open')) {
|
|
524
|
-
document.body.style.overflow = 'hidden';
|
|
525
|
-
} else {
|
|
526
|
-
document.body.style.overflow = '';
|
|
527
|
-
}
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// Close sidebar when clicking overlay
|
|
532
|
-
if (sidebarOverlay) {
|
|
533
|
-
sidebarOverlay.addEventListener('click', () => {
|
|
534
|
-
sidebar.classList.remove('open');
|
|
535
|
-
sidebarOverlay.classList.remove('active');
|
|
536
|
-
menuToggle.classList.remove('active');
|
|
537
|
-
document.body.style.overflow = '';
|
|
538
518
|
});
|
|
539
519
|
}
|
|
540
520
|
|
|
@@ -542,17 +522,14 @@ if (sidebarOverlay) {
|
|
|
542
522
|
// Only close when clicking outside the sidebar or the close button
|
|
543
523
|
document.addEventListener('click', (e) => {
|
|
544
524
|
// Check if we're on mobile
|
|
545
|
-
if (window.innerWidth <=
|
|
525
|
+
if (window.innerWidth <= 768) {
|
|
546
526
|
const isClickInsideSidebar = sidebar && sidebar.contains(e.target);
|
|
547
527
|
const isMenuToggle = e.target.closest('#menu-toggle');
|
|
548
|
-
const
|
|
528
|
+
const isNavItem = e.target.closest('.nav-item, .nav-title');
|
|
549
529
|
|
|
550
|
-
// Close sidebar
|
|
551
|
-
if (
|
|
530
|
+
// Close sidebar only if clicking outside AND not on menu toggle AND not on nav items
|
|
531
|
+
if (!isClickInsideSidebar && !isMenuToggle && !isNavItem && sidebar?.classList.contains('open')) {
|
|
552
532
|
sidebar.classList.remove('open');
|
|
553
|
-
sidebarOverlay?.classList.remove('active');
|
|
554
|
-
menuToggle?.classList.remove('active');
|
|
555
|
-
document.body.style.overflow = '';
|
|
556
533
|
}
|
|
557
534
|
}
|
|
558
535
|
});
|
|
@@ -689,9 +666,6 @@ document.addEventListener('keydown', (e) => {
|
|
|
689
666
|
// Escape to close mobile menu
|
|
690
667
|
if (e.key === 'Escape') {
|
|
691
668
|
sidebar?.classList.remove('open');
|
|
692
|
-
sidebarOverlay?.classList.remove('active');
|
|
693
|
-
menuToggle?.classList.remove('active');
|
|
694
|
-
document.body.style.overflow = '';
|
|
695
669
|
}
|
|
696
670
|
});
|
|
697
671
|
|
|
@@ -730,7 +704,7 @@ function initSidebarResize() {
|
|
|
730
704
|
const savedWidth = localStorage.getItem('sidebarWidth');
|
|
731
705
|
if (savedWidth && savedWidth >= 200 && savedWidth <= 500) {
|
|
732
706
|
sidebar.style.width = `${savedWidth}px`;
|
|
733
|
-
|
|
707
|
+
// Don't set margin-left - flexbox handles the layout
|
|
734
708
|
}
|
|
735
709
|
|
|
736
710
|
// Mouse down on resize handle
|
|
@@ -759,7 +733,7 @@ function initSidebarResize() {
|
|
|
759
733
|
const constrainedWidth = Math.max(200, Math.min(500, width));
|
|
760
734
|
|
|
761
735
|
sidebar.style.width = `${constrainedWidth}px`;
|
|
762
|
-
|
|
736
|
+
// Don't set margin-left - flexbox handles the layout
|
|
763
737
|
|
|
764
738
|
e.preventDefault();
|
|
765
739
|
}
|
|
@@ -801,7 +775,7 @@ function initSidebarResize() {
|
|
|
801
775
|
const constrainedWidth = Math.max(200, Math.min(500, width));
|
|
802
776
|
|
|
803
777
|
sidebar.style.width = `${constrainedWidth}px`;
|
|
804
|
-
|
|
778
|
+
// Don't set margin-left - flexbox handles the layout
|
|
805
779
|
|
|
806
780
|
e.preventDefault();
|
|
807
781
|
}
|
|
@@ -1085,7 +1059,6 @@ function exportToPDF() {
|
|
|
1085
1059
|
const mainWrapper = document.querySelector('.main-wrapper');
|
|
1086
1060
|
|
|
1087
1061
|
if (content) {
|
|
1088
|
-
content.style.marginLeft = '0';
|
|
1089
1062
|
content.style.padding = '20px';
|
|
1090
1063
|
content.style.maxWidth = 'none';
|
|
1091
1064
|
}
|
|
@@ -1200,7 +1173,6 @@ function exportToPDF() {
|
|
|
1200
1173
|
|
|
1201
1174
|
// Restore content styles
|
|
1202
1175
|
if (content) {
|
|
1203
|
-
content.style.marginLeft = '';
|
|
1204
1176
|
content.style.padding = '';
|
|
1205
1177
|
content.style.maxWidth = '';
|
|
1206
1178
|
}
|
|
@@ -1333,21 +1305,15 @@ function generateBreadcrumbs() {
|
|
|
1333
1305
|
// Initialize tooltip positioning for navigation items
|
|
1334
1306
|
function initTooltips() {
|
|
1335
1307
|
const tooltipElements = document.querySelectorAll('[data-tooltip]');
|
|
1336
|
-
console.log('[Tooltips] Found', tooltipElements.length, 'elements with tooltips');
|
|
1337
1308
|
|
|
1338
1309
|
tooltipElements.forEach(element => {
|
|
1339
1310
|
element.addEventListener('mouseenter', function(e) {
|
|
1340
1311
|
const rect = element.getBoundingClientRect();
|
|
1312
|
+
const tooltip = window.getComputedStyle(element, '::after');
|
|
1341
1313
|
|
|
1342
1314
|
// Position the tooltip using CSS variables
|
|
1343
1315
|
element.style.setProperty('--tooltip-left', `${rect.right + 10}px`);
|
|
1344
1316
|
element.style.setProperty('--tooltip-top', `${rect.top + rect.height / 2}px`);
|
|
1345
|
-
console.log('[Tooltip] Positioned at:', rect.right + 10, rect.top + rect.height / 2);
|
|
1346
|
-
});
|
|
1347
|
-
|
|
1348
|
-
element.addEventListener('mouseleave', function(e) {
|
|
1349
|
-
element.style.removeProperty('--tooltip-left');
|
|
1350
|
-
element.style.removeProperty('--tooltip-top');
|
|
1351
1317
|
});
|
|
1352
1318
|
});
|
|
1353
1319
|
}
|
package/lib/core-builder.js
CHANGED
|
@@ -24,42 +24,34 @@ 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
|
-
//
|
|
30
|
-
|
|
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
|
-
}
|
|
27
|
+
// Extract summary from markdown content for tooltips
|
|
28
|
+
function extractSummary(content, maxLength = 150) {
|
|
29
|
+
// Remove front matter
|
|
30
|
+
content = content.replace(/^---[\s\S]*?---\n/, '');
|
|
37
31
|
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
32
|
+
// Remove headers
|
|
33
|
+
content = content.replace(/^#+\s+.+$/gm, '');
|
|
34
|
+
|
|
35
|
+
// Remove code blocks
|
|
36
|
+
content = content.replace(/```[\s\S]*?```/g, '');
|
|
37
|
+
content = content.replace(/`[^`]+`/g, '');
|
|
38
|
+
|
|
39
|
+
// Remove images and links
|
|
40
|
+
content = content.replace(/!\[[^\]]*\]\([^)]*\)/g, '');
|
|
41
|
+
content = content.replace(/\[[^\]]*\]\([^)]*\)/g, '');
|
|
42
|
+
|
|
43
|
+
// Remove HTML tags
|
|
44
|
+
content = content.replace(/<[^>]+>/g, '');
|
|
45
|
+
|
|
46
|
+
// Remove extra whitespace
|
|
47
|
+
content = content.trim().replace(/\s+/g, ' ');
|
|
48
|
+
|
|
49
|
+
// Truncate if needed
|
|
50
|
+
if (content.length > maxLength) {
|
|
51
|
+
content = content.substring(0, maxLength).trim() + '...';
|
|
59
52
|
}
|
|
60
53
|
|
|
61
|
-
|
|
62
|
-
return summary.length > 200 ? summary.substring(0, 200) + '...' : summary;
|
|
54
|
+
return content || 'No description available';
|
|
63
55
|
}
|
|
64
56
|
|
|
65
57
|
// Process markdown content
|
|
@@ -121,6 +113,7 @@ function generateHTML(title, content, navigation, currentPath = '', config = {})
|
|
|
121
113
|
|
|
122
114
|
<!-- Styles -->
|
|
123
115
|
<link rel="stylesheet" href="/css/notion-style.css">
|
|
116
|
+
<link rel="stylesheet" href="/css/style.css">
|
|
124
117
|
|
|
125
118
|
<!-- Favicon -->
|
|
126
119
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📚</text></svg>">
|
|
@@ -178,9 +171,6 @@ function generateHTML(title, content, navigation, currentPath = '', config = {})
|
|
|
178
171
|
|
|
179
172
|
<!-- Main Content -->
|
|
180
173
|
<div class="main-wrapper">
|
|
181
|
-
<!-- Sidebar Overlay -->
|
|
182
|
-
<div class="sidebar-overlay"></div>
|
|
183
|
-
|
|
184
174
|
<!-- Sidebar -->
|
|
185
175
|
<aside class="sidebar">
|
|
186
176
|
<div class="sidebar-header">
|
|
@@ -232,7 +222,7 @@ const folderDescriptions = {
|
|
|
232
222
|
};
|
|
233
223
|
|
|
234
224
|
// Build navigation structure with rich functionality
|
|
235
|
-
function buildNavigationStructure(files, currentFile
|
|
225
|
+
function buildNavigationStructure(files, currentFile) {
|
|
236
226
|
const tree = { files: [], folders: {} };
|
|
237
227
|
|
|
238
228
|
files.forEach(file => {
|
|
@@ -279,7 +269,7 @@ function buildNavigationStructure(files, currentFile, summaries = {}) {
|
|
|
279
269
|
};
|
|
280
270
|
|
|
281
271
|
// Helper function to render a section
|
|
282
|
-
const renderSection = (folderName, folderData, level = 0, parentPath = ''
|
|
272
|
+
const renderSection = (folderName, folderData, level = 0, parentPath = '') => {
|
|
283
273
|
const icons = {
|
|
284
274
|
'root': 'fas fa-home',
|
|
285
275
|
'product-roadmap': 'fas fa-road',
|
|
@@ -323,7 +313,7 @@ function buildNavigationStructure(files, currentFile, summaries = {}) {
|
|
|
323
313
|
|
|
324
314
|
// Get folder description for tooltip
|
|
325
315
|
const folderDescription = folderDescriptions[folderName] || '';
|
|
326
|
-
const tooltipAttr = folderDescription ? `data-tooltip="${escapeHtml(folderDescription)}"
|
|
316
|
+
const tooltipAttr = folderDescription ? `data-tooltip="${escapeHtml(folderDescription)}"` : '';
|
|
327
317
|
|
|
328
318
|
// Start all sections collapsed by default (JavaScript will expand sections containing active items)
|
|
329
319
|
const hasActiveChild = checkActiveChild(folderData, currentFile);
|
|
@@ -355,13 +345,10 @@ function buildNavigationStructure(files, currentFile, summaries = {}) {
|
|
|
355
345
|
}
|
|
356
346
|
|
|
357
347
|
const linkPath = '/' + file.urlPath;
|
|
358
|
-
|
|
359
|
-
// Get summary for tooltip
|
|
360
|
-
const summary = summaries[file.urlPath] || '';
|
|
361
|
-
const tooltipAttr = summary ? `data-tooltip="${escapeHtml(summary)}"` : '';
|
|
348
|
+
const tooltip = file.summary ? ` data-tooltip="${escapeHtml(file.summary)}"` : '';
|
|
362
349
|
|
|
363
350
|
html += `
|
|
364
|
-
<a href="${linkPath}" class="nav-item${isActive}"
|
|
351
|
+
<a href="${linkPath}" class="nav-item${isActive}"${tooltip}><i class="fas fa-file-alt"></i> ${title}</a>`;
|
|
365
352
|
});
|
|
366
353
|
|
|
367
354
|
html += `</div></div>`;
|
|
@@ -372,7 +359,7 @@ function buildNavigationStructure(files, currentFile, summaries = {}) {
|
|
|
372
359
|
.forEach(subFolder => {
|
|
373
360
|
// Build the path for the subfolder including current folder
|
|
374
361
|
const currentPath = parentPath ? `${parentPath}-${folderName}` : folderName;
|
|
375
|
-
html += renderSection(subFolder, folderData.folders[subFolder], level + 1, currentPath
|
|
362
|
+
html += renderSection(subFolder, folderData.folders[subFolder], level + 1, currentPath);
|
|
376
363
|
});
|
|
377
364
|
|
|
378
365
|
return html;
|
|
@@ -383,14 +370,14 @@ function buildNavigationStructure(files, currentFile, summaries = {}) {
|
|
|
383
370
|
|
|
384
371
|
if (!hasFolders) {
|
|
385
372
|
// Generate simple flat navigation for all files in root
|
|
386
|
-
return renderSection('root', { files: tree.files, folders: {} }, 0
|
|
373
|
+
return renderSection('root', { files: tree.files, folders: {} }, 0);
|
|
387
374
|
} else {
|
|
388
375
|
// Generate hierarchical navigation
|
|
389
376
|
let nav = '';
|
|
390
377
|
|
|
391
378
|
// Render root files first
|
|
392
379
|
if (tree.files.length > 0) {
|
|
393
|
-
nav += renderSection('root', { files: tree.files, folders: {} }, 0
|
|
380
|
+
nav += renderSection('root', { files: tree.files, folders: {} }, 0);
|
|
394
381
|
}
|
|
395
382
|
|
|
396
383
|
// Add other top-level folders in logical order
|
|
@@ -413,7 +400,7 @@ function buildNavigationStructure(files, currentFile, summaries = {}) {
|
|
|
413
400
|
|
|
414
401
|
folderOrder.forEach(folderName => {
|
|
415
402
|
if (tree.folders[folderName]) {
|
|
416
|
-
nav += renderSection(folderName, tree.folders[folderName], 1
|
|
403
|
+
nav += renderSection(folderName, tree.folders[folderName], 1);
|
|
417
404
|
delete tree.folders[folderName]; // Remove so we don't render it again
|
|
418
405
|
}
|
|
419
406
|
});
|
|
@@ -422,7 +409,7 @@ function buildNavigationStructure(files, currentFile, summaries = {}) {
|
|
|
422
409
|
Object.keys(tree.folders)
|
|
423
410
|
.sort()
|
|
424
411
|
.forEach(folderName => {
|
|
425
|
-
nav += renderSection(folderName, tree.folders[folderName], 1
|
|
412
|
+
nav += renderSection(folderName, tree.folders[folderName], 1);
|
|
426
413
|
});
|
|
427
414
|
|
|
428
415
|
return nav;
|
|
@@ -430,7 +417,7 @@ function buildNavigationStructure(files, currentFile, summaries = {}) {
|
|
|
430
417
|
}
|
|
431
418
|
|
|
432
419
|
// Process single markdown file
|
|
433
|
-
async function processMarkdownFile(filePath, outputPath, allFiles, config
|
|
420
|
+
async function processMarkdownFile(filePath, outputPath, allFiles, config) {
|
|
434
421
|
const content = await fs.readFile(filePath, 'utf-8');
|
|
435
422
|
const fileName = path.basename(filePath, '.md');
|
|
436
423
|
const relativePath = path.relative(config.docsDir, filePath);
|
|
@@ -440,11 +427,14 @@ async function processMarkdownFile(filePath, outputPath, allFiles, config, summa
|
|
|
440
427
|
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
441
428
|
const title = titleMatch ? titleMatch[1] : fileName;
|
|
442
429
|
|
|
430
|
+
// Extract summary for tooltip
|
|
431
|
+
const summary = extractSummary(content);
|
|
432
|
+
|
|
443
433
|
// Process content
|
|
444
434
|
const htmlContent = processMarkdownContent(content);
|
|
445
435
|
|
|
446
436
|
// Build navigation
|
|
447
|
-
const navigation = buildNavigationStructure(allFiles, urlPath
|
|
437
|
+
const navigation = buildNavigationStructure(allFiles, urlPath);
|
|
448
438
|
|
|
449
439
|
// Generate full HTML
|
|
450
440
|
const html = generateHTML(title, htmlContent, navigation, urlPath, config);
|
|
@@ -453,7 +443,7 @@ async function processMarkdownFile(filePath, outputPath, allFiles, config, summa
|
|
|
453
443
|
await fs.ensureDir(path.dirname(outputPath));
|
|
454
444
|
await fs.writeFile(outputPath, html);
|
|
455
445
|
|
|
456
|
-
return { title, urlPath };
|
|
446
|
+
return { title, urlPath, summary };
|
|
457
447
|
}
|
|
458
448
|
|
|
459
449
|
// Get all markdown files
|
|
@@ -475,11 +465,16 @@ async function getAllMarkdownFiles(dir, baseDir = dir) {
|
|
|
475
465
|
.replace(/[-_]/g, ' ')
|
|
476
466
|
.replace(/\b\w/g, l => l.toUpperCase());
|
|
477
467
|
|
|
468
|
+
// Read file to extract summary
|
|
469
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
470
|
+
const summary = extractSummary(content);
|
|
471
|
+
|
|
478
472
|
files.push({
|
|
479
473
|
path: fullPath,
|
|
480
474
|
relativePath,
|
|
481
475
|
urlPath,
|
|
482
|
-
displayName
|
|
476
|
+
displayName,
|
|
477
|
+
summary
|
|
483
478
|
});
|
|
484
479
|
}
|
|
485
480
|
}
|
|
@@ -512,21 +507,10 @@ async function buildDocumentation(config) {
|
|
|
512
507
|
});
|
|
513
508
|
}
|
|
514
509
|
|
|
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
|
-
|
|
526
510
|
console.log(chalk.blue('📝 Processing files...'));
|
|
527
511
|
for (const file of files) {
|
|
528
512
|
const outputPath = path.join(outputDir, file.urlPath);
|
|
529
|
-
await processMarkdownFile(file.path, outputPath, files, config
|
|
513
|
+
await processMarkdownFile(file.path, outputPath, files, config);
|
|
530
514
|
console.log(chalk.green(`✅ Generated: ${outputPath}`));
|
|
531
515
|
}
|
|
532
516
|
|
|
@@ -873,6 +857,7 @@ async function createDefaultIndexPage(outputDir, config, version) {
|
|
|
873
857
|
<title>Welcome to ${siteName}</title>
|
|
874
858
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
875
859
|
<link rel="stylesheet" href="/css/notion-style.css">
|
|
860
|
+
<link rel="stylesheet" href="/css/style.css">
|
|
876
861
|
<style>
|
|
877
862
|
.welcome-container {
|
|
878
863
|
max-width: 800px;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Cache Busting Guide for @knowcode/doc-builder
|
|
2
|
+
|
|
3
|
+
If you're not seeing updates after upgrading to a new version, it's likely due to caching. Follow these steps:
|
|
4
|
+
|
|
5
|
+
## 1. Clean Everything Locally
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Remove old build artifacts
|
|
9
|
+
rm -rf html/
|
|
10
|
+
|
|
11
|
+
# Clear npm cache
|
|
12
|
+
npm cache clean --force
|
|
13
|
+
|
|
14
|
+
# Remove node_modules and reinstall
|
|
15
|
+
rm -rf node_modules
|
|
16
|
+
npm install
|
|
17
|
+
|
|
18
|
+
# Make sure you have the latest version
|
|
19
|
+
npm install @knowcode/doc-builder@latest
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 2. Rebuild with Fresh Files
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Build fresh documentation
|
|
26
|
+
npx @knowcode/doc-builder build
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 3. Deploy with Force Flag
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Force Vercel to ignore cache
|
|
33
|
+
vercel --prod --force
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 4. Clear Browser Cache
|
|
37
|
+
|
|
38
|
+
- **Chrome/Edge**: Cmd+Shift+R (Mac) or Ctrl+Shift+R (Windows)
|
|
39
|
+
- **Firefox**: Cmd+Shift+R (Mac) or Ctrl+Shift+R (Windows)
|
|
40
|
+
- **Safari**: Cmd+Option+R
|
|
41
|
+
- Or use Incognito/Private browsing mode
|
|
42
|
+
|
|
43
|
+
## 5. Clear Vercel/CDN Cache (if applicable)
|
|
44
|
+
|
|
45
|
+
If using Vercel:
|
|
46
|
+
1. Go to your project dashboard
|
|
47
|
+
2. Settings → Functions → Purge Cache
|
|
48
|
+
3. Or redeploy with a different domain temporarily
|
|
49
|
+
|
|
50
|
+
## 6. Add Cache Busting to Your Build
|
|
51
|
+
|
|
52
|
+
Edit your `doc-builder.config.js` to add version query strings:
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
module.exports = {
|
|
56
|
+
// ... other config
|
|
57
|
+
cacheBust: true, // This will add ?v=timestamp to CSS/JS files
|
|
58
|
+
};
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Common Issues
|
|
62
|
+
|
|
63
|
+
- **"I updated but nothing changed"** - It's cache. Follow all steps above.
|
|
64
|
+
- **"Tooltips still don't work"** - Clear browser cache and check console for errors
|
|
65
|
+
- **"Spacing is still wrong"** - The CSS is cached. Hard refresh the page.
|
|
66
|
+
|
|
67
|
+
## Verify You Have The Right Version
|
|
68
|
+
|
|
69
|
+
Check the version in your package.json:
|
|
70
|
+
```bash
|
|
71
|
+
npm list @knowcode/doc-builder
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Should show: `@knowcode/doc-builder@1.3.13` or higher.
|
|
75
|
+
|
|
76
|
+
## Still Not Working?
|
|
77
|
+
|
|
78
|
+
1. Open browser DevTools
|
|
79
|
+
2. Go to Network tab
|
|
80
|
+
3. Check "Disable cache" checkbox
|
|
81
|
+
4. Refresh the page
|
|
82
|
+
5. Look at the CSS/JS files being loaded - they should not show "(from cache)"
|