diff --git a/package-lock.json b/package-lock.json index 58774ecd6a9da0..0a4d174f17be39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -103,6 +103,7 @@ "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.32", "gh-pages": "^6.0.0", "globals": "^17.0.0", + "gray-matter": "^4.0.3", "husky": "^9.1.7", "lint-staged": "^16.2.7", "patch-package": "^8.0.1", diff --git a/package.json b/package.json index 3989cdfcedee5d..58bf2b1b0d8ac2 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "lint": "eslint --fix .", "checklint": "eslint .", "check:contributing-versions": "node .github/scripts/check-contributing-versions.cjs", - "test:unit": "node --test src/utils/build-collections.test.js src/utils/page-path-guard.test.js src/utils/resources-url.test.js", + "test:unit": "node --test src/utils/build-collections.test.js src/utils/page-path-guard.test.js src/utils/resources-url.test.js src/utils/dark-mode-logos.test.js", "pretest": "eslint --ignore-path .gitignore .", "deploy": "gatsby build && gh-pages -d public -b master", "noIndex": "gatsby build && echo 'User-agent: *\nDisallow: /' > public/robots.txt", @@ -132,6 +132,7 @@ "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.32", "gh-pages": "^6.0.0", "globals": "^17.0.0", + "gray-matter": "^4.0.3", "husky": "^9.1.7", "lint-staged": "^16.2.7", "patch-package": "^8.0.1", diff --git a/src/collections/integrations/aerospike-kubernetes-operator/icons/white/aerospike-kubernetes-operator-white.svg b/src/collections/integrations/aerospike-kubernetes-operator/icons/white/aerospike-kubernetes-operator-white.svg index 23d7c7f4df10c7..0ab219f82ee8e2 100644 --- a/src/collections/integrations/aerospike-kubernetes-operator/icons/white/aerospike-kubernetes-operator-white.svg +++ b/src/collections/integrations/aerospike-kubernetes-operator/icons/white/aerospike-kubernetes-operator-white.svg @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/src/collections/integrations/aws-node-termination-handler-2/icons/white/aws-node-termination-handler-2-white.svg b/src/collections/integrations/aws-node-termination-handler-2/icons/white/aws-node-termination-handler-2-white.svg index aa9e84b87c10f7..c9b3c2787e1e01 100644 --- a/src/collections/integrations/aws-node-termination-handler-2/icons/white/aws-node-termination-handler-2-white.svg +++ b/src/collections/integrations/aws-node-termination-handler-2/icons/white/aws-node-termination-handler-2-white.svg @@ -1 +1,13 @@ - \ No newline at end of file + + + + + + + + + + \ No newline at end of file diff --git a/src/collections/integrations/aws-vpc-cni/icons/white/aws-vpc-cni-white.svg b/src/collections/integrations/aws-vpc-cni/icons/white/aws-vpc-cni-white.svg index aa9e84b87c10f7..c9b3c2787e1e01 100644 --- a/src/collections/integrations/aws-vpc-cni/icons/white/aws-vpc-cni-white.svg +++ b/src/collections/integrations/aws-vpc-cni/icons/white/aws-vpc-cni-white.svg @@ -1 +1,13 @@ - \ No newline at end of file + + + + + + + + + + \ No newline at end of file diff --git a/src/collections/integrations/gitlab-controller/icons/color/gitlab-controller-color.svg b/src/collections/integrations/gitlab-controller/icons/color/gitlab-controller-color.svg index 8435de5170ce9a..21bc4022252112 100644 --- a/src/collections/integrations/gitlab-controller/icons/color/gitlab-controller-color.svg +++ b/src/collections/integrations/gitlab-controller/icons/color/gitlab-controller-color.svg @@ -1 +1,6 @@ - \ No newline at end of file + + + + + + diff --git a/src/collections/integrations/kubeform-provider-aws/icons/color/kubeform-provider-aws-color.svg b/src/collections/integrations/kubeform-provider-aws/icons/color/kubeform-provider-aws-color.svg index 6c9c88ef1cd3d0..03b9b6e624fc50 100644 --- a/src/collections/integrations/kubeform-provider-aws/icons/color/kubeform-provider-aws-color.svg +++ b/src/collections/integrations/kubeform-provider-aws/icons/color/kubeform-provider-aws-color.svg @@ -1,7 +1,8 @@ - - diff --git a/src/collections/integrations/kubeform-provider-aws/icons/white/kubeform-provider-aws-white.svg b/src/collections/integrations/kubeform-provider-aws/icons/white/kubeform-provider-aws-white.svg index aa9e84b87c10f7..6c9c88ef1cd3d0 100644 --- a/src/collections/integrations/kubeform-provider-aws/icons/white/kubeform-provider-aws-white.svg +++ b/src/collections/integrations/kubeform-provider-aws/icons/white/kubeform-provider-aws-white.svg @@ -1 +1,35 @@ - \ No newline at end of file + + + + + + + + + + \ No newline at end of file diff --git a/src/collections/integrations/ngrok-operator/icons/color/ngrok-operator-color.svg b/src/collections/integrations/ngrok-operator/icons/color/ngrok-operator-color.svg index c18fbe907a0211..d7a829a828c783 100644 --- a/src/collections/integrations/ngrok-operator/icons/color/ngrok-operator-color.svg +++ b/src/collections/integrations/ngrok-operator/icons/color/ngrok-operator-color.svg @@ -1,33 +1,33 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - \ No newline at end of file + diff --git a/src/collections/integrations/ngrok-operator/icons/white/ngrok-operator-white.svg b/src/collections/integrations/ngrok-operator/icons/white/ngrok-operator-white.svg index aa9e84b87c10f7..0fde52196c67f3 100644 --- a/src/collections/integrations/ngrok-operator/icons/white/ngrok-operator-white.svg +++ b/src/collections/integrations/ngrok-operator/icons/white/ngrok-operator-white.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/collections/integrations/rustrial-aws-eks-iam-auth-controller/icons/color/rustrial-aws-eks-iam-auth-controller-color.svg b/src/collections/integrations/rustrial-aws-eks-iam-auth-controller/icons/color/rustrial-aws-eks-iam-auth-controller-color.svg index e69de29bb2d1d6..46ca38b79c7135 100644 --- a/src/collections/integrations/rustrial-aws-eks-iam-auth-controller/icons/color/rustrial-aws-eks-iam-auth-controller-color.svg +++ b/src/collections/integrations/rustrial-aws-eks-iam-auth-controller/icons/color/rustrial-aws-eks-iam-auth-controller-color.svg @@ -0,0 +1,9 @@ + + Icon-Architecture/64/Arch_Amazon-Elastic-Kubernetes-Service_64 + + + + + + + \ No newline at end of file diff --git a/src/collections/integrations/rustrial-aws-eks-iam-auth-controller/icons/white/rustrial-aws-eks-iam-auth-controller-white.svg b/src/collections/integrations/rustrial-aws-eks-iam-auth-controller/icons/white/rustrial-aws-eks-iam-auth-controller-white.svg index e69de29bb2d1d6..ebaa2ff4b66a3d 100644 --- a/src/collections/integrations/rustrial-aws-eks-iam-auth-controller/icons/white/rustrial-aws-eks-iam-auth-controller-white.svg +++ b/src/collections/integrations/rustrial-aws-eks-iam-auth-controller/icons/white/rustrial-aws-eks-iam-auth-controller-white.svg @@ -0,0 +1,6 @@ + + Icon-Architecture/64/Arch_Amazon-Elastic-Kubernetes-Service_64 + + + + \ No newline at end of file diff --git a/src/collections/integrations/scheduler-plugins/icons/white/scheduler-plugins-white.svg b/src/collections/integrations/scheduler-plugins/icons/white/scheduler-plugins-white.svg index 0595e7bb5d2b98..d0bbeb6eca5aa1 100644 --- a/src/collections/integrations/scheduler-plugins/icons/white/scheduler-plugins-white.svg +++ b/src/collections/integrations/scheduler-plugins/icons/white/scheduler-plugins-white.svg @@ -1,9 +1,3 @@ - - - - - - - - - \ No newline at end of file + + + diff --git a/src/collections/integrations/wordpress-operator/icons/white/wordpress-operator-white.svg b/src/collections/integrations/wordpress-operator/icons/white/wordpress-operator-white.svg index 3629718b48ee46..dcd620b913494b 100644 --- a/src/collections/integrations/wordpress-operator/icons/white/wordpress-operator-white.svg +++ b/src/collections/integrations/wordpress-operator/icons/white/wordpress-operator-white.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/sections/Meshery/Meshery-integrations/IntegrationsGrid.js b/src/sections/Meshery/Meshery-integrations/IntegrationsGrid.js index ffe2b837766111..cfabfd16b8552f 100644 --- a/src/sections/Meshery/Meshery-integrations/IntegrationsGrid.js +++ b/src/sections/Meshery/Meshery-integrations/IntegrationsGrid.js @@ -6,6 +6,7 @@ import SearchBox from "../../../reusecore/Search"; import EmptyResources from "../../Resources/Resources-error/emptyStateTemplate"; import { Honeycomb, Hexagon } from "./Honeycomb/Honeycomb"; import { useStyledDarkMode } from "../../../theme/app/useStyledDarkMode"; +import { selectIntegrationIcon } from "../../../utils/dark-mode-logos"; const IntegrationsGrid = ({ category, count }) => { const data = useStaticQuery(graphql` @@ -264,13 +265,13 @@ const IntegrationsGrid = ({ category, count }) => { renderItem={(item) => { const status = item.frontmatter.status === "InProgress" ? true : false; - const integrationIcon = item.frontmatter.integrationIcon?.publicURL; - const hasDedicatedDarkIcon = Boolean( - item.frontmatter.darkModeIntegrationIcon, - ); - const darkModeIntegrationIcon = - item.frontmatter.darkModeIntegrationIcon || - item.frontmatter.integrationIcon; + const iconSrc = selectIntegrationIcon({ + slugPath: item.fields.slug, + iconURL: item.frontmatter.integrationIcon?.publicURL, + darkModeIconURL: + item.frontmatter.darkModeIntegrationIcon?.publicURL, + isDark, + }); if (status) { return ( { {item.frontmatter.title}
@@ -308,28 +304,14 @@ const IntegrationsGrid = ({ category, count }) => { {item.frontmatter.title}
{item.frontmatter.title}
- {/*
diff --git a/src/utils/dark-mode-logos.js b/src/utils/dark-mode-logos.js new file mode 100644 index 00000000000000..2a6810746050ef --- /dev/null +++ b/src/utils/dark-mode-logos.js @@ -0,0 +1,65 @@ +/* eslint-env node */ + +// Integration slugs (the last segment of fields.slug, derived from the +// permalink or title) whose color logo is too dark for the dark theme, so the +// grid shows their darkModeIntegrationIcon instead. +const DARK_MODE_LOGO_SLUGS = new Set([ + "actions-runner-controller-arc", + "aerospike-kubernetes-operator", + "awx-operator", + "chaosblade", + "cloudnativepg", + "contrail-analytics", + "cortex", + "dapr", + "github-actions-runner-operator", + "github-actions-runners", + "helm-controller", + "intel-device-plugins-operator", + "kommander", + "kong-api-gateway", + "kong-mesh", + "kubevela", + "kuma", + "skooner", + "vela-workflow", + "victoria-metrics-k8s-stack", + "containerd", + "tuf", + "tikv-operator", + "ngrok-operator", + "kube-rs", + "kubeform-provider-aws", + "wordpress-operator", + "scheduler-plugins", + "aws-node-termination-handler", + "aws-target-group-binding", + "aws-vpc-cni", + "rustrial-aws-eks-iam-auth-controller", + "aws-opensearch-service", + "aws-simple-queuing-service", + "aws-systems-manager", +]); + +const getIntegrationSlug = (slugPath) => + slugPath.split("/").filter(Boolean).pop(); + +// Listed integrations use their dark-mode icon in the dark theme when they +// have one; every other logo keeps its original colors. +const selectIntegrationIcon = ({ + slugPath, + iconURL, + darkModeIconURL, + isDark, +}) => + isDark && + darkModeIconURL && + DARK_MODE_LOGO_SLUGS.has(getIntegrationSlug(slugPath)) + ? darkModeIconURL + : iconURL; + +module.exports = { + DARK_MODE_LOGO_SLUGS, + getIntegrationSlug, + selectIntegrationIcon, +}; diff --git a/src/utils/dark-mode-logos.test.js b/src/utils/dark-mode-logos.test.js new file mode 100644 index 00000000000000..10c931259c1d87 --- /dev/null +++ b/src/utils/dark-mode-logos.test.js @@ -0,0 +1,120 @@ +/* eslint-env node */ + +const { describe, it } = require("node:test"); +const assert = require("node:assert/strict"); +const fs = require("fs"); +const path = require("path"); +const matter = require("gray-matter"); + +const slugify = require("./slugify"); +const { + DARK_MODE_LOGO_SLUGS, + getIntegrationSlug, + selectIntegrationIcon, +} = require("./dark-mode-logos"); + +const INTEGRATIONS_DIR = path.join(__dirname, "../collections/integrations"); + +// Mirrors how gatsby-node.js builds fields.slug for the integrations collection. +const publishedIntegrations = fs + .readdirSync(INTEGRATIONS_DIR) + .map((dir) => path.join(INTEGRATIONS_DIR, dir, "index.mdx")) + .filter((file) => fs.existsSync(file)) + .map((file) => { + const { data } = matter(fs.readFileSync(file, "utf8")); + return { + dir: path.dirname(file), + published: data.published === true, + slug: `/integrations/${data.permalink ? data.permalink : slugify(data.title)}`, + darkModeIcon: data.darkModeIntegrationIcon, + }; + }) + .filter((integration) => integration.published); + +describe("DARK_MODE_LOGO_SLUGS", () => { + for (const slug of DARK_MODE_LOGO_SLUGS) { + it(`${slug} matches one published integration with a dark-mode icon`, () => { + const matches = publishedIntegrations.filter( + (integration) => getIntegrationSlug(integration.slug) === slug, + ); + assert.equal(matches.length, 1); + + const [{ dir, darkModeIcon }] = matches; + assert.ok(darkModeIcon, "darkModeIntegrationIcon is not set"); + const iconFile = path.join(dir, darkModeIcon); + assert.ok(fs.existsSync(iconFile), `${darkModeIcon} does not exist`); + assert.ok(fs.statSync(iconFile).size > 0, `${darkModeIcon} is empty`); + }); + } +}); + +describe("selectIntegrationIcon", () => { + const icons = { iconURL: "/color.svg", darkModeIconURL: "/white.svg" }; + + it("uses the dark-mode icon for a listed integration in the dark theme", () => { + assert.equal( + selectIntegrationIcon({ + ...icons, + slugPath: "/integrations/kuma", + isDark: true, + }), + "/white.svg", + ); + }); + + it("matches the slug when the path has a trailing slash", () => { + assert.equal( + selectIntegrationIcon({ + ...icons, + slugPath: "/integrations/kuma/", + isDark: true, + }), + "/white.svg", + ); + }); + + it("keeps the color icon in the light theme", () => { + assert.equal( + selectIntegrationIcon({ + ...icons, + slugPath: "/integrations/kuma", + isDark: false, + }), + "/color.svg", + ); + }); + + it("keeps the color icon for an unlisted integration", () => { + assert.equal( + selectIntegrationIcon({ + ...icons, + slugPath: "/integrations/gitlab", + isDark: true, + }), + "/color.svg", + ); + }); + + it("matches exact slugs only", () => { + assert.equal( + selectIntegrationIcon({ + ...icons, + slugPath: "/integrations/kuma-mesh", + isDark: true, + }), + "/color.svg", + ); + }); + + it("falls back to the color icon when there is no dark-mode icon", () => { + assert.equal( + selectIntegrationIcon({ + iconURL: "/color.svg", + darkModeIconURL: undefined, + slugPath: "/integrations/kuma", + isDark: true, + }), + "/color.svg", + ); + }); +});