@mgks/docmd 0.1.0 → 0.1.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.
@@ -1,6 +1,4 @@
1
- /* src/assets/css/main.css */
2
- @import url('./toc.css'); /* Import the TOC styles */
3
-
1
+ /* src/assets/css/docmd-main.css */
4
2
  :root {
5
3
  --font-family-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
6
4
  --font-family-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
@@ -18,6 +16,14 @@
18
16
  --code-text: #333;
19
17
  --header-bg: #ffffff; /* Added for header */
20
18
  --header-border: #e0e0e0; /* Added for header border */
19
+
20
+ /* Image styling variables */
21
+ --image-border-color: #e0e0e0;
22
+ --image-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
23
+ --image-caption-bg: #f8f8f8;
24
+ --image-caption-text: #666;
25
+ --lightbox-bg: rgba(0, 0, 0, 0.9);
26
+ --lightbox-text: #fff;
21
27
  }
22
28
 
23
29
  body[data-theme="dark"] {
@@ -33,6 +39,14 @@
33
39
  --code-text: #abb2bf;
34
40
  --header-bg: #1a1a1a; /* Added for header */
35
41
  --header-border: #444444; /* Added for header border */
42
+
43
+ /* Image styling variables for dark mode */
44
+ --image-border-color: #444444;
45
+ --image-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
46
+ --image-caption-bg: #2c2c2c;
47
+ --image-caption-text: #bdc3c7;
48
+ --lightbox-bg: rgba(0, 0, 0, 0.95);
49
+ --lightbox-text: #fff;
36
50
  }
37
51
 
