@eox/pages-theme-eox 1.9.0 → 2.0.0-alpha.10
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/.gitlab-ci.yml +4 -1
- package/README.md +88 -11
- package/cypress/support/mocks/authors.data.js +14 -0
- package/cypress/support/mocks/helpers.js +65 -4
- package/cypress/support/mocks/vitepress.js +8 -1
- package/cypress.config.js +14 -0
- package/package.json +3 -1
- package/src/Layout.vue +69 -1
- package/src/authors.data.js +14 -0
- package/src/components/BlogList.vue +655 -0
- package/src/components/BlogPost.vue +472 -0
- package/src/components/CTASection.vue +18 -4
- package/src/components/FeatureCard/Index.vue +462 -31
- package/src/components/FeatureCard/Poster.vue +25 -3
- package/src/components/FeatureSection.cy.js +16 -0
- package/src/components/FeatureSection.vue +3 -8
- package/src/components/FeaturesGallery.vue +34 -2
- package/src/components/Footer.cy.js +52 -2
- package/src/components/Footer.vue +17 -5
- package/src/components/HeroSection.cy.js +20 -0
- package/src/components/HeroSection.vue +140 -25
- package/src/components/ImageCarousel.vue +11 -2
- package/src/components/ImageElement.vue +16 -4
- package/src/components/ImageGallery.vue +29 -4
- package/src/components/LogoSection.vue +26 -3
- package/src/components/MobileNavDropdown.vue +13 -3
- package/src/components/NavBar.cy.js +15 -0
- package/src/components/NavBar.vue +149 -21
- package/src/components/NavDropdown.vue +12 -2
- package/src/components/OpenPositions.vue +292 -0
- package/src/components/SectionHeader.cy.js +54 -0
- package/src/components/SectionHeader.vue +115 -0
- package/src/components/TagList.vue +311 -0
- package/src/components/TeamPage.vue +347 -0
- package/src/components/TestimonialsSection.cy.js +76 -0
- package/src/components/TestimonialsSection.vue +368 -0
- package/src/components/TextSection.cy.js +115 -0
- package/src/components/TextSection.vue +396 -0
- package/src/helpers.js +182 -37
- package/src/helpers.test.js +181 -0
- package/src/index.js +16 -0
- package/src/pages/author/[author].md +5 -0
- package/src/pages/author/[author].paths.js +60 -0
- package/src/pages/blog.md +5 -0
- package/src/pages/tag/[tag].md +5 -0
- package/src/pages/tag/[tag].paths.js +49 -0
- package/src/pages/tag.md +5 -0
- package/src/pages/team.md +5 -0
- package/src/posts.data.js +134 -0
- package/src/style.css +389 -8
- package/src/tagUtils.js +148 -0
- package/src/team.data.js +1 -1
- package/src/vitepressConfig.mjs +101 -1
package/src/style.css
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
:root {
|
|
4
4
|
--vp-nav-height: 58px;
|
|
5
|
+
--vp-nav-logo-height: 28px;
|
|
5
6
|
}
|
|
6
7
|
:root:has(.top-nav.at-top) {
|
|
7
8
|
--vp-nav-height: 90px;
|
|
@@ -49,6 +50,11 @@ body {
|
|
|
49
50
|
transition: padding-top 0.3s ease-in-out;
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
main {
|
|
54
|
+
padding: 0 !important;
|
|
55
|
+
margin: 0 !important;
|
|
56
|
+
}
|
|
57
|
+
|
|
52
58
|
*:has(> nav.top:not(.s, .m, .l)) {
|
|
53
59
|
padding-block-start: 0;
|
|
54
60
|
}
|
|
@@ -86,6 +92,91 @@ body {
|
|
|
86
92
|
padding-right: 0;
|
|
87
93
|
}
|
|
88
94
|
|
|
95
|
+
/* Ensure full-width layout sections touch and stack seamlessly without gaps */
|
|
96
|
+
.VPHome .full-width:not(.home-hero-section) {
|
|
97
|
+
margin-block-start: 0 !important;
|
|
98
|
+
margin-block-end: 0 !important;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.layout-blog .cta-section {
|
|
102
|
+
margin-block-end: 0 !important;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* When a section follows a title (title plus section combination), eliminate start padding */
|
|
106
|
+
:is(
|
|
107
|
+
h1,
|
|
108
|
+
h2,
|
|
109
|
+
h3,
|
|
110
|
+
h4,
|
|
111
|
+
h5,
|
|
112
|
+
h6,
|
|
113
|
+
header,
|
|
114
|
+
.section-header-group,
|
|
115
|
+
[class*="section-title"]
|
|
116
|
+
)
|
|
117
|
+
+ section,
|
|
118
|
+
:is(
|
|
119
|
+
h1,
|
|
120
|
+
h2,
|
|
121
|
+
h3,
|
|
122
|
+
h4,
|
|
123
|
+
h5,
|
|
124
|
+
h6,
|
|
125
|
+
header,
|
|
126
|
+
.section-header-group,
|
|
127
|
+
[class*="section-title"]
|
|
128
|
+
)
|
|
129
|
+
+ :not(section, hr)
|
|
130
|
+
+ section,
|
|
131
|
+
:is(
|
|
132
|
+
h1,
|
|
133
|
+
h2,
|
|
134
|
+
h3,
|
|
135
|
+
h4,
|
|
136
|
+
h5,
|
|
137
|
+
h6,
|
|
138
|
+
header,
|
|
139
|
+
.section-header-group,
|
|
140
|
+
[class*="section-title"]
|
|
141
|
+
)
|
|
142
|
+
+ :not(section, hr)
|
|
143
|
+
+ :not(section, hr)
|
|
144
|
+
+ section,
|
|
145
|
+
:is(
|
|
146
|
+
h1,
|
|
147
|
+
h2,
|
|
148
|
+
h3,
|
|
149
|
+
h4,
|
|
150
|
+
h5,
|
|
151
|
+
h6,
|
|
152
|
+
header,
|
|
153
|
+
.section-header-group,
|
|
154
|
+
[class*="section-title"]
|
|
155
|
+
)
|
|
156
|
+
+ :not(section, hr)
|
|
157
|
+
+ :not(section, hr)
|
|
158
|
+
+ :not(section, hr)
|
|
159
|
+
+ section,
|
|
160
|
+
:is(
|
|
161
|
+
h1,
|
|
162
|
+
h2,
|
|
163
|
+
h3,
|
|
164
|
+
h4,
|
|
165
|
+
h5,
|
|
166
|
+
h6,
|
|
167
|
+
header,
|
|
168
|
+
.section-header-group,
|
|
169
|
+
[class*="section-title"]
|
|
170
|
+
)
|
|
171
|
+
+ :not(section, hr)
|
|
172
|
+
+ :not(section, hr)
|
|
173
|
+
+ :not(section, hr)
|
|
174
|
+
+ :not(section, hr)
|
|
175
|
+
+ section {
|
|
176
|
+
padding-block-start: 0 !important;
|
|
177
|
+
padding-top: 0 !important;
|
|
178
|
+
}
|
|
179
|
+
|
|
89
180
|
.VPHome .vp-doc a {
|
|
90
181
|
font-weight: 400;
|
|
91
182
|
color: inherit;
|
|
@@ -143,7 +234,8 @@ footer {
|
|
|
143
234
|
margin-top: 0 !important;
|
|
144
235
|
position: relative;
|
|
145
236
|
z-index: var(--vp-z-index-footer);
|
|
146
|
-
background: var(--surface-container-
|
|
237
|
+
background: var(--surface-container-lowest);
|
|
238
|
+
border-top: 1px solid var(--vp-c-divider, rgba(0, 0, 0, 0.08));
|
|
147
239
|
}
|
|
148
240
|
|
|
149
241
|
/**/
|
|
@@ -168,14 +260,24 @@ button.text:hover,
|
|
|
168
260
|
}
|
|
169
261
|
}
|
|
170
262
|
|
|
171
|
-
.
|
|
263
|
+
.hero-gradient-bg {
|
|
264
|
+
/*Fallback*/
|
|
265
|
+
background: #000c14;
|
|
266
|
+
background: linear-gradient(
|
|
267
|
+
180deg,
|
|
268
|
+
#000c14 0%,
|
|
269
|
+
var(--primary, #004170) 100%
|
|
270
|
+
) !important;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.primary-gradient-bg,
|
|
274
|
+
.dark-section-gradient-bg {
|
|
172
275
|
/*Fallback*/
|
|
173
|
-
background:
|
|
174
|
-
background:
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
hsl(from var(--primary) h s calc(l - 20)) 100%
|
|
276
|
+
background: #000c14;
|
|
277
|
+
background: linear-gradient(
|
|
278
|
+
180deg,
|
|
279
|
+
var(--primary, #004170) 0%,
|
|
280
|
+
#000c14 100%
|
|
179
281
|
) !important;
|
|
180
282
|
}
|
|
181
283
|
|
|
@@ -345,3 +447,282 @@ eox-feedback-button {
|
|
|
345
447
|
z-index: calc(var(--vp-z-index-sidebar) + 2);
|
|
346
448
|
}
|
|
347
449
|
}
|
|
450
|
+
|
|
451
|
+
/* ==========================================================================
|
|
452
|
+
Simple Pages (layout: page) styling improvements
|
|
453
|
+
========================================================================== */
|
|
454
|
+
|
|
455
|
+
.layout-page {
|
|
456
|
+
background-color: var(--surface) !important;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.layout-page .VPPage {
|
|
460
|
+
max-width: 1200px;
|
|
461
|
+
margin-inline: auto;
|
|
462
|
+
padding-block-start: 66px; /* Exactly 156px from top of viewport (90px navbar + 66px padding) */
|
|
463
|
+
padding-block-end: 96px;
|
|
464
|
+
padding-inline: 24px;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/* Remove double inner padding on custom layout elements to ensure absolute alignment */
|
|
468
|
+
.layout-page .VPPage .holder {
|
|
469
|
+
padding-inline: 0 !important;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/* Constrain standard reading elements to 1000px max-width, while letting full-width custom page components span 1200px */
|
|
473
|
+
.layout-page
|
|
474
|
+
.VPPage
|
|
475
|
+
> div
|
|
476
|
+
> div
|
|
477
|
+
> :is(p, ul, ol, blockquote, h1, h2, h3, h4, h5, h6, pre, table) {
|
|
478
|
+
max-width: 1000px;
|
|
479
|
+
margin-inline-start: 0;
|
|
480
|
+
margin-inline-end: auto;
|
|
481
|
+
width: 100%;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
@media (max-width: 960px) {
|
|
485
|
+
.layout-page .VPPage {
|
|
486
|
+
padding-inline: 24px;
|
|
487
|
+
padding-block-start: 48px;
|
|
488
|
+
padding-block-end: 64px;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
@media (max-width: 640px) {
|
|
493
|
+
.layout-page .VPPage {
|
|
494
|
+
padding-inline: 16px;
|
|
495
|
+
padding-block-start: 36px;
|
|
496
|
+
padding-block-end: 48px;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/* Typography on simple pages inside main page content */
|
|
501
|
+
.layout-page .VPPage h1 {
|
|
502
|
+
font-size: 2rem; /* Exactly 32px */
|
|
503
|
+
line-height: 1.25;
|
|
504
|
+
margin-block-start: 0;
|
|
505
|
+
margin-block-end: 1.5rem;
|
|
506
|
+
color: var(--on-surface);
|
|
507
|
+
font-weight: 700;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
@media (max-width: 640px) {
|
|
511
|
+
.layout-page .VPPage h1 {
|
|
512
|
+
font-size: 1.75rem; /* 28px on mobile */
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.layout-page .VPPage h2 {
|
|
517
|
+
font-size: 1.5rem; /* Exactly 24px */
|
|
518
|
+
line-height: 1.35;
|
|
519
|
+
margin-block-start: 3rem;
|
|
520
|
+
margin-block-end: 1.125rem;
|
|
521
|
+
color: var(--on-surface);
|
|
522
|
+
border-top: none;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
@media (max-width: 640px) {
|
|
526
|
+
.layout-page .VPPage h2 {
|
|
527
|
+
font-size: 1.375rem; /* 22px on mobile */
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
.layout-page .VPPage h3 {
|
|
532
|
+
font-size: clamp(1.2rem, 3.5vw, 1.45rem);
|
|
533
|
+
line-height: 1.3;
|
|
534
|
+
margin-block-start: 2.25rem;
|
|
535
|
+
margin-block-end: 0.875rem;
|
|
536
|
+
color: var(--on-surface);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.layout-page .VPPage h4 {
|
|
540
|
+
font-size: 1.15rem;
|
|
541
|
+
line-height: 1.4;
|
|
542
|
+
margin-block-start: 1.75rem;
|
|
543
|
+
margin-block-end: 0.75rem;
|
|
544
|
+
color: var(--on-surface);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.layout-page .VPPage p {
|
|
548
|
+
font-size: 1rem; /* Exactly 16px */
|
|
549
|
+
line-height: 1.65;
|
|
550
|
+
margin-block-start: 0;
|
|
551
|
+
margin-block-end: 1.5rem;
|
|
552
|
+
color: var(--on-surface);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/* Lists */
|
|
556
|
+
.layout-page .VPPage ul,
|
|
557
|
+
.layout-page .VPPage ol {
|
|
558
|
+
margin-block-start: 0;
|
|
559
|
+
margin-block-end: 1.5rem;
|
|
560
|
+
padding-inline-start: 1.5rem;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.layout-page .VPPage li {
|
|
564
|
+
margin-block-end: 0.5rem;
|
|
565
|
+
line-height: 1.6;
|
|
566
|
+
font-size: 1rem; /* Exactly 16px */
|
|
567
|
+
color: var(--on-surface);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/* Inline links readability fix */
|
|
571
|
+
.layout-page .VPPage a:not(.button) {
|
|
572
|
+
color: var(--primary);
|
|
573
|
+
text-decoration: underline;
|
|
574
|
+
text-underline-offset: 3px;
|
|
575
|
+
text-decoration-thickness: 1px;
|
|
576
|
+
transition:
|
|
577
|
+
color 0.2s ease,
|
|
578
|
+
text-decoration-color 0.2s ease;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.layout-page .VPPage a:not(.button):hover {
|
|
582
|
+
opacity: 0.85;
|
|
583
|
+
text-decoration-thickness: 2px;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/* Scroll Anchors, Blockquotes & Code */
|
|
587
|
+
.layout-page .VPPage blockquote {
|
|
588
|
+
border-inline-start: 4px solid var(--primary);
|
|
589
|
+
padding-inline-start: 1.25rem;
|
|
590
|
+
margin-inline: 0;
|
|
591
|
+
margin-block: 2rem;
|
|
592
|
+
font-style: italic;
|
|
593
|
+
color: var(--on-surface-variant);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
.layout-page .VPPage sup,
|
|
597
|
+
.layout-page .VPPage sub {
|
|
598
|
+
font-size: 0.8rem;
|
|
599
|
+
line-height: 1;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
.layout-page .VPPage pre {
|
|
603
|
+
margin-block: 1.5rem;
|
|
604
|
+
padding: 1rem;
|
|
605
|
+
border-radius: 8px;
|
|
606
|
+
background-color: var(--surface-container-low);
|
|
607
|
+
overflow-x: auto;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/* Local Search styles overrides */
|
|
611
|
+
.VPLocalSearchBox .search-actions button {
|
|
612
|
+
height: 36px !important;
|
|
613
|
+
width: 36px !important;
|
|
614
|
+
min-width: 0 !important;
|
|
615
|
+
max-width: none !important;
|
|
616
|
+
border-radius: 50% !important;
|
|
617
|
+
padding: 0 !important;
|
|
618
|
+
display: inline-flex !important;
|
|
619
|
+
align-items: center !important;
|
|
620
|
+
justify-content: center !important;
|
|
621
|
+
border: none !important;
|
|
622
|
+
background: transparent !important;
|
|
623
|
+
box-shadow: none !important;
|
|
624
|
+
color: var(--vp-c-text-2) !important;
|
|
625
|
+
transition:
|
|
626
|
+
background-color 0.15s,
|
|
627
|
+
color 0.15s !important;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
.VPLocalSearchBox .search-actions button:not([disabled]):hover {
|
|
631
|
+
background-color: var(--vp-c-default-soft) !important;
|
|
632
|
+
color: var(--vp-c-brand-1) !important;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
.VPLocalSearchBox .search-actions button:disabled {
|
|
636
|
+
opacity: 0.37 !important;
|
|
637
|
+
background: transparent !important;
|
|
638
|
+
color: var(--vp-c-text-3) !important;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.VPLocalSearchBox .results {
|
|
642
|
+
list-style: none !important;
|
|
643
|
+
padding-left: 0 !important;
|
|
644
|
+
margin: 0 !important;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
.VPLocalSearchBox .results li {
|
|
648
|
+
list-style: none !important;
|
|
649
|
+
margin: 0 !important;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/* Screen Reader Only Utility */
|
|
653
|
+
.sr-only {
|
|
654
|
+
position: absolute !important;
|
|
655
|
+
width: 1px !important;
|
|
656
|
+
height: 1px !important;
|
|
657
|
+
padding: 0 !important;
|
|
658
|
+
margin: -1px !important;
|
|
659
|
+
overflow: hidden !important;
|
|
660
|
+
clip: rect(0, 0, 0, 0) !important;
|
|
661
|
+
white-space: nowrap !important;
|
|
662
|
+
border-width: 0 !important;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/* ==========================================================================
|
|
666
|
+
Links in text hover underline
|
|
667
|
+
========================================================================== */
|
|
668
|
+
|
|
669
|
+
a.link {
|
|
670
|
+
text-decoration: none;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
:is(p, li, blockquote, figcaption, td, th, dd, dt, .card-body-text)
|
|
674
|
+
a:not(
|
|
675
|
+
.button,
|
|
676
|
+
[role="button"],
|
|
677
|
+
.chip,
|
|
678
|
+
.badge,
|
|
679
|
+
.circle,
|
|
680
|
+
.header-anchor,
|
|
681
|
+
.card-cover-link,
|
|
682
|
+
.grid-link,
|
|
683
|
+
.sidebar-tag,
|
|
684
|
+
.post-tag,
|
|
685
|
+
.clickable-chip,
|
|
686
|
+
.tag-link,
|
|
687
|
+
.social-link-btn,
|
|
688
|
+
.custom-cta-button,
|
|
689
|
+
:has(> img:only-child),
|
|
690
|
+
:has(> svg:only-child)
|
|
691
|
+
):hover,
|
|
692
|
+
a.link:hover,
|
|
693
|
+
.vp-doc
|
|
694
|
+
a:not(
|
|
695
|
+
.button,
|
|
696
|
+
[role="button"],
|
|
697
|
+
.header-anchor,
|
|
698
|
+
.card-cover-link,
|
|
699
|
+
.grid-link,
|
|
700
|
+
.sidebar-tag,
|
|
701
|
+
.post-tag,
|
|
702
|
+
.clickable-chip,
|
|
703
|
+
.tag-link,
|
|
704
|
+
.social-link-btn,
|
|
705
|
+
.custom-cta-button,
|
|
706
|
+
:has(> img:only-child),
|
|
707
|
+
:has(> svg:only-child)
|
|
708
|
+
):hover {
|
|
709
|
+
text-decoration: underline;
|
|
710
|
+
text-underline-offset: 2px;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/* Ensure navigation bars, dropdown menus, sidebars, and outline links do not get hover underline unless explicitly marked .link */
|
|
714
|
+
:is(
|
|
715
|
+
nav,
|
|
716
|
+
menu,
|
|
717
|
+
dialog,
|
|
718
|
+
.top-nav,
|
|
719
|
+
.social-links,
|
|
720
|
+
.VPSidebar,
|
|
721
|
+
.VPDocAsideOutline,
|
|
722
|
+
.VPLocalSearchBox
|
|
723
|
+
)
|
|
724
|
+
a:not(.link):hover,
|
|
725
|
+
menu a:hover,
|
|
726
|
+
menu li a:hover {
|
|
727
|
+
text-decoration: none !important;
|
|
728
|
+
}
|
package/src/tagUtils.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
export const tagThemes = [
|
|
2
|
+
// Managed cloud workspace (Category 0)
|
|
3
|
+
[
|
|
4
|
+
"eoxhub",
|
|
5
|
+
"eurodatacube",
|
|
6
|
+
"cloud-processing",
|
|
7
|
+
"mundi",
|
|
8
|
+
"jupyter",
|
|
9
|
+
"vre",
|
|
10
|
+
"processing",
|
|
11
|
+
],
|
|
12
|
+
// Data management (Category 1)
|
|
13
|
+
[
|
|
14
|
+
"data-access",
|
|
15
|
+
"catalog",
|
|
16
|
+
"eo-data",
|
|
17
|
+
"open-search",
|
|
18
|
+
"ard",
|
|
19
|
+
"eoxserver",
|
|
20
|
+
"django",
|
|
21
|
+
"sxcat",
|
|
22
|
+
"data-cubes",
|
|
23
|
+
"opensearch",
|
|
24
|
+
],
|
|
25
|
+
// Data visualization (Category 2)
|
|
26
|
+
[
|
|
27
|
+
"3d",
|
|
28
|
+
"animation",
|
|
29
|
+
"cesium",
|
|
30
|
+
"globe",
|
|
31
|
+
"ndvi",
|
|
32
|
+
"plotty",
|
|
33
|
+
"graphly",
|
|
34
|
+
"geotiff-js",
|
|
35
|
+
"client",
|
|
36
|
+
"visualization",
|
|
37
|
+
"cog",
|
|
38
|
+
"geotiff",
|
|
39
|
+
"openlayers",
|
|
40
|
+
"vue-js",
|
|
41
|
+
"eoxc",
|
|
42
|
+
"dashboard",
|
|
43
|
+
"javascript",
|
|
44
|
+
"leaflet",
|
|
45
|
+
"d3",
|
|
46
|
+
"webgl",
|
|
47
|
+
"video",
|
|
48
|
+
"data visualization",
|
|
49
|
+
],
|
|
50
|
+
// Data products (Category 3)
|
|
51
|
+
[
|
|
52
|
+
"eoxcloudless",
|
|
53
|
+
"eoxmaps",
|
|
54
|
+
"s2cloudless",
|
|
55
|
+
"maps",
|
|
56
|
+
"sentinel-2",
|
|
57
|
+
"labels",
|
|
58
|
+
"cloudless-mosaic",
|
|
59
|
+
"voronoi-diagram",
|
|
60
|
+
"openstreetmap",
|
|
61
|
+
"mapchete",
|
|
62
|
+
],
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
export const tagColors = [
|
|
66
|
+
"rgb(255, 94, 94)", // Managed cloud workspace
|
|
67
|
+
"rgb(0, 177, 176)", // Data management
|
|
68
|
+
"rgb(219, 173, 66)", // Data visualization
|
|
69
|
+
"rgb(218, 71, 228)", // Data products
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
export const tagCategories = [
|
|
73
|
+
"Managed cloud workspace",
|
|
74
|
+
"Data management",
|
|
75
|
+
"Data visualization",
|
|
76
|
+
"Data products",
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get color for a given tag
|
|
81
|
+
* @param {string} tag
|
|
82
|
+
* @returns {string} color hex/rgb
|
|
83
|
+
*/
|
|
84
|
+
export function getTagColor(tag) {
|
|
85
|
+
if (!tag) return "#e0e0e0";
|
|
86
|
+
const cleanTag = tag.toLowerCase().trim();
|
|
87
|
+
for (let i = 0; i < tagThemes.length; i++) {
|
|
88
|
+
if (tagThemes[i].includes(cleanTag)) {
|
|
89
|
+
return tagColors[i];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return "#e0e0e0";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get style object for a given tag
|
|
97
|
+
* @param {string} tag
|
|
98
|
+
* @returns {object} style object
|
|
99
|
+
*/
|
|
100
|
+
export function getTagStyle(tag) {
|
|
101
|
+
const color = getTagColor(tag);
|
|
102
|
+
if (color.startsWith("rgb(255, 94, 94)")) {
|
|
103
|
+
return {
|
|
104
|
+
backgroundColor: "rgba(255, 94, 94, 0.15)",
|
|
105
|
+
border: "1px solid rgb(255, 94, 94)",
|
|
106
|
+
color: "#d32f2f",
|
|
107
|
+
};
|
|
108
|
+
} else if (color.startsWith("rgb(0, 177, 176)")) {
|
|
109
|
+
return {
|
|
110
|
+
backgroundColor: "rgba(0, 177, 176, 0.15)",
|
|
111
|
+
border: "1px solid rgb(0, 177, 176)",
|
|
112
|
+
color: "#00796b",
|
|
113
|
+
};
|
|
114
|
+
} else if (color.startsWith("rgb(219, 173, 66)")) {
|
|
115
|
+
return {
|
|
116
|
+
backgroundColor: "rgba(219, 173, 66, 0.15)",
|
|
117
|
+
border: "1px solid rgb(219, 173, 66)",
|
|
118
|
+
color: "#f57c00",
|
|
119
|
+
};
|
|
120
|
+
} else if (color.startsWith("rgb(218, 71, 228)")) {
|
|
121
|
+
return {
|
|
122
|
+
backgroundColor: "rgba(218, 71, 228, 0.15)",
|
|
123
|
+
border: "1px solid rgb(218, 71, 228)",
|
|
124
|
+
color: "#c2185b",
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
backgroundColor: "rgba(0, 0, 0, 0.05)",
|
|
129
|
+
border: "1px solid rgba(0, 0, 0, 0.1)",
|
|
130
|
+
color: "#475569",
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get category name for a given tag
|
|
136
|
+
* @param {string} tag
|
|
137
|
+
* @returns {string} category name
|
|
138
|
+
*/
|
|
139
|
+
export function getTagCategory(tag) {
|
|
140
|
+
if (!tag) return "Other";
|
|
141
|
+
const cleanTag = tag.toLowerCase().trim();
|
|
142
|
+
for (let i = 0; i < tagThemes.length; i++) {
|
|
143
|
+
if (tagThemes[i].includes(cleanTag)) {
|
|
144
|
+
return tagCategories[i];
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return "Other";
|
|
148
|
+
}
|
package/src/team.data.js
CHANGED
package/src/vitepressConfig.mjs
CHANGED
|
@@ -1,3 +1,90 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
function copyThemePages() {
|
|
5
|
+
try {
|
|
6
|
+
const themeSrcDir = path.dirname(new URL(import.meta.url).pathname);
|
|
7
|
+
const pages = [
|
|
8
|
+
{ src: "blog.md", dest: "blog.md" },
|
|
9
|
+
{ src: "tag.md", dest: "tag.md" },
|
|
10
|
+
{ src: "tag/[tag].md", dest: "tag/[tag].md" },
|
|
11
|
+
{
|
|
12
|
+
...(() => {
|
|
13
|
+
// Let's resolve the actual pages dir inside the theme package
|
|
14
|
+
// This is robust on any npm installation structure
|
|
15
|
+
return {};
|
|
16
|
+
})(),
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
// Better yet, just copy our built-in custom pages directly relative to this module
|
|
21
|
+
const filesToCopy = [
|
|
22
|
+
"blog.md",
|
|
23
|
+
"team.md",
|
|
24
|
+
"tag.md",
|
|
25
|
+
"tag/[tag].md",
|
|
26
|
+
"tag/[tag].paths.js",
|
|
27
|
+
"author/[author].md",
|
|
28
|
+
"author/[author].paths.js",
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const targetDir = process.cwd();
|
|
32
|
+
const pagesSrcDir = path.join(themeSrcDir, "pages");
|
|
33
|
+
|
|
34
|
+
for (const file of filesToCopy) {
|
|
35
|
+
const src = path.join(pagesSrcDir, file);
|
|
36
|
+
const dest = path.join(targetDir, file);
|
|
37
|
+
if (fs.existsSync(src)) {
|
|
38
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
39
|
+
|
|
40
|
+
let shouldCopy = !fs.existsSync(dest);
|
|
41
|
+
if (!shouldCopy) {
|
|
42
|
+
const srcContent = fs.readFileSync(src, "utf8");
|
|
43
|
+
const destContent = fs.readFileSync(dest, "utf8");
|
|
44
|
+
if (srcContent !== destContent) {
|
|
45
|
+
shouldCopy = true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (shouldCopy) {
|
|
49
|
+
fs.writeFileSync(dest, fs.readFileSync(src));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.error("Failed to copy theme pages:", err);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getBlogRewrites() {
|
|
59
|
+
const rewrites = {};
|
|
60
|
+
const postsDir = path.resolve(process.cwd(), "_posts");
|
|
61
|
+
if (!fs.existsSync(postsDir)) return rewrites;
|
|
62
|
+
|
|
63
|
+
const files = fs.readdirSync(postsDir).filter((f) => f.endsWith(".md"));
|
|
64
|
+
for (const file of files) {
|
|
65
|
+
const filePath = path.join(postsDir, file);
|
|
66
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
67
|
+
const dateMatch = content.match(/date:\s*["']?(\d{4})-(\d{2})-\d{2}["']?/);
|
|
68
|
+
if (dateMatch) {
|
|
69
|
+
const [_, year, month] = dateMatch;
|
|
70
|
+
const baseName = file.replace(/\.md$/, "");
|
|
71
|
+
const slug = baseName
|
|
72
|
+
.toLowerCase()
|
|
73
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
74
|
+
.replace(/^-+|-+$/g, "");
|
|
75
|
+
rewrites[`_posts/${file}`] = `${year}/${month}/${slug}.md`;
|
|
76
|
+
} else {
|
|
77
|
+
const baseName = file.replace(/\.md$/, "");
|
|
78
|
+
const slug = baseName
|
|
79
|
+
.toLowerCase()
|
|
80
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
81
|
+
.replace(/^-+|-+$/g, "");
|
|
82
|
+
rewrites[`_posts/${file}`] = `blog/${slug}.md`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return rewrites;
|
|
86
|
+
}
|
|
87
|
+
|
|
1
88
|
/**
|
|
2
89
|
* Base configuration for VitePress
|
|
3
90
|
* Documentation: see https://vitepress.dev/reference/site-config
|
|
@@ -5,9 +92,18 @@
|
|
|
5
92
|
* @returns
|
|
6
93
|
*/
|
|
7
94
|
export const generate = (brandConfig) => {
|
|
95
|
+
copyThemePages();
|
|
8
96
|
const config = {
|
|
9
97
|
appearance: false,
|
|
10
98
|
cleanUrls: true,
|
|
99
|
+
markdown: {
|
|
100
|
+
headers: {
|
|
101
|
+
level: [2, 3, 4, 5, 6],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
rewrites: {
|
|
105
|
+
...getBlogRewrites(),
|
|
106
|
+
},
|
|
11
107
|
description: brandConfig.meta?.description,
|
|
12
108
|
head: [
|
|
13
109
|
["link", { rel: "icon", href: brandConfig.meta?.favicon }],
|
|
@@ -93,6 +189,7 @@ export const generate = (brandConfig) => {
|
|
|
93
189
|
],
|
|
94
190
|
srcExclude: ["README.md"],
|
|
95
191
|
themeConfig: {
|
|
192
|
+
outline: "deep",
|
|
96
193
|
siteTitle: false,
|
|
97
194
|
theme: {
|
|
98
195
|
primaryColor: brandConfig.theme?.primary_color,
|
|
@@ -115,7 +212,7 @@ export const generate = (brandConfig) => {
|
|
|
115
212
|
></span>`,
|
|
116
213
|
copyright:
|
|
117
214
|
brandConfig.theme?.footer?.copyright ||
|
|
118
|
-
'Copyright ©
|
|
215
|
+
'Copyright © 2008-present <a href="https://eox.at" target="_blank">EOX IT Services GmbH</a>',
|
|
119
216
|
},
|
|
120
217
|
},
|
|
121
218
|
title: brandConfig.meta?.title,
|
|
@@ -123,6 +220,9 @@ export const generate = (brandConfig) => {
|
|
|
123
220
|
ssr: {
|
|
124
221
|
noExternal: ["@eox/pages-theme-eox"],
|
|
125
222
|
},
|
|
223
|
+
optimizeDeps: {
|
|
224
|
+
exclude: ["@eox/pages-theme-eox"],
|
|
225
|
+
},
|
|
126
226
|
},
|
|
127
227
|
vue: {
|
|
128
228
|
template: {
|