@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.
- package/.github/workflows/publish.yml +1 -1
- package/README.md +2 -2
- package/bin/docmd.js +6 -2
- package/config.js +31 -31
- package/docs/cli-commands.md +13 -0
- package/docs/content/images.md +205 -0
- package/docs/content/index.md +17 -0
- package/docs/theming/custom-css-js.md +31 -0
- package/package.json +3 -1
- package/src/assets/css/{main.css → docmd-main.css} +252 -9
- package/src/assets/css/{theme-sky.css → docmd-theme-sky.css} +153 -1
- package/src/assets/js/docmd-image-lightbox.js +72 -0
- package/src/assets/js/{theme-toggle.js → docmd-theme-toggle.js} +4 -4
- package/src/commands/build.js +109 -8
- package/src/commands/dev.js +3 -3
- package/src/commands/init.js +82 -12
- package/src/core/file-processor.js +40 -0
- package/src/core/html-generator.js +7 -3
- package/src/templates/layout.ejs +4 -62
- package/src/templates/toc.ejs +53 -20
- package/docs/writing-content/index.md +0 -17
- package/src/assets/css/toc.css +0 -76
- /package/docs/{writing-content → content}/custom-containers.md +0 -0
- /package/docs/{writing-content → content}/frontmatter.md +0 -0
- /package/docs/{writing-content → content}/markdown-syntax.md +0 -0
- /package/src/assets/css/{highlight-dark.css → docmd-highlight-dark.css} +0 -0
- /package/src/assets/css/{highlight-light.css → docmd-highlight-light.css} +0 -0
- /package/src/assets/images/{logo-dark.png → docmd-logo-dark.png} +0 -0
- /package/src/assets/images/{logo-light.png → docmd-logo-light.png} +0 -0
|
@@ -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
|
|
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">×</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
|
}
|
package/src/commands/build.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
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
|