38
52
  body {
@@ -275,11 +289,6 @@
275
289
  .callout .callout-content > :first-child { margin-top: 0; }
276
290
  .callout .callout-content > :last-child { margin-bottom: 0; }
277
291
 
278
-
279
- /* Cards */
280
- .card {
281
- /* background-color: var(--code-bg); /* Already set by .docmd-container */
282
- }
283
292
  .card .card-title {
284
293
  font-weight: bold;
285
294
  font-size: 1.1em;
@@ -559,4 +568,238 @@
559
568
  display: flex;
560
569
  flex-direction: column-reverse;
561
570
  }
562
- }
571
+ }
572
+
573
+ /* TOC Styles - Simplified Hyperlink Style */
574
+ .toc-container {
575
+ margin: 0;
576
+ padding: 0;
577
+ border: none;
578
+ background-color: transparent;
579
+ }
580
+
581
+ .toc-title {
582
+ margin-top: 0;
583
+ margin-bottom: 0.5rem;
584
+ font-size: 1rem;
585
+ font-weight: bold;
586
+ color: var(--text-muted);
587
+
588
+ }
589
+
590
+ .toc-list {
591
+ list-style: none;
592
+ padding-left: 0;
593
+ margin: 0;
594
+ }
595
+
596
+ .toc-item {
597
+ margin-bottom: 0.25rem;
598
+ line-height: 1.4;
599
+ }
600
+
601
+ .toc-link {
602
+ text-decoration: none;
603
+ color: var(--link-color);
604
+ display: inline-block;
605
+ padding: 0.1rem 0;
606
+ font-size: 0.9rem;
607
+ font-weight: 500;
608
+
609
+ }
610
+
611
+ .toc-link:hover {
612
+ text-decoration: underline;
613
+ }
614
+
615
+ /* Indentation for different heading levels */
616
+ .toc-level-2 {
617
+ margin-left: 0;
618
+ }
619
+
620
+ .toc-level-3 {
621
+ margin-left: 0.75rem;
622
+ font-size: 0.85rem;
623
+ }
624
+
625
+ .toc-level-4 {
626
+ margin-left: 1.5rem;
627
+ font-size: 0.8rem;
628
+ }
629
+
630
+ /* TOC sidebar should only display on active pages */
631
+ .toc-sidebar {
632
+ width: 180px;
633
+ position: sticky;
634
+ top: 2rem;
635
+ max-height: calc(100vh - 4rem);
636
+ overflow-y: auto;
637
+ align-self: flex-start;
638
+
639
+ }
640
+
641
+ /* Hide TOC on mobile */
642
+ @media (max-width: 1024px) {
643
+ .toc-sidebar {
644
+ width: 100%;
645
+ position: static;
646
+ margin-bottom: 1rem;
647
+ }
648
+ }
649
+
650
+ /* Basic image styling */
651
+ img {
652
+ max-width: 100%;
653
+ height: auto;
654
+ display: block;
655
+ margin: 1.5rem 0;
656
+ }
657
+
658
+ /* Image alignment classes */
659
+ img.align-left {
660
+ float: left;
661
+ margin-right: 1.5rem;
662
+ margin-bottom: 1rem;
663
+ }
664
+
665
+ img.align-center {
666
+ margin-left: auto;
667
+ margin-right: auto;
668
+ }
669
+
670
+ img.align-right {
671
+ float: right;
672
+ margin-left: 1.5rem;
673
+ margin-bottom: 1rem;
674
+ }
675
+
676
+ /* Image size classes */
677
+ img.size-small {
678
+ max-width: 300px;
679
+ }
680
+
681
+ img.size-medium {
682
+ max-width: 500px;
683
+ }
684
+
685
+ img.size-large {
686
+ max-width: 800px;
687
+ }
688
+
689
+ /* Image borders and shadows */
690
+ img.with-border {
691
+ border: 1px solid var(--image-border-color);
692
+ padding: 4px;
693
+ }
694
+
695
+ img.with-shadow {
696
+ box-shadow: var(--image-shadow);
697
+ }
698
+
699
+ /* Figure and caption styling */
700
+ .docmd-container figure {
701
+ margin: 2rem 0;
702
+ }
703
+
704
+ .docmd-container figure img {
705
+ margin-bottom: 0.5rem;
706
+ }
707
+
708
+ .docmd-container figcaption {
709
+ font-size: 0.9rem;
710
+ color: var(--image-caption-text);
711
+ text-align: center;
712
+ padding: 0.5rem;
713
+ background-color: var(--image-caption-bg);
714
+ border-radius: 0 0 4px 4px;
715
+ }
716
+
717
+ /* Image gallery */
718
+ .docmd-container .image-gallery {
719
+ display: grid;
720
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
721
+ gap: 1rem;
722
+ margin: 2rem 0;
723
+ }
724
+
725
+ .docmd-container .image-gallery figure {
726
+ margin: 0;
727
+ }
728
+
729
+ /* Clear floats after aligned images */
730
+ .docmd-container .clear-float::after {
731
+ content: "";
732
+ display: table;
733
+ clear: both;
734
+ }
735
+
736
+ /* Lightbox styling */
737
+ .docmd-lightbox {
738
+ display: none;
739
+ position: fixed;
740
+ top: 0;
741
+ left: 0;
742
+ width: 100%;
743
+ height: 100%;
744
+ background-color: var(--lightbox-bg);
745
+ z-index: 9999;
746
+ justify-content: center;
747
+ align-items: center;
748
+ flex-direction: column;
749
+ }
750
+
751
+ .docmd-lightbox-content {
752
+ position: relative;
753
+ max-width: 90%;
754
+ max-height: 90%;
755
+ text-align: center;
756
+ }
757
+
758
+ .docmd-lightbox-content img {
759
+ max-width: 100%;
760
+ max-height: 80vh;
761
+ object-fit: contain;
762
+ margin: 0 auto;
763
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
764
+ }
765
+
766
+ .docmd-lightbox-caption {
767
+ color: var(--lightbox-text);
768
+ padding: 1rem;
769
+ font-size: 1rem;
770
+ max-width: 100%;
771
+ }
772
+
773
+ .docmd-lightbox-close {
774
+ position: absolute;
775
+ top: 20px;
776
+ right: 30px;
777
+ color: var(--lightbox-text);
778
+ font-size: 2.5rem;
779
+ cursor: pointer;
780
+ z-index: 10000;
781
+ }
782
+
783
+ .docmd-lightbox-close:hover {
784
+ color: #ddd;
785
+ }
786
+
787
+ /* Cursor for lightbox images */
788
+ img.lightbox,
789
+ .docmd-container .image-gallery img {
790
+ cursor: zoom-in;
791
+ }
792
+
793
+ /* Responsive image handling */
794
+ @media (max-width: 768px) {
795
+ img.align-left,
796
+ img.align-right {
797
+ float: none;
798
+ margin-left: auto;
799
+ margin-right: auto;
800
+ }
801
+
802
+ .docmd-container .image-gallery {
803
+ grid-template-columns: 1fr;
804
+ }
805
+ }
@@ -1,4 +1,4 @@
1
- /* theme-sky.css - Sky theme for docmd inspired by Mintlify */
1
+ /* theme-sky.css - Sky theme for docmd */
2
2
 
