@knowcode/doc-builder 1.8.7 → 1.9.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/.claude/settings.local.json +2 -1
- package/CHANGELOG.md +27 -0
- package/assets/css/notion-style.css +141 -0
- package/assets/js/main.js +76 -0
- package/html/README.html +10 -3
- package/html/css/notion-style.css +141 -0
- package/html/documentation-index.html +10 -3
- package/html/guides/authentication-default-change.html +10 -3
- package/html/guides/authentication-guide.html +10 -3
- package/html/guides/claude-workflow-guide.html +10 -3
- package/html/guides/documentation-standards.html +10 -3
- package/html/guides/phosphor-icons-guide.html +10 -3
- package/html/guides/private-directory-authentication.html +10 -3
- package/html/guides/public-site-deployment.html +10 -3
- package/html/guides/search-engine-verification-guide.html +10 -3
- package/html/guides/seo-guide.html +10 -3
- package/html/guides/seo-optimization-guide.html +10 -3
- package/html/guides/troubleshooting-guide.html +10 -3
- package/html/guides/windows-setup-guide.html +10 -3
- package/html/image-modal-test.html +305 -0
- package/html/index.html +10 -3
- package/html/js/main.js +76 -0
- package/html/private/cache-control-anti-pattern.html +10 -3
- package/html/private/launch/README.html +10 -3
- package/html/private/launch/auth-cleanup-summary.html +10 -3
- package/html/private/launch/bubble-plugin-specification.html +10 -3
- package/html/private/launch/go-to-market-strategy.html +10 -3
- package/html/private/launch/launch-announcements.html +10 -3
- package/html/private/launch/vercel-deployment-auth-setup.html +10 -3
- package/html/private/next-steps-walkthrough.html +11 -4
- package/html/private/supabase-auth-implementation-completed.html +10 -3
- package/html/private/supabase-auth-implementation-plan.html +10 -3
- package/html/private/supabase-auth-integration-plan.html +10 -3
- package/html/private/supabase-auth-setup-guide.html +10 -3
- package/html/private/test-private-doc.html +10 -3
- package/html/private/user-management-tooling.html +10 -3
- package/html/prompts/markdown-document-standards.html +409 -0
- package/html/sitemap.xml +56 -44
- package/html/vercel-cli-setup-guide.html +10 -3
- package/html/vercel-first-time-setup-guide.html +10 -3
- package/lib/core-builder.js +1 -0
- package/lib/emoji-mapper.js +13 -0
- package/package/assets/css/notion-style.css +432 -135
- package/package/assets/js/main.js +259 -25
- package/package.json +1 -1
|
@@ -79,9 +79,6 @@ function initializeMermaidFullScreen() {
|
|
|
79
79
|
const toolbar = document.createElement('div');
|
|
80
80
|
toolbar.className = 'mermaid-toolbar';
|
|
81
81
|
|
|
82
|
-
const title = document.createElement('div');
|
|
83
|
-
title.textContent = 'Mermaid Diagram';
|
|
84
|
-
|
|
85
82
|
const actions = document.createElement('div');
|
|
86
83
|
actions.className = 'mermaid-actions';
|
|
87
84
|
|
|
@@ -91,23 +88,8 @@ function initializeMermaidFullScreen() {
|
|
|
91
88
|
fullScreenBtn.innerHTML = '<i class="fas fa-expand"></i> Full Screen';
|
|
92
89
|
fullScreenBtn.addEventListener('click', () => openMermaidFullScreen(mermaidDiv, index));
|
|
93
90
|
|
|
94
|
-
// Copy SVG button
|
|
95
|
-
const copyBtn = document.createElement('button');
|
|
96
|
-
copyBtn.className = 'mermaid-btn';
|
|
97
|
-
copyBtn.innerHTML = '<i class="fas fa-copy"></i> Copy SVG';
|
|
98
|
-
copyBtn.addEventListener('click', () => copyMermaidSVG(mermaidDiv));
|
|
99
|
-
|
|
100
|
-
// Copy Mermaid source button
|
|
101
|
-
const copyMermaidBtn = document.createElement('button');
|
|
102
|
-
copyMermaidBtn.className = 'mermaid-btn';
|
|
103
|
-
copyMermaidBtn.innerHTML = '<i class="fas fa-code"></i> Copy Mermaid';
|
|
104
|
-
copyMermaidBtn.addEventListener('click', () => copyMermaidSource(mermaidDiv));
|
|
105
|
-
|
|
106
91
|
actions.appendChild(fullScreenBtn);
|
|
107
|
-
actions.appendChild(copyBtn);
|
|
108
|
-
actions.appendChild(copyMermaidBtn);
|
|
109
92
|
|
|
110
|
-
toolbar.appendChild(title);
|
|
111
93
|
toolbar.appendChild(actions);
|
|
112
94
|
|
|
113
95
|
// Create wrapper for the diagram
|
|
@@ -512,12 +494,147 @@ function updateThemeIcon(theme) {
|
|
|
512
494
|
const menuToggle = document.getElementById('menu-toggle');
|
|
513
495
|
const sidebar = document.querySelector('.sidebar');
|
|
514
496
|
|
|
497
|
+
// Set initial menu state based on configuration
|
|
498
|
+
const menuDefaultOpen = window.docBuilderConfig?.features?.menuDefaultOpen !== false;
|
|
499
|
+
if (sidebar && window.innerWidth > 768) {
|
|
500
|
+
if (!menuDefaultOpen) {
|
|
501
|
+
sidebar.classList.add('closed');
|
|
502
|
+
// Add class to body to show menu toggle on desktop when menu starts closed
|
|
503
|
+
document.body.classList.add('menu-starts-closed');
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Create overlay element for mobile
|
|
508
|
+
let overlay = document.querySelector('.sidebar-overlay');
|
|
509
|
+
if (!overlay && window.innerWidth <= 768) {
|
|
510
|
+
overlay = document.createElement('div');
|
|
511
|
+
overlay.className = 'sidebar-overlay';
|
|
512
|
+
document.body.appendChild(overlay);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
515
|
if (menuToggle) {
|
|
516
516
|
menuToggle.addEventListener('click', () => {
|
|
517
|
+
if (window.innerWidth <= 768) {
|
|
518
|
+
// Mobile: toggle 'open' class
|
|
519
|
+
sidebar.classList.toggle('open');
|
|
520
|
+
} else {
|
|
521
|
+
// Desktop: toggle 'closed' class
|
|
522
|
+
sidebar.classList.toggle('closed');
|
|
523
|
+
// Update visibility of menu toggle based on sidebar state
|
|
524
|
+
updateMenuToggleVisibility();
|
|
525
|
+
}
|
|
526
|
+
if (overlay) {
|
|
527
|
+
overlay.classList.toggle('active');
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Function to update menu toggle visibility
|
|
533
|
+
function updateMenuToggleVisibility() {
|
|
534
|
+
if (window.innerWidth > 768) {
|
|
535
|
+
if (!menuDefaultOpen || sidebar.classList.contains('closed')) {
|
|
536
|
+
document.body.classList.add('show-menu-toggle');
|
|
537
|
+
} else {
|
|
538
|
+
document.body.classList.remove('show-menu-toggle');
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// Initial check
|
|
544
|
+
updateMenuToggleVisibility();
|
|
545
|
+
|
|
546
|
+
// Update on window resize
|
|
547
|
+
window.addEventListener('resize', updateMenuToggleVisibility);
|
|
548
|
+
|
|
549
|
+
// Close menu when clicking overlay
|
|
550
|
+
if (overlay) {
|
|
551
|
+
overlay.addEventListener('click', () => {
|
|
552
|
+
sidebar.classList.remove('open');
|
|
553
|
+
overlay.classList.remove('active');
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Floating Menu Button for Mobile
|
|
558
|
+
function initFloatingMenuButton() {
|
|
559
|
+
// Only initialize on mobile
|
|
560
|
+
if (window.innerWidth > 768) return;
|
|
561
|
+
|
|
562
|
+
// Check if button already exists
|
|
563
|
+
if (document.getElementById('floating-menu-toggle')) return;
|
|
564
|
+
|
|
565
|
+
// Create floating button
|
|
566
|
+
const floatingButton = document.createElement('button');
|
|
567
|
+
floatingButton.id = 'floating-menu-toggle';
|
|
568
|
+
floatingButton.className = 'floating-menu-toggle';
|
|
569
|
+
floatingButton.setAttribute('aria-label', 'Toggle menu');
|
|
570
|
+
floatingButton.innerHTML = '<i class="fas fa-bars"></i>';
|
|
571
|
+
floatingButton.style.display = 'flex'; // Always visible on mobile
|
|
572
|
+
floatingButton.classList.add('visible'); // Start visible
|
|
573
|
+
|
|
574
|
+
// Add to body
|
|
575
|
+
document.body.appendChild(floatingButton);
|
|
576
|
+
|
|
577
|
+
// Toggle sidebar on click
|
|
578
|
+
floatingButton.addEventListener('click', () => {
|
|
517
579
|
sidebar.classList.toggle('open');
|
|
580
|
+
|
|
581
|
+
// Handle overlay
|
|
582
|
+
let overlay = document.querySelector('.sidebar-overlay');
|
|
583
|
+
if (!overlay) {
|
|
584
|
+
overlay = document.createElement('div');
|
|
585
|
+
overlay.className = 'sidebar-overlay';
|
|
586
|
+
document.body.appendChild(overlay);
|
|
587
|
+
|
|
588
|
+
// Add overlay click handler
|
|
589
|
+
overlay.addEventListener('click', () => {
|
|
590
|
+
sidebar.classList.remove('open');
|
|
591
|
+
overlay.classList.remove('active');
|
|
592
|
+
floatingButton.querySelector('i').className = 'fas fa-bars';
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (overlay) {
|
|
597
|
+
overlay.classList.toggle('active');
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// Update icon based on state
|
|
601
|
+
const icon = floatingButton.querySelector('i');
|
|
602
|
+
if (sidebar.classList.contains('open')) {
|
|
603
|
+
icon.className = 'fas fa-times';
|
|
604
|
+
} else {
|
|
605
|
+
icon.className = 'fas fa-bars';
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
// Remove scroll-based visibility - button is always visible on mobile
|
|
610
|
+
|
|
611
|
+
// Update icon when sidebar state changes from other sources
|
|
612
|
+
const observer = new MutationObserver(() => {
|
|
613
|
+
const icon = floatingButton.querySelector('i');
|
|
614
|
+
if (sidebar.classList.contains('open')) {
|
|
615
|
+
icon.className = 'fas fa-times';
|
|
616
|
+
} else {
|
|
617
|
+
icon.className = 'fas fa-bars';
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
observer.observe(sidebar, {
|
|
622
|
+
attributes: true,
|
|
623
|
+
attributeFilter: ['class']
|
|
518
624
|
});
|
|
519
625
|
}
|
|
520
626
|
|
|
627
|
+
// Initialize floating button on load and resize
|
|
628
|
+
document.addEventListener('DOMContentLoaded', initFloatingMenuButton);
|
|
629
|
+
window.addEventListener('resize', () => {
|
|
630
|
+
const existingButton = document.getElementById('floating-menu-toggle');
|
|
631
|
+
if (window.innerWidth > 768 && existingButton) {
|
|
632
|
+
existingButton.remove();
|
|
633
|
+
} else if (window.innerWidth <= 768 && !existingButton) {
|
|
634
|
+
initFloatingMenuButton();
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
|
|
521
638
|
// Prevent sidebar from closing when clicking nav items
|
|
522
639
|
// Only close when clicking outside the sidebar or the close button
|
|
523
640
|
document.addEventListener('click', (e) => {
|
|
@@ -525,11 +642,21 @@ document.addEventListener('click', (e) => {
|
|
|
525
642
|
if (window.innerWidth <= 768) {
|
|
526
643
|
const isClickInsideSidebar = sidebar && sidebar.contains(e.target);
|
|
527
644
|
const isMenuToggle = e.target.closest('#menu-toggle');
|
|
645
|
+
const isFloatingButton = e.target.closest('#floating-menu-toggle');
|
|
528
646
|
const isNavItem = e.target.closest('.nav-item, .nav-title');
|
|
647
|
+
const overlay = document.querySelector('.sidebar-overlay');
|
|
529
648
|
|
|
530
649
|
// 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')) {
|
|
650
|
+
if (!isClickInsideSidebar && !isMenuToggle && !isFloatingButton && !isNavItem && sidebar?.classList.contains('open')) {
|
|
532
651
|
sidebar.classList.remove('open');
|
|
652
|
+
if (overlay) {
|
|
653
|
+
overlay.classList.remove('active');
|
|
654
|
+
}
|
|
655
|
+
// Update floating button icon if it exists
|
|
656
|
+
const floatingBtn = document.getElementById('floating-menu-toggle');
|
|
657
|
+
if (floatingBtn) {
|
|
658
|
+
floatingBtn.querySelector('i').className = 'fas fa-bars';
|
|
659
|
+
}
|
|
533
660
|
}
|
|
534
661
|
}
|
|
535
662
|
});
|
|
@@ -538,12 +665,16 @@ document.addEventListener('click', (e) => {
|
|
|
538
665
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
539
666
|
anchor.addEventListener('click', function (e) {
|
|
540
667
|
e.preventDefault();
|
|
541
|
-
const
|
|
542
|
-
if (
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
668
|
+
const href = this.getAttribute('href');
|
|
669
|
+
// Skip if href is just '#' (prevents querySelector error)
|
|
670
|
+
if (href && href !== '#') {
|
|
671
|
+
const target = document.querySelector(href);
|
|
672
|
+
if (target) {
|
|
673
|
+
target.scrollIntoView({
|
|
674
|
+
behavior: 'smooth',
|
|
675
|
+
block: 'start'
|
|
676
|
+
});
|
|
677
|
+
}
|
|
547
678
|
}
|
|
548
679
|
});
|
|
549
680
|
});
|
|
@@ -1186,6 +1317,10 @@ function exportToPDF() {
|
|
|
1186
1317
|
|
|
1187
1318
|
// Add PDF export button functionality
|
|
1188
1319
|
function addPDFExportButton() {
|
|
1320
|
+
// Check configuration - default to true if not set
|
|
1321
|
+
const showPdfDownload = window.docBuilderConfig?.features?.showPdfDownload !== false;
|
|
1322
|
+
if (!showPdfDownload) return;
|
|
1323
|
+
|
|
1189
1324
|
const headerActions = document.querySelector('.header-actions');
|
|
1190
1325
|
if (headerActions) {
|
|
1191
1326
|
const pdfButton = document.createElement('button');
|
|
@@ -1318,8 +1453,106 @@ function initTooltips() {
|
|
|
1318
1453
|
});
|
|
1319
1454
|
}
|
|
1320
1455
|
|
|
1456
|
+
// Handle .md link redirects
|
|
1457
|
+
function initMarkdownLinkRedirects() {
|
|
1458
|
+
// Check if current URL ends with .md and redirect
|
|
1459
|
+
if (window.location.pathname.endsWith('.md')) {
|
|
1460
|
+
const htmlPath = window.location.pathname.replace(/\.md$/, '.html');
|
|
1461
|
+
console.log(`Redirecting from .md to .html: ${htmlPath}`);
|
|
1462
|
+
window.location.replace(htmlPath);
|
|
1463
|
+
return; // Stop execution as we're redirecting
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
// Intercept clicks on .md links
|
|
1467
|
+
document.addEventListener('click', function(e) {
|
|
1468
|
+
const link = e.target.closest('a');
|
|
1469
|
+
if (link && link.href && link.href.endsWith('.md')) {
|
|
1470
|
+
e.preventDefault();
|
|
1471
|
+
const htmlUrl = link.href.replace(/\.md$/, '.html');
|
|
1472
|
+
console.log(`Converting .md link to .html: ${htmlUrl}`);
|
|
1473
|
+
window.location.href = htmlUrl;
|
|
1474
|
+
}
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
// Image Modal System
|
|
1479
|
+
function initImageModal() {
|
|
1480
|
+
// Create modal HTML structure
|
|
1481
|
+
const modalHTML = `
|
|
1482
|
+
<div class="image-modal" id="imageModal">
|
|
1483
|
+
<div class="image-modal-content">
|
|
1484
|
+
<div class="image-modal-close" id="imageModalClose">×</div>
|
|
1485
|
+
<img class="image-modal-img" id="imageModalImg" src="" alt="">
|
|
1486
|
+
<div class="image-modal-caption" id="imageModalCaption"></div>
|
|
1487
|
+
</div>
|
|
1488
|
+
</div>
|
|
1489
|
+
`;
|
|
1490
|
+
|
|
1491
|
+
// Add modal to document body
|
|
1492
|
+
document.body.insertAdjacentHTML('beforeend', modalHTML);
|
|
1493
|
+
|
|
1494
|
+
const modal = document.getElementById('imageModal');
|
|
1495
|
+
const modalImg = document.getElementById('imageModalImg');
|
|
1496
|
+
const modalCaption = document.getElementById('imageModalCaption');
|
|
1497
|
+
const closeBtn = document.getElementById('imageModalClose');
|
|
1498
|
+
|
|
1499
|
+
// Add click handlers to all content images
|
|
1500
|
+
const contentImages = document.querySelectorAll('.content img');
|
|
1501
|
+
contentImages.forEach(img => {
|
|
1502
|
+
img.addEventListener('click', function() {
|
|
1503
|
+
modal.classList.add('active');
|
|
1504
|
+
modalImg.src = this.src;
|
|
1505
|
+
modalImg.alt = this.alt;
|
|
1506
|
+
modalCaption.textContent = this.alt;
|
|
1507
|
+
|
|
1508
|
+
// Hide caption if no alt text
|
|
1509
|
+
if (!this.alt) {
|
|
1510
|
+
modalCaption.style.display = 'none';
|
|
1511
|
+
} else {
|
|
1512
|
+
modalCaption.style.display = 'block';
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
// Prevent body scrolling
|
|
1516
|
+
document.body.style.overflow = 'hidden';
|
|
1517
|
+
});
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1520
|
+
// Close modal functions
|
|
1521
|
+
function closeModal() {
|
|
1522
|
+
modal.classList.remove('active');
|
|
1523
|
+
document.body.style.overflow = '';
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
// Close on X button click
|
|
1527
|
+
closeBtn.addEventListener('click', closeModal);
|
|
1528
|
+
|
|
1529
|
+
// Close on overlay click (but not on image click)
|
|
1530
|
+
modal.addEventListener('click', function(e) {
|
|
1531
|
+
if (e.target === modal) {
|
|
1532
|
+
closeModal();
|
|
1533
|
+
}
|
|
1534
|
+
});
|
|
1535
|
+
|
|
1536
|
+
// Close on Escape key
|
|
1537
|
+
document.addEventListener('keydown', function(e) {
|
|
1538
|
+
if (e.key === 'Escape' && modal.classList.contains('active')) {
|
|
1539
|
+
closeModal();
|
|
1540
|
+
}
|
|
1541
|
+
});
|
|
1542
|
+
|
|
1543
|
+
// Prevent modal content from closing modal when clicked
|
|
1544
|
+
modalImg.addEventListener('click', function(e) {
|
|
1545
|
+
e.stopPropagation();
|
|
1546
|
+
});
|
|
1547
|
+
|
|
1548
|
+
document.querySelector('.image-modal-content').addEventListener('click', function(e) {
|
|
1549
|
+
e.stopPropagation();
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1321
1553
|
// Initialize on DOM Load
|
|
1322
1554
|
document.addEventListener('DOMContentLoaded', () => {
|
|
1555
|
+
initMarkdownLinkRedirects();
|
|
1323
1556
|
highlightNavigation();
|
|
1324
1557
|
generateTableOfContents();
|
|
1325
1558
|
initSidebarResize();
|
|
@@ -1327,5 +1560,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
1327
1560
|
initNavigationFilter();
|
|
1328
1561
|
addPDFExportButton();
|
|
1329
1562
|
generateBreadcrumbs();
|
|
1563
|
+
initImageModal();
|
|
1330
1564
|
initTooltips();
|
|
1331
1565
|
});
|