@eox/pages-theme-eox 1.9.0 → 2.0.0-alpha.2

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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  import { createContentLoader } from "vitepress";
2
2
 
3
- export default createContentLoader("team/*.md", {
3
+ export default createContentLoader("_team/*.md", {
4
4
  transform(rawData) {
5
5
  return rawData
6
6
  .filter((page) => {
@@ -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,
@@ -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: {