3
3
  :root [data-theme="light"] {
4
4
  /* Font family */
@@ -35,6 +35,16 @@
35
35
  --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
36
36
  --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
37
37
  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
38
+
39
+ /* Image styling variables */
40
+ --image-border-color: var(--sky-border);
41
+ --image-shadow: var(--shadow-md);
42
+ --image-caption-bg: var(--sky-background-alt);
43
+ --image-caption-text: var(--sky-text-light);
44
+ --image-hover-transform: translateY(-2px);
45
+ --image-hover-shadow: var(--shadow-lg);
46
+ --image-border-radius: 8px;
47
+ --image-transition: all 0.3s ease;
38
48
  }
39
49
 
40
50
  /* Dark mode */
@@ -69,6 +79,16 @@
69
79
  --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
70
80
  --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
71
81
  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2);
82
+
83
+ /* Image styling variables for dark mode */
84
+ --image-border-color: var(--sky-border);
85
+ --image-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
86
+ --image-caption-bg: var(--sky-background-alt);
87
+ --image-caption-text: var(--sky-text-light);
88
+ --image-hover-transform: translateY(-2px);
89
+ --image-hover-shadow: 0 6px 12px rgba(0, 0, 0, 0.7);
90
+ --image-border-radius: 8px;
91
+ --image-transition: all 0.3s ease;
72
92
  }
73
93
 
74
94
  /* Apply theme styles */
@@ -496,4 +516,136 @@
496
516
  h3 {
497
517
  font-size: 1.25rem;
498
518
  }
519
+ }
520
+
521
+ /* Enhanced image styling for Sky theme */
522
+ img {
523
+ border-radius: var(--image-border-radius);
524
+ transition: var(--image-transition);
525
+ }
526
+
527
+ /* Enhanced borders and shadows */
528
+ img.with-border {
529
+ border: 1px solid var(--image-border-color);
530
+ padding: 8px;
531
+ background-color: var(--bg-color);
532
+ }
533
+
534
+ img.with-shadow {
535
+ box-shadow: var(--image-shadow);
536
+ }
537
+
538
+ img.with-shadow:hover {
539
+ box-shadow: var(--image-hover-shadow);
540
+ }
541
+
542
+ /* Beautiful figure styling */
543
+ figure {
544
+ border-radius: var(--image-border-radius);
545
+ overflow: hidden;
546
+ transition: var(--image-transition);
547
+ box-shadow: var(--shadow-sm);
548
+ }
549
+
550
+ figure:hover {
551
+ box-shadow: var(--shadow-md);
552
+ }
553
+
554
+ figure img {
555
+ margin-bottom: 0;
556
+ border-radius: var(--image-border-radius) var(--image-border-radius) 0 0;
557
+ }
558
+
559
+ figcaption {
560
+ background-color: var(--image-caption-bg);
561
+ color: var(--image-caption-text);
562
+ padding: 0.75rem 1rem;
563
+ font-size: 0.9rem;
564
+ font-weight: 500;
565
+ }
566
+
567
+ /* Advanced image gallery */
568
+ .image-gallery {
569
+ display: grid;
570
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
571
+ gap: 1.5rem;
572
+ margin: 2rem 0;
573
+ }
574
+
575
+ .image-gallery figure {
576
+ height: 100%;
577
+ display: flex;
578
+ flex-direction: column;
579
+ margin: 0;
580
+ transition: var(--image-transition);
581
+ }
582
+
583
+ .image-gallery figure:hover {
584
+ transform: var(--image-hover-transform);
585
+ }
586
+
587
+ .image-gallery img {
588
+ height: 200px;
589
+ width: 100%;
590
+ object-fit: cover;
591
+ margin: 0;
592
+ }
593
+
594
+ .image-gallery figcaption {
595
+ flex: 1;
596
+ display: flex;
597
+ align-items: center;
598
+ justify-content: center;
599
+ text-align: center;
600
+ }
601
+
602
+ /* Zoom effect on gallery images */
603
+ .image-gallery.zoom img {
604
+ transition: transform 0.5s ease;
605
+ }
606
+
607
+ .image-gallery.zoom figure:hover img {
608
+ transform: scale(1.05);
609
+ }
610
+
611
+ /* Lightbox effect - requires JavaScript implementation */
612
+ img.lightbox {
613
+ cursor: zoom-in;
614
+ }
615
+
616
+ /* Image with frames */
617
+ img.framed {
618
+ border: 8px solid white;
619
+ box-shadow: 0 0 0 1px var(--image-border-color), var(--image-shadow);
620
+ box-sizing: border-box;
621
+ }
622
+
623
+ /* Polaroid style */
624
+ figure.polaroid {
625
+ background: white;
626
+ padding: 10px 10px 30px 10px;
627
+ box-shadow: var(--shadow-md);
628
+ }
629
+
630
+ figure.polaroid img {
631
+ border-radius: 0;
632
+ box-shadow: none;
633
+ }
634
+
635
+ figure.polaroid figcaption {
636
+ background: white;
637
+ color: var(--sky-text);
638
+ font-family: 'Caveat', cursive, var(--font-family-sans);
639
+ font-size: 1.1rem;
640
+ }
641
+
642
+ /* Responsive adjustments */
643
+ @media (max-width: 768px) {
644
+ .image-gallery {
645
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
646
+ }
647
+
648
+ .image-gallery img {
649
+ height: 150px;
650
+ }
499
651
  }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * docmd-image-lightbox.js - Simple lightbox implementation for docmd images
