diff --git a/website/package.json b/website/package.json
index 1ab7e698b318..22f1dd202e89 100644
--- a/website/package.json
+++ b/website/package.json
@@ -31,6 +31,7 @@
"docusaurus-plugin-openapi-docs": "2.0.0-beta.3",
"docusaurus-plugin-remote-content": "^3.1.0",
"docusaurus-theme-openapi-docs": "2.0.0-beta.2",
+ "git-url-parse": "^14.0.0",
"plugin-image-zoom": "flexanalytics/plugin-image-zoom",
"prism-svelte": "^0.5.0",
"react": "18.2.0",
diff --git a/website/src/css/custom.css b/website/src/css/custom.css
index 26fb467341e0..407e8d03043e 100644
--- a/website/src/css/custom.css
+++ b/website/src/css/custom.css
@@ -17,6 +17,7 @@
--navbar-link-color: #122d33;
--unleash-font-size-smaller: 90%;
+ --ifm-footer-logo-max-width: 250px;
/* navbar is independent of the theme in general */
--ifm-navbar-background-color: var(--unleash-color-green);
diff --git a/website/src/theme/DocItem/Footer/GitHubContributors.jsx b/website/src/theme/DocItem/Footer/GitHubContributors.jsx
new file mode 100644
index 000000000000..fd3ff533227e
--- /dev/null
+++ b/website/src/theme/DocItem/Footer/GitHubContributors.jsx
@@ -0,0 +1,92 @@
+// biome-ignore lint/correctness/noUnusedImports: Needs this for React to work
+import React, { useState, useEffect } from 'react';
+import { getContributors } from './contributors';
+import styles from './contributors.module.scss';
+
+const unleashTeam = new Map([
+ ['alvinometric', 'developer advocate, Unleash'],
+ ['andreas-unleash', 'developer, Unleash'],
+ ['chriswk', 'principal developer, Unleash'],
+ ['daveleek', 'developer, Unleash'],
+ ['FredrikOseberg', 'principal developer, Unleash'],
+ ['gardleopard', 'platform lead, Unleash'],
+ ['gastonfournier', 'senior developer, Unleash'],
+ ['ivarconr', 'co-founder, Unleash'],
+ ['kwasniew', 'senior developer, Unleash'],
+ ['nnennandukwe', 'developer advocate, Unleash'],
+ ['nunogois', 'senior developer, Unleash'],
+ ['sighphyre', 'senior developer, Unleash'],
+ ['sjaanus', 'senior developer, Unleash'],
+ ['thomasheartman', 'developer, Unleash'],
+ ['Tymek', 'developer, Unleash'],
+]);
+
+const GitHubContributors = ({ owner, repo, filePath }) => {
+ const [contributors, setContributors] = useState([]);
+ const url = `https://api.github.com/repos/${owner}/${repo}/commits?path=${filePath}`;
+
+ useEffect(() => {
+ const fetchFileContributors = () => {
+ fetch(url)
+ .then((response) => response.json())
+ .then((commits) => {
+ const contributors = getContributors(commits);
+
+ contributors.sort((a, b) => {
+ if (unleashTeam.has(a.login)) {
+ return -1;
+ }
+ return 1;
+ });
+ setContributors(contributors);
+ })
+ .catch((error) => {
+ console.error(error);
+ setContributors([]);
+ });
+ };
+
+ fetchFileContributors();
+ }, []);
+
+ if (!contributors.length) {
+ return null;
+ }
+
+ return (
+
+
Contributors
+
+
+ {contributors?.map((contributor) => {
+ const isUnleashTeam = unleashTeam.has(contributor.login);
+ const name = isUnleashTeam
+ ? `${contributor.login}, ${unleashTeam.get(
+ contributor.login,
+ )}`
+ : contributor.login;
+ return (
+ -
+
+
+
+
+ );
+ })}
+
+
+ );
+};
+
+export default GitHubContributors;
diff --git a/website/src/theme/DocItem/Footer/contributors.js b/website/src/theme/DocItem/Footer/contributors.js
new file mode 100644
index 000000000000..9e501be5f13b
--- /dev/null
+++ b/website/src/theme/DocItem/Footer/contributors.js
@@ -0,0 +1,23 @@
+export const getContributors = (commits) => {
+ // filter out commits that don't have an author
+ const commitsWithAuthors = commits.filter((commit) => !!commit.author);
+
+ // use a Set to deduplicate the list of contributors
+ const contributorSet = new Set();
+ for (const commit of commitsWithAuthors) {
+ contributorSet.add(JSON.stringify(commit.author));
+ }
+
+ const contributors = Array.from(contributorSet).map((str) => {
+ const contributor = JSON.parse(str);
+ const { login, html_url, avatar_url } = contributor;
+ return { login, html_url, avatar_url };
+ });
+
+ // sort alphabetically
+ contributors.sort((a, b) => {
+ return a.login.localeCompare(b.login);
+ });
+
+ return contributors;
+};
diff --git a/website/src/theme/DocItem/Footer/contributors.module.scss b/website/src/theme/DocItem/Footer/contributors.module.scss
new file mode 100644
index 000000000000..da4353128af4
--- /dev/null
+++ b/website/src/theme/DocItem/Footer/contributors.module.scss
@@ -0,0 +1,56 @@
+.contributors {
+ margin-block: var(--ifm-spacing-vertical);
+}
+
+.wrapper {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20px;
+ margin: 0;
+ padding: 0;
+
+ li{
+ list-style: none;
+ }
+}
+
+.unleash{
+ position: relative;
+ display: block;
+}
+
+.unleash:before{
+ display: block;
+ position: absolute;
+ z-index: 2;
+ content: '';
+ top: -5px;
+ right: -5px;
+ width: 30px;
+ height: 30px;
+ background-image: url(/img/logo.svg);
+}
+
+.contributor {
+ margin-top: 10px;
+
+ img{
+ border-radius: 100%;
+ margin:0;
+ padding: 0;
+ border: 2px solid var(--unleash-color-gray);
+ transition: border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default),
+ scale var(--ifm-transition-fast) var(--ifm-transition-timing-default);
+ }
+}
+
+.contributor img:hover{
+ border-color: var(--ifm-pagination-nav-color-hover);
+ scale: 1.1;
+}
+
+@media (max-width: 600px) {
+ .wrapper {
+ display: block;
+ }
+}
diff --git a/website/src/theme/DocItem/Footer/contributors.test.js b/website/src/theme/DocItem/Footer/contributors.test.js
new file mode 100644
index 000000000000..1c96cee9bdca
--- /dev/null
+++ b/website/src/theme/DocItem/Footer/contributors.test.js
@@ -0,0 +1,99 @@
+const commits = [
+ {
+ sha: '2754c26f2e022b623e46e08fc1108b350710ef91',
+ node_id:
+ 'C_kwDOAXdJ9doAKDI3NTRjMjZmMmUwMjJiNjIzZTQ2ZTA4ZmMxMTA4YjM1MDcxMGVmOTE',
+ url: 'https://api.github.com/repos/Unleash/unleash/commits/2754c26f2e022b623e46e08fc1108b350710ef91',
+ html_url:
+ 'https://github.com/Unleash/unleash/commit/2754c26f2e022b623e46e08fc1108b350710ef91',
+ comments_url:
+ 'https://api.github.com/repos/Unleash/unleash/commits/2754c26f2e022b623e46e08fc1108b350710ef91/comments',
+ author: {
+ login: 'markunl',
+ id: 128738155,
+ node_id: 'U_kgDOB6xjaw',
+ avatar_url: 'https://avatars.githubusercontent.com/u/128738155?v=4',
+ gravatar_id: '',
+ url: 'https://api.github.com/users/markunl',
+ html_url: 'https://github.com/markunl',
+ type: 'User',
+ site_admin: false,
+ },
+ },
+ {
+ sha: 'd5fbd0b743cc99791d34864c70f78985cc83b2d8',
+ node_id:
+ 'C_kwDOAXdJ9doAKGQ1ZmJkMGI3NDNjYzk5NzkxZDM0ODY0YzcwZjc4OTg1Y2M4M2IyZDg',
+ url: 'https://api.github.com/repos/Unleash/unleash/commits/d5fbd0b743cc99791d34864c70f78985cc83b2d8',
+ html_url:
+ 'https://github.com/Unleash/unleash/commit/d5fbd0b743cc99791d34864c70f78985cc83b2d8',
+ comments_url:
+ 'https://api.github.com/repos/Unleash/unleash/commits/d5fbd0b743cc99791d34864c70f78985cc83b2d8/comments',
+ author: {
+ login: 'thomasheartman',
+ id: 17786332,
+ node_id: 'MDQ6VXNlcjE3Nzg2MzMy',
+ avatar_url: 'https://avatars.githubusercontent.com/u/17786332?v=4',
+ gravatar_id: '',
+ url: 'https://api.github.com/users/thomasheartman',
+ html_url: 'https://github.com/thomasheartman',
+ type: 'User',
+ site_admin: false,
+ },
+ },
+ {
+ sha: 'ebcab898e7610082d3ada81ab0b729ba1f17655d',
+ node_id:
+ 'C_kwDOAXdJ9doAKGViY2FiODk4ZTc2MTAwODJkM2FkYTgxYWIwYjcyOWJhMWYxNzY1NWQ',
+ url: 'https://api.github.com/repos/Unleash/unleash/commits/ebcab898e7610082d3ada81ab0b729ba1f17655d',
+ html_url:
+ 'https://github.com/Unleash/unleash/commit/ebcab898e7610082d3ada81ab0b729ba1f17655d',
+ comments_url:
+ 'https://api.github.com/repos/Unleash/unleash/commits/ebcab898e7610082d3ada81ab0b729ba1f17655d/comments',
+ author: {
+ login: 'thomasheartman',
+ id: 17786332,
+ node_id: 'MDQ6VXNlcjE3Nzg2MzMy',
+ avatar_url: 'https://avatars.githubusercontent.com/u/17786332?v=4',
+ gravatar_id: '',
+ url: 'https://api.github.com/users/thomasheartman',
+ html_url: 'https://github.com/thomasheartman',
+ type: 'User',
+ site_admin: false,
+ },
+ },
+ {
+ sha: 'ead86ed62191777895d5a5f1a7c58f16a87ebde7',
+ node_id:
+ 'C_kwDOAXdJ9doAKGVhZDg2ZWQ2MjE5MTc3Nzg5NWQ1YTVmMWE3YzU4ZjE2YTg3ZWJkZTc',
+ author: {
+ login: 'thomasheartman',
+ id: 17786332,
+ node_id: 'MDQ6VXNlcjE3Nzg2MzMy',
+ avatar_url: 'https://avatars.githubusercontent.com/u/17786332?v=4',
+ gravatar_id: '',
+ url: 'https://api.github.com/users/thomasheartman',
+ html_url: 'https://github.com/thomasheartman',
+ type: 'User',
+ site_admin: false,
+ },
+ },
+];
+
+const expectedContributors = [
+ {
+ login: 'thomasheartman',
+ html_url: 'https://github.com/thomasheartman',
+ avatar_url: 'https://avatars.githubusercontent.com/u/17786332?v=4',
+ },
+ {
+ login: 'markunl',
+ html_url: 'https://github.com/markunl',
+ avatar_url: 'https://avatars.githubusercontent.com/u/128738155?v=4',
+ },
+];
+
+test('getContributors should return the correct list of contributors', () => {
+ const contributors = getContributors(commits);
+ expect(contributors).toEqual(expectedContributors);
+});
diff --git a/website/src/theme/DocItem/Footer/index.jsx b/website/src/theme/DocItem/Footer/index.jsx
new file mode 100644
index 000000000000..eceb37171b48
--- /dev/null
+++ b/website/src/theme/DocItem/Footer/index.jsx
@@ -0,0 +1,25 @@
+// biome-ignore lint/correctness/noUnusedImports: Needs this for React to work
+import React from 'react';
+import Footer from '@theme-original/DocItem/Footer';
+import { useDoc } from '@docusaurus/theme-common/internal';
+import GitHubContributors from './GitHubContributors';
+import GitUrlParse from 'git-url-parse';
+
+export default function FooterWrapper(props) {
+ const { metadata } = useDoc();
+ const file = metadata.editUrl;
+
+ if (!file) {
+ return ;
+ }
+
+ const info = GitUrlParse(file);
+ const { name, owner, filepath } = info;
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/website/static/img/logo.svg b/website/static/img/logo.svg
index b79f917031f4..05f7c9f51e4b 100644
--- a/website/static/img/logo.svg
+++ b/website/static/img/logo.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/website/yarn.lock b/website/yarn.lock
index e5e6082bd8d6..02e79efac610 100644
--- a/website/yarn.lock
+++ b/website/yarn.lock
@@ -6743,6 +6743,21 @@ get-stream@^6.0.0, get-stream@^6.0.1:
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+git-up@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/git-up/-/git-up-7.0.0.tgz#bace30786e36f56ea341b6f69adfd83286337467"
+ integrity sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==
+ dependencies:
+ is-ssh "^1.4.0"
+ parse-url "^8.1.0"
+
+git-url-parse@^14.0.0:
+ version "14.0.0"
+ resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-14.0.0.tgz#18ce834726d5fbca0c25a4555101aa277017418f"
+ integrity sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==
+ dependencies:
+ git-up "^7.0.0"
+
github-slugger@^1.4.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.5.0.tgz#17891bbc73232051474d68bd867a34625c955f7d"
@@ -7645,6 +7660,13 @@ is-root@^2.1.0:
resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c"
integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==
+is-ssh@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.4.0.tgz#4f8220601d2839d8fa624b3106f8e8884f01b8b2"
+ integrity sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==
+ dependencies:
+ protocols "^2.0.1"
+
is-stream@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
@@ -9020,6 +9042,20 @@ parse-numeric-range@^1.3.0:
resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz#7c63b61190d61e4d53a1197f0c83c47bb670ffa3"
integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==
+parse-path@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-7.0.0.tgz#605a2d58d0a749c8594405d8cc3a2bf76d16099b"
+ integrity sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==
+ dependencies:
+ protocols "^2.0.0"
+
+parse-url@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-8.1.0.tgz#972e0827ed4b57fc85f0ea6b0d839f0d8a57a57d"
+ integrity sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==
+ dependencies:
+ parse-path "^7.0.0"
+
parse5-htmlparser2-tree-adapter@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1"
@@ -9567,6 +9603,11 @@ property-information@^6.0.0:
resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.1.1.tgz#5ca85510a3019726cb9afed4197b7b8ac5926a22"
integrity sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==
+protocols@^2.0.0, protocols@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86"
+ integrity sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==
+
proxy-addr@~2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"