From 09c89fa13b9327e8c75066a67f4d150ae3a06cfb Mon Sep 17 00:00:00 2001 From: cooronx <2197083441@qq.com> Date: Mon, 13 Apr 2026 21:19:29 +0800 Subject: [PATCH 1/5] feat: replace footer star section fetch with generated JSON --- .github/workflows/master.yml | 3 + .github/workflows/pr_ci.yml | 3 + docusaurus.config.js | 52 +---- package.json | 1 + scripts/generate-footer-stars.js | 90 +++++++++ src/components/FooterMoreBadges/badges.json | 58 ++++++ src/components/FooterMoreBadges/index.js | 180 ++++++++++++++++++ src/components/FooterMoreBadges/stars.json | 13 ++ .../FooterMoreBadges/styles.module.css | 47 +++++ src/css/custom.css | 40 ---- src/theme/Footer/Links/MultiColumn/index.js | 75 ++++++++ 11 files changed, 471 insertions(+), 91 deletions(-) create mode 100644 scripts/generate-footer-stars.js create mode 100644 src/components/FooterMoreBadges/badges.json create mode 100644 src/components/FooterMoreBadges/index.js create mode 100644 src/components/FooterMoreBadges/stars.json create mode 100644 src/components/FooterMoreBadges/styles.module.css create mode 100644 src/theme/Footer/Links/MultiColumn/index.js diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index c768916f9..6c0091a4a 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -48,6 +48,9 @@ jobs: if: github.event_name != 'pull_request' run: yarn crowdin:sync + - name: Generate footer stars + run: yarn generate:footer-stars + - name: Build run: yarn build diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml index 8c68a5795..3024e6cec 100644 --- a/.github/workflows/pr_ci.yml +++ b/.github/workflows/pr_ci.yml @@ -22,5 +22,8 @@ jobs: - name: Install dependencies run: yarn install + - name: Generate footer stars + run: yarn generate:footer-stars + - name: Build website run: yarn build --locale en diff --git a/docusaurus.config.js b/docusaurus.config.js index fb91717f2..ab6625af1 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -234,60 +234,10 @@ module.exports = { }, { title: "More", + className: "footer-more-column", items: [ { html: ` - - GitHub Repo stars - -            - - GitHub Repo stars - - `, - }, - { - html: ` - - GitHub Repo stars - -    - - GitHub Repo stars - - `, - }, - { - html: ` - - GitHub Repo stars - -         - - GitHub Repo stars - - `, - }, - { - html: ` - - GitHub Repo stars - -      - - GitHub Repo stars - - `, - }, - { - html: ` - - Twitter Follow - - `, - }, - { - html: ` -`, - }, - ], + items: [], }, ], logo: { From 438b7c5e204e3d407b14235711c0ce33d9c22c13 Mon Sep 17 00:00:00 2001 From: cooronx <2197083441@qq.com> Date: Wed, 15 Apr 2026 22:53:23 +0800 Subject: [PATCH 3/5] feat: replace index keys in footer links --- src/theme/Footer/Links/MultiColumn/index.js | 30 ++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/theme/Footer/Links/MultiColumn/index.js b/src/theme/Footer/Links/MultiColumn/index.js index 50a88aa19..9431008df 100644 --- a/src/theme/Footer/Links/MultiColumn/index.js +++ b/src/theme/Footer/Links/MultiColumn/index.js @@ -4,6 +4,24 @@ import {ThemeClassNames} from "@docusaurus/theme-common"; import LinkItem from "@theme/Footer/LinkItem"; import FooterMoreBadges from "@site/src/components/FooterMoreBadges"; +function getItemKey(item) { + return [ + item.href, + item.to, + item.label, + item.className, + item.html, + ].filter(Boolean).join("::"); +} + +function getColumnKey(column) { + return [ + column.title, + column.className, + ...column.items.map(getItemKey), + ].filter(Boolean).join("::"); +} + function ColumnLinkItem({item}) { return item.html ? (
  • - {column.items.map((item, index) => ( - + {column.items.map((item) => ( + ))} ) : (
      - {column.items.map((item, index) => ( - + {column.items.map((item) => ( + ))}
    )} @@ -67,8 +85,8 @@ function Column({column}) { export default function FooterLinksMultiColumn({columns}) { return (
    - {columns.map((column, index) => ( - + {columns.map((column) => ( + ))}
    ); From f621ea211457ed954e68ee0cd3d379ce797f7e7e Mon Sep 17 00:00:00 2001 From: cooronx <54298598+cooronx@users.noreply.github.com> Date: Thu, 16 Apr 2026 00:17:44 +0800 Subject: [PATCH 4/5] feat: use smaller stable keys for footer items Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/theme/Footer/Links/MultiColumn/index.js | 27 +++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/theme/Footer/Links/MultiColumn/index.js b/src/theme/Footer/Links/MultiColumn/index.js index 9431008df..a935742f4 100644 --- a/src/theme/Footer/Links/MultiColumn/index.js +++ b/src/theme/Footer/Links/MultiColumn/index.js @@ -4,14 +4,37 @@ import {ThemeClassNames} from "@docusaurus/theme-common"; import LinkItem from "@theme/Footer/LinkItem"; import FooterMoreBadges from "@site/src/components/FooterMoreBadges"; +function getShortHash(value) { + let hash = 0; + + for (let index = 0; index < value.length; index += 1) { + hash = (hash * 31 + value.charCodeAt(index)) >>> 0; + } + + return hash.toString(36); +} + function getItemKey(item) { - return [ + if (item.id) { + return item.id; + } + + const stableKey = [ item.href, item.to, item.label, item.className, - item.html, ].filter(Boolean).join("::"); + + if (stableKey) { + return stableKey; + } + + if (item.html) { + return `html:${getShortHash(item.html)}`; + } + + return "item"; } function getColumnKey(column) { From c7a3592357cde49d1273dd0313b27c8013ae012f Mon Sep 17 00:00:00 2001 From: cooronx <2197083441@qq.com> Date: Thu, 16 Apr 2026 01:01:25 +0800 Subject: [PATCH 5/5] feat: xtract footer badges into svg icon components --- src/components/FooterMoreBadges/badges.json | 24 +-- src/components/FooterMoreBadges/index.js | 150 ++++-------------- .../FooterMoreBadges/styles.module.css | 76 ++++++++- static/img/footer/github.svg | 3 + static/img/footer/x.svg | 3 + 5 files changed, 116 insertions(+), 140 deletions(-) create mode 100644 static/img/footer/github.svg create mode 100644 static/img/footer/x.svg diff --git a/src/components/FooterMoreBadges/badges.json b/src/components/FooterMoreBadges/badges.json index 092941c0a..d26952cd5 100644 --- a/src/components/FooterMoreBadges/badges.json +++ b/src/components/FooterMoreBadges/badges.json @@ -3,56 +3,48 @@ "label": "Casbin", "owner": "casbin", "repo": "casbin", - "href": "https://github.com/casbin/casbin", - "labelWidth": 64 + "href": "https://github.com/casbin/casbin" }, { "label": "jCasbin", "owner": "casbin", "repo": "jcasbin", - "href": "https://github.com/casbin/jcasbin", - "labelWidth": 70 + "href": "https://github.com/casbin/jcasbin" }, { "label": "Node-Casbin", "owner": "casbin", "repo": "node-casbin", - "href": "https://github.com/casbin/node-casbin", - "labelWidth": 96 + "href": "https://github.com/casbin/node-casbin" }, { "label": "PHP-Casbin", "owner": "php-casbin", "repo": "php-casbin", - "href": "https://github.com/php-casbin/php-casbin", - "labelWidth": 90 + "href": "https://github.com/php-casbin/php-casbin" }, { "label": "PyCasbin", "owner": "casbin", "repo": "pycasbin", - "href": "https://github.com/casbin/pycasbin", - "labelWidth": 76 + "href": "https://github.com/casbin/pycasbin" }, { "label": "Casbin.NET", "owner": "casbin", "repo": "Casbin.NET", - "href": "https://github.com/casbin/Casbin.NET", - "labelWidth": 88 + "href": "https://github.com/casbin/Casbin.NET" }, { "label": "Casbin-CPP", "owner": "casbin", "repo": "casbin-cpp", - "href": "https://github.com/casbin/casbin-cpp", - "labelWidth": 90 + "href": "https://github.com/casbin/casbin-cpp" }, { "label": "Casbin-RS", "owner": "casbin", "repo": "casbin-rs", - "href": "https://github.com/casbin/casbin-rs", - "labelWidth": 84 + "href": "https://github.com/casbin/casbin-rs" } ] diff --git a/src/components/FooterMoreBadges/index.js b/src/components/FooterMoreBadges/index.js index 21dfe0f6f..412108190 100644 --- a/src/components/FooterMoreBadges/index.js +++ b/src/components/FooterMoreBadges/index.js @@ -1,24 +1,16 @@ -import React, {useId} from "react"; +import React from "react"; import styles from "./styles.module.css"; import githubBadges from "./badges.json"; import starsData from "./stars.json"; +const GITHUB_BADGES = githubBadges; +const STAR_COUNTS = starsData.stars ?? {}; const STAR_FORMATTER = new Intl.NumberFormat("en-US", { notation: "compact", compactDisplay: "short", maximumFractionDigits: 1, }); -const GITHUB_BADGES = githubBadges; -const STAR_COUNTS = starsData.stars ?? {}; - -// github SVG path -const GITHUB_ICON_PATH = - "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"; -// X SVG path -const X_ICON_PATH = - "M14.234 10.162 22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299-.929-1.329L3.076 1.56h3.182l5.965 8.532.929 1.329 7.754 11.09h-3.186z"; - function getRepoKey(owner, repo) { return `${owner}/${repo}`; } @@ -27,113 +19,6 @@ function formatStars(count) { return STAR_FORMATTER.format(count).replace(/\.0(?=[A-Za-z])/u, "").toLowerCase(); } -function getCountWidth(value) { - return Math.max(27, 12 + value.length * 4); -} - -function GitHubStarBadge({label, labelWidth, stars}) { - const badgeId = useId().replace(/:/gu, ""); - const gradientId = `footer-badge-gradient-${badgeId}`; - const safeStars = Number.isFinite(stars) ? stars : 0; - const formattedStars = formatStars(safeStars); - const countWidth = getCountWidth(formattedStars); - const badgeWidth = labelWidth + countWidth + 7; - const labelCenterX = labelWidth / 2 + 8.5; - const countCenterX = labelWidth + 6 + countWidth / 2; - - return ( - - ); -} - -function XFollowBadge() { - const badgeId = useId().replace(/:/gu, ""); - const gradientId = `footer-badge-x-gradient-${badgeId}`; - - return ( - - ); -} - function BadgeLink({href, ariaLabel, children}) { return (