3
+ */
4
+
5
+ document.addEventListener('DOMContentLoaded', function() {
6
+ // Create lightbox elements
7
+ const lightbox = document.createElement('div');
8
+ lightbox.className = 'docmd-lightbox';
9
+ lightbox.innerHTML = `
10
+ <div class="docmd-lightbox-content">
11
+ <img src="" alt="">
12
+ <div class="docmd-lightbox-caption"></div>
13
+ </div>
14
+ <div class="docmd-lightbox-close">&times;</div>
15
+ `;
16
+ document.body.appendChild(lightbox);
17
+
18
+ const lightboxImg = lightbox.querySelector('img');
19
+ const lightboxCaption = lightbox.querySelector('.docmd-lightbox-caption');
20
+ const lightboxClose = lightbox.querySelector('.docmd-lightbox-close');
21
+
22
+ // Find all images with lightbox class or in image galleries
23
+ const lightboxImages = document.querySelectorAll('img.lightbox, .image-gallery img');
24
+
25
+ // Add click event to each image
26
+ lightboxImages.forEach(function(img) {
27
+ img.style.cursor = 'zoom-in';
28
+
29
+ img.addEventListener('click', function() {
30
+ // Get the image source and caption
31
+ const src = this.getAttribute('src');
32
+ let caption = this.getAttribute('alt') || '';
33
+
34
+ // If image is inside a figure with figcaption, use that caption
35
+ const figure = this.closest('figure');
36
+ if (figure) {
37
+ const figcaption = figure.querySelector('figcaption');
38
+ if (figcaption) {
39
+ caption = figcaption.textContent;
40
+ }
41
+ }
42
+
43
+ // Set the lightbox content
44
+ lightboxImg.setAttribute('src', src);
45
+ lightboxCaption.textContent = caption;
46
+
47
+ // Show the lightbox
48
+ lightbox.style.display = 'flex';
49
+ document.body.style.overflow = 'hidden'; // Prevent scrolling
50
+ });
51
+ });
52
+
53
+ // Close lightbox when clicking the close button or outside the image
54
+ lightboxClose.addEventListener('click', closeLightbox);
55
+ lightbox.addEventListener('click', function(e) {
56
+ if (e.target === lightbox) {
57
+ closeLightbox();
58
+ }
59
+ });
60
+
61
+ // Close lightbox when pressing Escape key
62
+ document.addEventListener('keydown', function(e) {
63
+ if (e.key === 'Escape' && lightbox.style.display === 'flex') {
64
+ closeLightbox();
65
+ }
66
+ });
67
+
68
+ function closeLightbox() {
69
+ lightbox.style.display = 'none';
70
+ document.body.style.overflow = ''; // Restore scrolling
71
+ }
72
+ });
@@ -12,10 +12,10 @@ function applyTheme(theme, isInitialLoad = false) {
12
12
  const isLight = theme.includes('light');
13
13
  const currentHref = highlightThemeLink.href;
14
14
 
15
- if (isDark && currentHref.includes('highlight-light.css')) {
16
- highlightThemeLink.href = currentHref.replace('highlight-light.css', 'highlight-dark.css');
17
- } else if (isLight && currentHref.includes('highlight-dark.css')) {
18
- highlightThemeLink.href = currentHref.replace('highlight-dark.css', 'highlight-light.css');
15
+ if (isDark && currentHref.includes('docmd-highlight-light.css')) {
16
+ highlightThemeLink.href = currentHref.replace('docmd-highlight-light.css', 'docmd-highlight-dark.css');
17
+ } else if (isLight && currentHref.includes('docmd-highlight-dark.css')) {
18
+ highlightThemeLink.href = currentHref.replace('docmd-highlight-dark.css', 'docmd-highlight-light.css');
19
19
  }
20
20
  }
21
21
  }
@@ -6,6 +6,7 @@ const { processMarkdownFile } = require('../core/file-processor');
6
6
  const { generateHtmlPage, generateNavigationHtml } = require('../core/html-generator');
7
7
  const { renderIcon, clearWarnedIcons } = require('../core/icon-renderer'); // Update import
8
8
  const { generateSitemap } = require('../plugins/sitemap'); // Import our sitemap plugin
9
+ const { version } = require('../../package.json'); // Import package version
9
10
 
10
11
  // Debug function to log navigation information
11
12
  function logNavigationPaths(pagePath, navPath, normalizedPath) {
@@ -17,7 +18,17 @@ function logNavigationPaths(pagePath, navPath, normalizedPath) {
17
18
  // Add a global or scoped flag to track if the warning has been shown in the current dev session
18
19
  let highlightWarningShown = false;
19
20
 
20
- async function buildSite(configPath, options = { isDev: false }) {
21
+ // Asset version metadata - update this when making significant changes to assets
22
+ const ASSET_VERSIONS = {
23
+ 'css/docmd-main.css': { version: version, description: 'Core styles' },
24
+ 'css/docmd-theme-sky.css': { version: version, description: 'Sky theme' },
25
+ 'css/docmd-highlight-light.css': { version: version, description: 'Light syntax highlighting' },
26
+ 'css/docmd-highlight-dark.css': { version: version, description: 'Dark syntax highlighting' },
27
+ 'js/docmd-theme-toggle.js': { version: version, description: 'Theme toggle functionality' },
28
+ // Add other assets here with their versions
29
+ };
30
+
31
+ async function buildSite(configPath, options = { isDev: false, preserve: false }) {
21
32
  clearWarnedIcons(); // Clear warnings at the start of every build
22
33
 
23
34
  const config = await loadConfig(configPath);
@@ -29,25 +40,66 @@ async function buildSite(configPath, options = { isDev: false }) {
29
40
  throw new Error(`Source directory not found: ${SRC_DIR}`);
30
41
  }
31
42
 
32
- await fs.emptyDir(OUTPUT_DIR);
33
- if (!options.isDev) {
34
- console.log(`🧹 Cleaned output directory: ${OUTPUT_DIR}`);
43
+ // Create output directory if it doesn't exist
44
+ await fs.ensureDir(OUTPUT_DIR);
45
+
46
+ // Instead of emptying the entire directory, we'll selectively clean up HTML files
47
+ // This preserves custom assets while ensuring we don't have stale HTML files
48
+ if (await fs.pathExists(OUTPUT_DIR)) {
49
+ const cleanupFiles = await findFilesToCleanup(OUTPUT_DIR);
50
+ for (const file of cleanupFiles) {
51
+ await fs.remove(file);
52
+ }
53
+ if (!options.isDev) {
54
+ console.log(`🧹 Cleaned HTML files from output directory: ${OUTPUT_DIR}`);
55
+ }
35
56
  }
36
57
 
58
+ // Track preserved files for summary report
59
+ const preservedFiles = [];
60
+
61
+ // Copy assets
37
62
  const assetsSrcDir = path.join(__dirname, '..', 'assets');
38
63
  const assetsDestDir = path.join(OUTPUT_DIR, 'assets');
64
+
39
65
  if (await fs.pathExists(assetsSrcDir)) {
40
- await fs.copy(assetsSrcDir, assetsDestDir);
41
66
  if (!options.isDev) {
42
- console.log(`📂 Copied assets to ${assetsDestDir}`);
67
+ console.log(`📂 Copying assets to ${assetsDestDir}...`);
68
+ }
69
+
70
+ // Create destination directory if it doesn't exist
71
+ await fs.ensureDir(assetsDestDir);
72
+
73
+ // Get all files from source directory recursively
74
+ const assetFiles = await getAllFiles(assetsSrcDir);
75
+
76
+ // Copy each file individually, checking for existing files if preserve flag is set
77
+ for (const srcFile of assetFiles) {
78
+ const relativePath = path.relative(assetsSrcDir, srcFile);
79
+ const destFile = path.join(assetsDestDir, relativePath);
80
+
81
+ // Check if destination file already exists
82
+ const fileExists = await fs.pathExists(destFile);
83
+
84
+ if (fileExists && options.preserve) {
85
+ // Skip file and add to preserved list
86
+ preservedFiles.push(relativePath);
87
+ if (!options.isDev) {
88
+ console.log(` Preserving existing file: ${relativePath}`);
89
+ }
90
+ } else {
91
+ // Copy file (either it doesn't exist or we're not preserving)
92
+ await fs.ensureDir(path.dirname(destFile));
93
+ await fs.copyFile(srcFile, destFile);
94
+ }
43
95
  }
44
96
  } else {
45
97
  console.warn(`⚠️ Assets source directory not found: ${assetsSrcDir}`);
46
98
  }
47
99
 
48
100
  // Check for Highlight.js themes
49
- const lightThemePath = path.join(__dirname, '..', 'assets', 'css', 'highlight-light.css');
50
- const darkThemePath = path.join(__dirname, '..', 'assets', 'css', 'highlight-dark.css');
101
+ const lightThemePath = path.join(__dirname, '..', 'assets', 'css', 'docmd-highlight-light.css');
102
+ const darkThemePath = path.join(__dirname, '..', 'assets', 'css', 'docmd-highlight-dark.css');
51
103
 
52
104
  const themesMissing = !await fs.pathExists(lightThemePath) || !await fs.pathExists(darkThemePath);
53
105
 
@@ -280,6 +332,55 @@ async function buildSite(configPath, options = { isDev: false }) {
280
332
  console.error(`❌ Error generating sitemap: ${error.message}`);
281
333
  }
282
334
  }
335
+
336
+ // Print summary of preserved files at the end of build
337
+ if (preservedFiles.length > 0 && !options.isDev) {
338
+ console.log(`\n📋 Build Summary: ${preservedFiles.length} existing files were preserved:`);
339
+ preservedFiles.forEach(file => console.log(` - assets/${file}`));
340
+ console.log(`\nTo update these files in future builds, run without the --preserve flag.`);
341
+ }
342
+ }
343
+
344
+ // Helper function to find HTML files and sitemap.xml to clean up
345
+ async function findFilesToCleanup(dir) {
346
+ const filesToRemove = [];
347
+ const items = await fs.readdir(dir, { withFileTypes: true });
348
+
349
+ for (const item of items) {
350
+ const fullPath = path.join(dir, item.name);
351
+
352
+ if (item.isDirectory()) {
353
+ // Don't delete the assets directory
354
+ if (item.name !== 'assets') {
355
+ const subDirFiles = await findFilesToCleanup(fullPath);
356
+ filesToRemove.push(...subDirFiles);
357
+ }
358
+ } else if (
359
+ item.name.endsWith('.html') ||
360
+ item.name === 'sitemap.xml'
361
+ ) {
362
+ filesToRemove.push(fullPath);
363
+ }
364
+ }
365
+
366
+ return filesToRemove;
367
+ }
368
+
369
+ // Helper function to recursively get all files in a directory
370
+ async function getAllFiles(dir) {
371
+ const files = [];
372
+ const items = await fs.readdir(dir, { withFileTypes: true });
373
+
374
+ for (const item of items) {
375
+ const fullPath = path.join(dir, item.name);
376
+ if (item.isDirectory()) {
377
+ files.push(...await getAllFiles(fullPath));
378
+ } else {
379
+ files.push(fullPath);
380
+ }
381
+ }
382
+
383
+ return files;
283
384
  }
284
385
 
285
386
  // findMarkdownFiles function remains the same