+
+
+
+ "
+`;
+
+exports[`Test Render Wakatime Card should render correctly with compact layout when langs_count is set 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
+ Wakatime Stats
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/renderWakatimeCard.test.js b/tests/renderWakatimeCard.test.js
index 098e9f7ee6193..67969bef50063 100644
--- a/tests/renderWakatimeCard.test.js
+++ b/tests/renderWakatimeCard.test.js
@@ -16,6 +16,15 @@ describe("Test Render Wakatime Card", () => {
expect(card).toMatchSnapshot();
});
+ it("should render correctly with compact layout when langs_count is set", () => {
+ const card = renderWakatimeCard(wakaTimeData.data, {
+ layout: "compact",
+ langs_count: 2,
+ });
+
+ expect(card).toMatchSnapshot();
+ });
+
it("should hide languages when hide is passed", () => {
document.body.innerHTML = renderWakatimeCard(wakaTimeData.data, {
hide: ["YAML", "Other"],
From f9e95b166dd347104047392316409015be6a2201 Mon Sep 17 00:00:00 2001
From: Tymoteusz Marzec <59064153+InfoTCube@users.noreply.github.com>
Date: Sat, 29 Oct 2022 15:41:04 +0200
Subject: [PATCH 111/905] Corrections of Polish expressions in translations.js
(#2240)
---
src/translations.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/translations.js b/src/translations.js
index 904da37d8f1ba..65fc231f59b4e 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -67,7 +67,7 @@ const statCardLocales = ({ name, apostrophe }) => {
my: "Jumlah Bintang",
sk: "Hviezdy",
tr: "Toplam Yıldız",
- pl: "Liczba Gwiazdek dostanych",
+ pl: "Liczba otrzymanych gwiazdek",
uz: "Yulduzchalar",
vi: "Tổng Số Sao",
se: "Antal intjänade stjärnor",
@@ -160,7 +160,7 @@ const statCardLocales = ({ name, apostrophe }) => {
my: "Jumlah Isu Dilaporkan",
sk: "Všetky problémy",
tr: "Toplam Hata",
- pl: "Wszystkie Issues",
+ pl: "Wszystkie problemy",
uz: "'Issue'lar",
vi: "Tổng Số Vấn Đề",
se: "Total antal issues",
@@ -322,7 +322,7 @@ const wakatimeCardLocales = {
my: "Statistik Wakatime",
sk: "Wakatime štatistika",
tr: "Waketime İstatistikler",
- pl: "statystyki Wakatime",
+ pl: "Statystyki Wakatime",
vi: "Thống Kê Wakatime",
se: "Wakatime statistik",
},
From 56aa307094923c02be37fa52e797c705bf72041d Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Fri, 18 Nov 2022 11:05:10 +0100
Subject: [PATCH 112/905] ci: update theme stale close message
---
scripts/close-stale-theme-prs.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/close-stale-theme-prs.js b/scripts/close-stale-theme-prs.js
index def7ef4548310..484351c123c3a 100644
--- a/scripts/close-stale-theme-prs.js
+++ b/scripts/close-stale-theme-prs.js
@@ -10,7 +10,7 @@ import { RequestError } from "@octokit/request-error";
import { getGithubToken, getRepoInfo } from "./helpers.js";
const CLOSING_COMMENT = `
- \rThis PR has been automatically closed due to inactivity. Please feel free to reopen it if you need to continue working on it.\
+ \rThis theme PR has been automatically closed due to inactivity. Please reopen it if you need to continue working on it.\
\rThank you for your contributions.
`;
const REVIEWER = "github-actions[bot]";
From 1a4e5a69551c249a2eeaeb31f066718b2b104b82 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Fri, 18 Nov 2022 11:06:24 +0100
Subject: [PATCH 113/905] ci: update theme stale close message
---
scripts/close-stale-theme-prs.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/close-stale-theme-prs.js b/scripts/close-stale-theme-prs.js
index 484351c123c3a..7db66f9775adb 100644
--- a/scripts/close-stale-theme-prs.js
+++ b/scripts/close-stale-theme-prs.js
@@ -10,7 +10,7 @@ import { RequestError } from "@octokit/request-error";
import { getGithubToken, getRepoInfo } from "./helpers.js";
const CLOSING_COMMENT = `
- \rThis theme PR has been automatically closed due to inactivity. Please reopen it if you need to continue working on it.\
+ \rThis theme PR has been automatically closed due to inactivity. Please reopen it if you want to continue working on it.\
\rThank you for your contributions.
`;
const REVIEWER = "github-actions[bot]";
From 26cde6bfe9461096aa63f8475a5c7c73382e7d15 Mon Sep 17 00:00:00 2001
From: Fabian Joswig
Date: Fri, 18 Nov 2022 14:19:04 +0000
Subject: [PATCH 114/905] Missing term in calculation of TOTAL_VALUES. (#2116)
* fix: added missing term in calculation of TOTAL_VALUES.
* fix: fix rank test
* refactor: update code formatting
* refactor: update code formatting
Co-authored-by: rickstaa
---
src/calculateRank.js | 6 +++++-
tests/calculateRank.test.js | 2 +-
tests/e2e/e2e.test.js | 2 +-
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/calculateRank.js b/src/calculateRank.js
index 85d965802b5e9..23d61dba35ddb 100644
--- a/src/calculateRank.js
+++ b/src/calculateRank.js
@@ -70,7 +70,11 @@ function calculateRank({
const RANK_B_VALUE = 100;
const TOTAL_VALUES =
- RANK_S_VALUE + RANK_A2_VALUE + RANK_A3_VALUE + RANK_B_VALUE;
+ RANK_S_VALUE +
+ RANK_DOUBLE_A_VALUE +
+ RANK_A2_VALUE +
+ RANK_A3_VALUE +
+ RANK_B_VALUE;
// prettier-ignore
const score = (
diff --git a/tests/calculateRank.test.js b/tests/calculateRank.test.js
index 5cc19a02aa73b..235b1b5f20b04 100644
--- a/tests/calculateRank.test.js
+++ b/tests/calculateRank.test.js
@@ -13,6 +13,6 @@ describe("Test calculateRank", () => {
prs: 300,
issues: 200,
}),
- ).toStrictEqual({ level: "A+", score: 49.16605417270399 });
+ ).toStrictEqual({ level: "A+", score: 49.25629684876535 });
});
});
diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js
index 0a38d98002b49..48bf16a0e083a 100644
--- a/tests/e2e/e2e.test.js
+++ b/tests/e2e/e2e.test.js
@@ -22,7 +22,7 @@ const STATS_DATA = {
contributedTo: 2,
rank: {
level: "A+",
- score: 51.01013099671447,
+ score: 50.900829325065935,
},
};
From 0c829e94885dd869720e1b4e4f428ffcbb58fcf2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8Dtalo=20Sousa?=
Date: Fri, 18 Nov 2022 11:49:38 -0300
Subject: [PATCH 115/905] Updates the brazilian readme (#2245)
---
docs/readme_pt-BR.md | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/docs/readme_pt-BR.md b/docs/readme_pt-BR.md
index 7f4814cec669b..62c23dc55c7e2 100644
--- a/docs/readme_pt-BR.md
+++ b/docs/readme_pt-BR.md
@@ -53,6 +53,8 @@
Nederlands
.
नेपाली
+ .
+ Türkçe
Gostou do projeto? Por favor considere fazer uma doação para ajudar a melhorá-lo!
@@ -142,7 +144,7 @@ Personalize a aparência do seu `Stats Card` ou `Repo Card` da maneira que desej
- `cache_seconds` - Defina o cabeçalho do cache manualmente _(min: 1800, max: 86400)_
- `locale` - defina o idioma no cartão _(por exemplo. cn, de, es, etc.)_
-> Nota sobre o cache: Cartões de repositório tem um cache padrão de 30 minutos (1800 segundos), se o número a contagem de forks e contagem de estrelas é menor que 1 mil o padrão é 2 horas (7200). Note também que o cache é limitado a um mínimo de 30 minutos e um máximo de 24 horas.
+> Nota sobre o cache: Cartões de repositório tem um cache padrão de 30 minutos (1800 segundos), se o número a contagem de forks e contagem de estrelas é menor que 1 mil o padrão é 2 horas (7200 segundos). Note também que o cache é limitado a um mínimo de 30 minutos e um máximo de 24 horas.
#### Opções exclusivas do cartão de estatísticas:
@@ -167,7 +169,7 @@ Personalize a aparência do seu `Stats Card` ou `Repo Card` da maneira que desej
> :warning: **Importante:**
> Nomes de linguagens devem ser uma sequência escapada de URI, como específicado em [Codificação por cento](https://pt.wikipedia.org/wiki/Codificação_por_cento)
-> (Isso é: `c++` deve se tornar `c%2B%2B`, `jupyter notebook` deve se tornar `jupyter%20notebook`, etc.)
+> (Ou seja: `c++` deve se tornar `c%2B%2B`, `jupyter notebook` deve se tornar `jupyter%20notebook`, etc.)
---
From 9aa39dfe81649eef84e8b750be86993e35c93a2b Mon Sep 17 00:00:00 2001
From: Pranav Joglekar
Date: Sun, 20 Nov 2022 00:48:42 +0530
Subject: [PATCH 116/905] feat: allow users to pass ring_color param (#2075)
* fix: prevent crash if undefined color is passed to func fallbackColor
* feat: allow users to pass ring_color param
Before this commit, the ring color was always equal to the title color.
This commit allows the user to pass a ring_color property to allow him
to style the ring color the way he pleases to. If no ring_color is
passed we default to the title color.
* docs: improves ring color documentation
* fix: improve code style
Co-authored-by: rickstaa
---
api/index.js | 2 ++
readme.md | 1 +
src/cards/stats-card.js | 7 ++--
src/common/utils.js | 12 +++++--
src/getStyles.js | 5 +--
.../renderWakatimeCard.test.js.snap | 4 +--
tests/api.test.js | 35 +++++++++++++++++++
tests/renderStatsCard.test.js | 33 +++++++++++++++++
tests/utils.test.js | 23 ++++++++++++
9 files changed, 114 insertions(+), 8 deletions(-)
diff --git a/api/index.js b/api/index.js
index 34824ba658a1f..88bd3c2e3e7ea 100644
--- a/api/index.js
+++ b/api/index.js
@@ -26,6 +26,7 @@ export default async (req, res) => {
include_all_commits,
line_height,
title_color,
+ ring_color,
icon_color,
text_color,
text_bold,
@@ -76,6 +77,7 @@ export default async (req, res) => {
include_all_commits: parseBoolean(include_all_commits),
line_height,
title_color,
+ ring_color,
icon_color,
text_color,
text_bold: parseBoolean(text_bold),
diff --git a/readme.md b/readme.md
index e18efc80f73b9..bfe042fcc2032 100644
--- a/readme.md
+++ b/readme.md
@@ -286,6 +286,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `custom_title` - Sets a custom title for the card. Default: ` GitHub Stats`.
- `text_bold` - Use bold text _(boolean)_. Default: `true`.
- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
+- `ring_color` - Color of the rank circle _(hex color)_. Defaults to the theme ring color if it exists and otherwise the title color.
> **Note**
> When hide_rank=`true`, the minimum card width is 270 px + the title length and padding.
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index 782ff069674bb..b078728ea54c3 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -89,6 +89,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
include_all_commits = false,
line_height = 25,
title_color,
+ ring_color,
icon_color,
text_color,
text_bold = true,
@@ -104,13 +105,14 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
const lheight = parseInt(String(line_height), 10);
// returns theme based colors with proper overrides and defaults
- const { titleColor, textColor, iconColor, bgColor, borderColor } =
+ const { titleColor, iconColor, textColor, bgColor, borderColor, ringColor } =
getCardColors({
title_color,
- icon_color,
text_color,
+ icon_color,
bg_color,
border_color,
+ ring_color,
theme,
});
@@ -201,6 +203,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
const progress = 100 - rank.score;
const cssStyles = getStyles({
titleColor,
+ ringColor,
textColor,
iconColor,
show_icons,
diff --git a/src/common/utils.js b/src/common/utils.js
index 43c7587fc2932..a0fbf3dabade7 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -133,9 +133,9 @@ function isValidGradient(colors) {
* @returns {string | string[]} The gradient or color.
*/
function fallbackColor(color, fallbackColor) {
- let colors = color.split(",");
let gradient = null;
+ let colors = color ? color.split(",") : [];
if (colors.length > 1 && isValidGradient(colors)) {
gradient = colors;
}
@@ -207,6 +207,7 @@ function getCardColors({
icon_color,
bg_color,
border_color,
+ ring_color,
theme,
fallbackTheme = "default",
}) {
@@ -221,6 +222,13 @@ function getCardColors({
title_color || selectedTheme.title_color,
"#" + defaultTheme.title_color,
);
+
+ // get the color provided by the user else the theme color
+ // finally if both colors are invalid we use the titleColor
+ const ringColor = fallbackColor(
+ ring_color || selectedTheme.ring_color,
+ titleColor,
+ );
const iconColor = fallbackColor(
icon_color || selectedTheme.icon_color,
"#" + defaultTheme.icon_color,
@@ -239,7 +247,7 @@ function getCardColors({
"#" + defaultBorderColor,
);
- return { titleColor, iconColor, textColor, bgColor, borderColor };
+ return { titleColor, iconColor, textColor, bgColor, borderColor, ringColor };
}
/**
diff --git a/src/getStyles.js b/src/getStyles.js
index 79692e8579035..f7b90f4adc7b4 100644
--- a/src/getStyles.js
+++ b/src/getStyles.js
@@ -77,6 +77,7 @@ const getStyles = ({
titleColor,
textColor,
iconColor,
+ ringColor,
show_icons,
progress,
}) => {
@@ -105,13 +106,13 @@ const getStyles = ({
}
.rank-circle-rim {
- stroke: ${titleColor};
+ stroke: ${ringColor};
fill: none;
stroke-width: 6;
opacity: 0.2;
}
.rank-circle {
- stroke: ${titleColor};
+ stroke: ${ringColor};
stroke-dasharray: 250;
fill: none;
stroke-width: 6;
diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap
index 416ead953e459..cc6129272f51e 100644
--- a/tests/__snapshots__/renderWakatimeCard.test.js.snap
+++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap
@@ -51,13 +51,13 @@ exports[`Test Render Wakatime Card should render correctly with compact layout 1
}
.rank-circle-rim {
- stroke: #2f80ed;
+ stroke: undefined;
fill: none;
stroke-width: 6;
opacity: 0.2;
}
.rank-circle {
- stroke: #2f80ed;
+ stroke: undefined;
stroke-dasharray: 250;
fill: none;
stroke-width: 6;
diff --git a/tests/api.test.js b/tests/api.test.js
index f77a7175b43d7..e1830858be063 100644
--- a/tests/api.test.js
+++ b/tests/api.test.js
@@ -248,4 +248,39 @@ describe("Test /api/", () => {
),
);
});
+
+ it("should allow changing ring_color", async () => {
+ const { req, res } = faker(
+ {
+ username: "anuraghazra",
+ hide: "issues,prs,contribs",
+ show_icons: true,
+ hide_border: true,
+ line_height: 100,
+ title_color: "fff",
+ ring_color: "0000ff",
+ icon_color: "fff",
+ text_color: "fff",
+ bg_color: "fff",
+ },
+ data,
+ );
+
+ await api(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "image/svg+xml");
+ expect(res.send).toBeCalledWith(
+ renderStatsCard(stats, {
+ hide: ["issues", "prs", "contribs"],
+ show_icons: true,
+ hide_border: true,
+ line_height: 100,
+ title_color: "fff",
+ ring_color: "0000ff",
+ icon_color: "fff",
+ text_color: "fff",
+ bg_color: "fff",
+ }),
+ );
+ });
});
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 69708137b334c..288048670f20b 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -239,6 +239,39 @@ describe("Test renderStatsCard", () => {
);
});
+ it("should render custom ring_color properly", () => {
+ const customColors = {
+ title_color: "5a0",
+ ring_color: "0000ff",
+ icon_color: "1b998b",
+ text_color: "9991",
+ bg_color: "252525",
+ };
+
+ document.body.innerHTML = renderStatsCard(stats, { ...customColors });
+
+ const styleTag = document.querySelector("style");
+ const stylesObject = cssToObject(styleTag.innerHTML);
+
+ const headerClassStyles = stylesObject[":host"][".header "];
+ const statClassStyles = stylesObject[":host"][".stat "];
+ const iconClassStyles = stylesObject[":host"][".icon "];
+ const rankCircleStyles = stylesObject[":host"][".rank-circle "];
+ const rankCircleRimStyles = stylesObject[":host"][".rank-circle-rim "];
+
+ expect(headerClassStyles.fill.trim()).toBe(`#${customColors.title_color}`);
+ expect(statClassStyles.fill.trim()).toBe(`#${customColors.text_color}`);
+ expect(iconClassStyles.fill.trim()).toBe(`#${customColors.icon_color}`);
+ expect(rankCircleStyles.stroke.trim()).toBe(`#${customColors.ring_color}`);
+ expect(rankCircleRimStyles.stroke.trim()).toBe(
+ `#${customColors.ring_color}`,
+ );
+ expect(queryByTestId(document.body, "card-bg")).toHaveAttribute(
+ "fill",
+ "#252525",
+ );
+ });
+
it("should render icons correctly", () => {
document.body.innerHTML = renderStatsCard(stats, {
show_icons: true,
diff --git a/tests/utils.test.js b/tests/utils.test.js
index b6e4a3be3f9f9..5f6231cceff2d 100644
--- a/tests/utils.test.js
+++ b/tests/utils.test.js
@@ -48,6 +48,7 @@ describe("Test utils.js", () => {
let colors = getCardColors({
title_color: "f00",
text_color: "0f0",
+ ring_color: "0000ff",
icon_color: "00f",
bg_color: "fff",
border_color: "fff",
@@ -57,6 +58,7 @@ describe("Test utils.js", () => {
titleColor: "#f00",
textColor: "#0f0",
iconColor: "#00f",
+ ringColor: "#0000ff",
bgColor: "#fff",
borderColor: "#fff",
});
@@ -75,6 +77,7 @@ describe("Test utils.js", () => {
titleColor: "#2f80ed",
textColor: "#0f0",
iconColor: "#00f",
+ ringColor: "#2f80ed",
bgColor: "#fff",
borderColor: "#e4e2e2",
});
@@ -87,11 +90,31 @@ describe("Test utils.js", () => {
expect(colors).toStrictEqual({
titleColor: "#fff",
textColor: "#9f9f9f",
+ ringColor: "#fff",
iconColor: "#79ff97",
bgColor: "#151515",
borderColor: "#e4e2e2",
});
});
+
+ it("getCardColors: should return ring color equal to title color if not ring color is defined", () => {
+ let colors = getCardColors({
+ title_color: "f00",
+ text_color: "0f0",
+ icon_color: "00f",
+ bg_color: "fff",
+ border_color: "fff",
+ theme: "dark",
+ });
+ expect(colors).toStrictEqual({
+ titleColor: "#f00",
+ textColor: "#0f0",
+ iconColor: "#00f",
+ ringColor: "#f00",
+ bgColor: "#fff",
+ borderColor: "#fff",
+ });
+ });
});
describe("wrapTextMultiline", () => {
From 0e02523459a527007f196cd1a35297d850d08839 Mon Sep 17 00:00:00 2001
From: Bradley Jester <109996512+jesterb0206@users.noreply.github.com>
Date: Sat, 19 Nov 2022 13:44:42 -0800
Subject: [PATCH 117/905] feat: added Date Night theme to index.js (#2264)
* Added Date Night theme to index.js
* My theme name should be in snake_case now
---
themes/index.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/themes/index.js b/themes/index.js
index 4279317b3edc3..a5d3abae8cb6f 100644
--- a/themes/index.js
+++ b/themes/index.js
@@ -367,6 +367,13 @@ export const themes = {
text_color: "e0def4",
bg_color: "191724",
},
+ date_night: {
+ title_color: "DA7885",
+ text_color: "E1B2A2",
+ icon_color: "BB8470",
+ border_color: "170F0C",
+ bg_color: "170F0C",
+ },
};
export default themes;
From b2e34ac8db9dd28f009ac1f7f657da8b7f21800c Mon Sep 17 00:00:00 2001
From: rickstaa
Date: Sun, 20 Nov 2022 08:39:44 +0100
Subject: [PATCH 118/905] test: update snapshots
---
tests/__snapshots__/renderWakatimeCard.test.js.snap | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap
index cc6129272f51e..1c0bd701fbbfe 100644
--- a/tests/__snapshots__/renderWakatimeCard.test.js.snap
+++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap
@@ -209,13 +209,13 @@ exports[`Test Render Wakatime Card should render correctly with compact layout w
}
.rank-circle-rim {
- stroke: #2f80ed;
+ stroke: undefined;
fill: none;
stroke-width: 6;
opacity: 0.2;
}
.rank-circle {
- stroke: #2f80ed;
+ stroke: undefined;
stroke-dasharray: 250;
fill: none;
stroke-width: 6;
From 4b656ebabb8cb866d08bd010df29845372027018 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 21 Nov 2022 10:07:09 +0100
Subject: [PATCH 119/905] refactor: migrate to using arrow functions (#2033)
---
src/calculateRank.js | 10 ++---
src/common/utils.js | 62 +++++++++++++--------------
src/fetchers/repo-fetcher.js | 4 +-
src/fetchers/stats-fetcher.js | 6 +--
src/fetchers/top-languages-fetcher.js | 4 +-
src/translations.js | 4 +-
6 files changed, 45 insertions(+), 45 deletions(-)
diff --git a/src/calculateRank.js b/src/calculateRank.js
index 23d61dba35ddb..24845bc7d9944 100644
--- a/src/calculateRank.js
+++ b/src/calculateRank.js
@@ -9,7 +9,7 @@
* @param {number} to The value to calculate the probability for.
* @returns {number} Probability.
*/
-function normalcdf(mean, sigma, to) {
+const normalcdf = (mean, sigma, to) => {
var z = (to - mean) / Math.sqrt(2 * sigma * sigma);
var t = 1 / (1 + 0.3275911 * Math.abs(z));
var a1 = 0.254829592;
@@ -24,7 +24,7 @@ function normalcdf(mean, sigma, to) {
sign = -1;
}
return (1 / 2) * (1 + sign * erf);
-}
+};
/**
* Calculates the users rank.
@@ -38,7 +38,7 @@ function normalcdf(mean, sigma, to) {
* @param {number} stargazers The number of stars.
* @returns {{level: string, score: number}}} The users rank.
*/
-function calculateRank({
+const calculateRank = ({
totalRepos,
totalCommits,
contributions,
@@ -46,7 +46,7 @@ function calculateRank({
prs,
issues,
stargazers,
-}) {
+}) => {
const COMMITS_OFFSET = 1.65;
const CONTRIBS_OFFSET = 1.65;
const ISSUES_OFFSET = 1;
@@ -98,7 +98,7 @@ function calculateRank({
})();
return { level, score: normalizedScore };
-}
+};
export { calculateRank };
export default calculateRank;
diff --git a/src/common/utils.js b/src/common/utils.js
index a0fbf3dabade7..688219c8d8e18 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -42,13 +42,13 @@ const renderError = (message, secondaryMessage = "") => {
* @param {string} str String to encode.
* @returns {string} Encoded string.
*/
-function encodeHTML(str) {
+const encodeHTML = (str) => {
return str
.replace(/[\u00A0-\u9999<>&](?!#)/gim, (i) => {
return "" + i.charCodeAt(0) + ";";
})
.replace(/\u0008/gim, "");
-}
+};
/**
* Retrieves num with suffix k(thousands) precise to 1 decimal if greater than 999.
@@ -56,11 +56,11 @@ function encodeHTML(str) {
* @param {number} num The number to format.
* @returns {string|number} The formatted number.
*/
-function kFormatter(num) {
+const kFormatter = (num) => {
return Math.abs(num) > 999
? Math.sign(num) * parseFloat((Math.abs(num) / 1000).toFixed(1)) + "k"
: Math.sign(num) * Math.abs(num);
-}
+};
/**
* Checks if a string is a valid hex color.
@@ -68,11 +68,11 @@ function kFormatter(num) {
* @param {string} hexColor String to check.
* @returns {boolean} True if the given string is a valid hex color.
*/
-function isValidHexColor(hexColor) {
+const isValidHexColor = (hexColor) => {
return new RegExp(
/^([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{4})$/,
).test(hexColor);
-}
+};
/**
* Returns boolean if value is either "true" or "false" else the value as it is.
@@ -80,7 +80,7 @@ function isValidHexColor(hexColor) {
* @param {string} value The value to parse.
* @returns {boolean | string} The parsed value.
*/
-function parseBoolean(value) {
+const parseBoolean = (value) => {
if (value === "true") {
return true;
} else if (value === "false") {
@@ -88,7 +88,7 @@ function parseBoolean(value) {
} else {
return value;
}
-}
+};
/**
* Parse string to array of strings.
@@ -96,10 +96,10 @@ function parseBoolean(value) {
* @param {string} str The string to parse.
* @returns {string[]} The array of strings.
*/
-function parseArray(str) {
+const parseArray = (str) => {
if (!str) return [];
return str.split(",");
-}
+};
/**
* Clamp the given number between the given range.
@@ -109,11 +109,11 @@ function parseArray(str) {
* @param {number} max The maximum value.
* returns {number} The clamped number.
*/
-function clampValue(number, min, max) {
+const clampValue = (number, min, max) => {
// @ts-ignore
if (Number.isNaN(parseInt(number))) return min;
return Math.max(min, Math.min(number, max));
-}
+};
/**
* Check if the given string is a valid gradient.
@@ -121,9 +121,9 @@ function clampValue(number, min, max) {
* @param {string[]} colors Array of colors.
* @returns {boolean} True if the given string is a valid gradient.
*/
-function isValidGradient(colors) {
+const isValidGradient = (colors) => {
return isValidHexColor(colors[1]) && isValidHexColor(colors[2]);
-}
+};
/**
* Retrieves a gradient if color has more than one valid hex codes else a single color.
@@ -132,7 +132,7 @@ function isValidGradient(colors) {
* @param {string} fallbackColor The fallback color.
* @returns {string | string[]} The gradient or color.
*/
-function fallbackColor(color, fallbackColor) {
+const fallbackColor = (color, fallbackColor) => {
let gradient = null;
let colors = color ? color.split(",") : [];
@@ -144,7 +144,7 @@ function fallbackColor(color, fallbackColor) {
(gradient ? gradient : isValidHexColor(color) && `#${color}`) ||
fallbackColor
);
-}
+};
/**
* Send GraphQL request to GitHub API.
@@ -153,7 +153,7 @@ function fallbackColor(color, fallbackColor) {
* @param {import('axios').AxiosRequestConfig['headers']} headers Request headers.
* @returns {Promise} Request response.
*/
-function request(data, headers) {
+const request = (data, headers) => {
// @ts-ignore
return axios({
url: "https://api.github.com/graphql",
@@ -161,7 +161,7 @@ function request(data, headers) {
headers,
data,
});
-}
+};
/**
* Auto layout utility, allows us to layout things vertically or horizontally with
@@ -174,7 +174,7 @@ function request(data, headers) {
* @param {"column" | "row"?=} props.direction Direction to layout items.
* @returns {string[]} Array of items with proper layout.
*/
-function flexLayout({ items, gap, direction, sizes = [] }) {
+const flexLayout = ({ items, gap, direction, sizes = [] }) => {
let lastSize = 0;
// filter() for filtering out empty strings
return items.filter(Boolean).map((item, i) => {
@@ -186,7 +186,7 @@ function flexLayout({ items, gap, direction, sizes = [] }) {
lastSize += size + gap;
return `${item}`;
});
-}
+};
/**
* Returns theme based colors with proper overrides and defaults.
@@ -201,7 +201,7 @@ function flexLayout({ items, gap, direction, sizes = [] }) {
* @param {string} args.fallbackTheme Fallback theme.
*
*/
-function getCardColors({
+const getCardColors = ({
title_color,
text_color,
icon_color,
@@ -210,7 +210,7 @@ function getCardColors({
ring_color,
theme,
fallbackTheme = "default",
-}) {
+}) => {
const defaultTheme = themes[fallbackTheme];
const selectedTheme = themes[theme] || defaultTheme;
const defaultBorderColor =
@@ -248,7 +248,7 @@ function getCardColors({
);
return { titleColor, iconColor, textColor, bgColor, borderColor, ringColor };
-}
+};
/**
* Split text over multiple lines based on the card width.
@@ -258,7 +258,7 @@ function getCardColors({
* @param {number} maxLines Maximum number of lines.
* @returns {string[]} Array of lines.
*/
-function wrapTextMultiline(text, width = 59, maxLines = 3) {
+const wrapTextMultiline = (text, width = 59, maxLines = 3) => {
const fullWidthComma = ",";
const encoded = encodeHTML(text);
const isChinese = encoded.includes(fullWidthComma);
@@ -283,7 +283,7 @@ function wrapTextMultiline(text, width = 59, maxLines = 3) {
// Remove empty lines if text fits in less than maxLines lines
const multiLineText = lines.filter(Boolean);
return multiLineText;
-}
+};
const noop = () => {};
// return console instance based on the environment
@@ -349,7 +349,7 @@ class MissingParamError extends Error {
* @param {number} fontSize Font size.
* @returns {number} Text length.
*/
-function measureText(str, fontSize = 10) {
+const measureText = (str, fontSize = 10) => {
// prettier-ignore
const widths = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -381,7 +381,7 @@ function measureText(str, fontSize = 10) {
)
.reduce((cur, acc) => acc + cur) * fontSize
);
-}
+};
/** @param {string} name */
const lowercaseTrim = (name) => name.toLowerCase().trim();
@@ -394,7 +394,7 @@ const lowercaseTrim = (name) => name.toLowerCase().trim();
* @param {number} perChunk Number of languages per column.
* @returns {Array} Array of languages split in two columns.
*/
-function chunkArray(arr, perChunk) {
+const chunkArray = (arr, perChunk) => {
return arr.reduce((resultArray, item, index) => {
const chunkIndex = Math.floor(index / perChunk);
@@ -406,7 +406,7 @@ function chunkArray(arr, perChunk) {
return resultArray;
}, []);
-}
+};
/**
* Parse emoji from string.
@@ -414,12 +414,12 @@ function chunkArray(arr, perChunk) {
* @param {string} str String to parse emoji from.
* @returns {string} String with emoji parsed.
*/
-function parseEmojis(str) {
+const parseEmojis = (str) => {
if (!str) throw new Error("[parseEmoji]: str argument not provided");
return str.replace(/:\w+:/gm, (emoji) => {
return toEmoji.get(emoji) || "";
});
-}
+};
export {
ERROR_CARD_LENGTH,
diff --git a/src/fetchers/repo-fetcher.js b/src/fetchers/repo-fetcher.js
index 28dd89a7f3e4a..ff7a2be8164cc 100644
--- a/src/fetchers/repo-fetcher.js
+++ b/src/fetchers/repo-fetcher.js
@@ -60,7 +60,7 @@ const urlExample = "/api/pin?username=USERNAME&repo=REPO_NAME";
* @param {string} reponame GitHub repository name.
* @returns {Promise} Repository data.
*/
-async function fetchRepo(username, reponame) {
+const fetchRepo = async (username, reponame) => {
if (!username && !reponame) {
throw new MissingParamError(["username", "repo"], urlExample);
}
@@ -100,7 +100,7 @@ async function fetchRepo(username, reponame) {
starCount: data.organization.repository.stargazers.totalCount,
};
}
-}
+};
export { fetchRepo };
export default fetchRepo;
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index c236b5882b42f..9d17d009c0b70 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -188,12 +188,12 @@ const totalStarsFetcher = async (username, repoToHide) => {
* @param {boolean} include_all_commits Include all commits.
* @returns {Promise} Stats data.
*/
-async function fetchStats(
+const fetchStats = async (
username,
count_private = false,
include_all_commits = false,
exclude_repo = [],
-) {
+) => {
if (!username) throw new MissingParamError(["username"]);
const stats = {
@@ -275,7 +275,7 @@ async function fetchStats(
});
return stats;
-}
+};
export { fetchStats };
export default fetchStats;
diff --git a/src/fetchers/top-languages-fetcher.js b/src/fetchers/top-languages-fetcher.js
index 109fa06bd2207..5fa1c8040b170 100644
--- a/src/fetchers/top-languages-fetcher.js
+++ b/src/fetchers/top-languages-fetcher.js
@@ -57,7 +57,7 @@ const fetcher = (variables, token) => {
* @param {string[]} exclude_repo List of repositories to exclude.
* @returns {Promise} Top languages data.
*/
-async function fetchTopLanguages(username, exclude_repo = []) {
+const fetchTopLanguages = async (username, exclude_repo = []) => {
if (!username) throw new MissingParamError(["username"]);
const res = await retryer(fetcher, { login: username });
@@ -136,7 +136,7 @@ async function fetchTopLanguages(username, exclude_repo = []) {
}, {});
return topLangs;
-}
+};
export { fetchTopLanguages };
export default fetchTopLanguages;
diff --git a/src/translations.js b/src/translations.js
index 65fc231f59b4e..45c8295e024de 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -367,9 +367,9 @@ const availableLocales = Object.keys(repoCardLocales["repocard.archived"]);
* @param {string} locale The locale to check.
* @returns {boolean} Boolean specifying whether the locale is available or not.
*/
-function isLocaleAvailable(locale) {
+const isLocaleAvailable = (locale) => {
return availableLocales.includes(locale.toLowerCase());
-}
+};
export {
isLocaleAvailable,
From 5df25a64721847ae6086fd1fcae0b4724805f5a8 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 21 Nov 2022 10:10:46 +0100
Subject: [PATCH 120/905] fix: improve boolean parse behaviour (#2029)
---
src/common/utils.js | 19 +++++++++++--------
tests/utils.test.js | 18 ++++++++++++++++++
2 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/src/common/utils.js b/src/common/utils.js
index 688219c8d8e18..1215fc9ac8cc2 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -77,17 +77,20 @@ const isValidHexColor = (hexColor) => {
/**
* Returns boolean if value is either "true" or "false" else the value as it is.
*
- * @param {string} value The value to parse.
- * @returns {boolean | string} The parsed value.
+ * @param {string | boolean} value The value to parse.
+ * @returns {boolean | undefined } The parsed value.
*/
const parseBoolean = (value) => {
- if (value === "true") {
- return true;
- } else if (value === "false") {
- return false;
- } else {
- return value;
+ if (typeof value === "boolean") return value;
+
+ if (typeof value === "string") {
+ if (value.toLowerCase() === "true") {
+ return true;
+ } else if (value.toLowerCase() === "false") {
+ return false;
+ }
}
+ return undefined;
};
/**
diff --git a/tests/utils.test.js b/tests/utils.test.js
index 5f6231cceff2d..c91fe9d54ae5d 100644
--- a/tests/utils.test.js
+++ b/tests/utils.test.js
@@ -4,6 +4,7 @@ import {
encodeHTML,
getCardColors,
kFormatter,
+ parseBoolean,
renderError,
wrapTextMultiline,
} from "../src/common/utils.js";
@@ -19,6 +20,23 @@ describe("Test utils.js", () => {
expect(kFormatter(9900000)).toBe("9900k");
});
+ it("should test parseBoolean", () => {
+ expect(parseBoolean(true)).toBe(true);
+ expect(parseBoolean(false)).toBe(false);
+
+ expect(parseBoolean("true")).toBe(true);
+ expect(parseBoolean("false")).toBe(false);
+ expect(parseBoolean("True")).toBe(true);
+ expect(parseBoolean("False")).toBe(false);
+ expect(parseBoolean("TRUE")).toBe(true);
+ expect(parseBoolean("FALSE")).toBe(false);
+
+ expect(parseBoolean("1")).toBe(undefined);
+ expect(parseBoolean("0")).toBe(undefined);
+ expect(parseBoolean("")).toBe(undefined);
+ expect(parseBoolean(undefined)).toBe(undefined);
+ });
+
it("should test encodeHTML", () => {
expect(encodeHTML(`hello world<,.#4^&^@%!))`)).toBe(
"<html>hello world<,.#4^&^@%!))",
From 42a4b6f60a5d534c9de5434ebaa09f222ac40247 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 21 Nov 2022 10:13:14 +0100
Subject: [PATCH 121/905] refactor: remove unused dotenv calls (#2059)
As explained in the Vercel documentation vercel ignores dot files (see
https://github.com/vercel/vercel/discussions/3962#discussioncomment-4277). It
instead loads the env variables defined in the vercel instance. As a
result we can therefore remove dotenv.
---
api/index.js | 3 ---
api/top-langs.js | 3 ---
api/wakatime.js | 3 ---
src/fetchers/stats-fetcher.js | 3 ---
src/fetchers/top-languages-fetcher.js | 3 ---
5 files changed, 15 deletions(-)
diff --git a/api/index.js b/api/index.js
index 88bd3c2e3e7ea..8fbe2bc28e998 100644
--- a/api/index.js
+++ b/api/index.js
@@ -1,4 +1,3 @@
-import * as dotenv from "dotenv";
import { renderStatsCard } from "../src/cards/stats-card.js";
import { blacklist } from "../src/common/blacklist.js";
import {
@@ -11,8 +10,6 @@ import {
import { fetchStats } from "../src/fetchers/stats-fetcher.js";
import { isLocaleAvailable } from "../src/translations.js";
-dotenv.config();
-
export default async (req, res) => {
const {
username,
diff --git a/api/top-langs.js b/api/top-langs.js
index 25f97c8b455b2..1b6b980d77c4b 100644
--- a/api/top-langs.js
+++ b/api/top-langs.js
@@ -1,4 +1,3 @@
-import * as dotenv from "dotenv";
import { renderTopLanguages } from "../src/cards/top-languages-card.js";
import { blacklist } from "../src/common/blacklist.js";
import {
@@ -11,8 +10,6 @@ import {
import { fetchTopLanguages } from "../src/fetchers/top-languages-fetcher.js";
import { isLocaleAvailable } from "../src/translations.js";
-dotenv.config();
-
export default async (req, res) => {
const {
username,
diff --git a/api/wakatime.js b/api/wakatime.js
index fb8caa51c9477..7680b76e602f2 100644
--- a/api/wakatime.js
+++ b/api/wakatime.js
@@ -1,4 +1,3 @@
-import * as dotenv from "dotenv";
import { renderWakatimeCard } from "../src/cards/wakatime-card.js";
import {
clampValue,
@@ -10,8 +9,6 @@ import {
import { fetchWakatimeStats } from "../src/fetchers/wakatime-fetcher.js";
import { isLocaleAvailable } from "../src/translations.js";
-dotenv.config();
-
export default async (req, res) => {
const {
username,
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index 9d17d009c0b70..7f6cb9e5e95b4 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -1,6 +1,5 @@
// @ts-check
import axios from "axios";
-import * as dotenv from "dotenv";
import githubUsernameRegex from "github-username-regex";
import { calculateRank } from "../calculateRank.js";
import { retryer } from "../common/retryer.js";
@@ -12,8 +11,6 @@ import {
wrapTextMultiline,
} from "../common/utils.js";
-dotenv.config();
-
/**
* Stats fetcher object.
*
diff --git a/src/fetchers/top-languages-fetcher.js b/src/fetchers/top-languages-fetcher.js
index 5fa1c8040b170..86d794435be08 100644
--- a/src/fetchers/top-languages-fetcher.js
+++ b/src/fetchers/top-languages-fetcher.js
@@ -1,5 +1,4 @@
// @ts-check
-import * as dotenv from "dotenv";
import { retryer } from "../common/retryer.js";
import {
CustomError,
@@ -9,8 +8,6 @@ import {
wrapTextMultiline,
} from "../common/utils.js";
-dotenv.config();
-
/**
* Top languages fetcher object.
*
From f07cd133d3166688c5883f64c6491665f38bba78 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 21 Nov 2022 10:15:43 +0100
Subject: [PATCH 122/905] fix: fix retry max-out bug (#2121)
* fix: fix retry max-out bug
This commit makes sure that the retry function tests all PATs.
* style: format code
* test: fix retry tests
* style: format code
---
src/common/retryer.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/common/retryer.js b/src/common/retryer.js
index 77f69d3cbbbce..e54eedbec6dd5 100644
--- a/src/common/retryer.js
+++ b/src/common/retryer.js
@@ -1,5 +1,11 @@
import { CustomError, logger } from "./utils.js";
+// Script variables.
+const PATs = Object.keys(process.env).filter((key) =>
+ /PAT_\d*$/.exec(key),
+).length;
+const RETRIES = PATs ? PATs : 7;
+
/**
* Try to execute the fetcher function until it succeeds or the max number of retries is reached.
*
@@ -10,7 +16,7 @@ import { CustomError, logger } from "./utils.js";
* @returns Promise
*/
const retryer = async (fetcher, variables, retries = 0) => {
- if (retries > 7) {
+ if (retries > RETRIES) {
throw new CustomError("Maximum retries exceeded", CustomError.MAX_RETRY);
}
try {
From 3cb205c65b709688e48ee61ebeabbb3af1f72518 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 21 Nov 2022 10:21:46 +0100
Subject: [PATCH 123/905] feat: improve card loading speed (#2124)
* feat: improve card loading times
This commit adds the `stale-while-revalidate` option to speed up the
card loading times.
* mend
---
api/index.js | 7 ++++++-
api/pin.js | 7 ++++++-
api/top-langs.js | 7 ++++++-
api/wakatime.js | 7 ++++++-
tests/api.test.js | 35 ++++++++++++++++++++++++++++++-----
5 files changed, 54 insertions(+), 9 deletions(-)
diff --git a/api/index.js b/api/index.js
index 8fbe2bc28e998..b449d43b49080 100644
--- a/api/index.js
+++ b/api/index.js
@@ -61,7 +61,12 @@ export default async (req, res) => {
CONSTANTS.ONE_DAY,
);
- res.setHeader("Cache-Control", `public, max-age=${cacheSeconds}`);
+ res.setHeader(
+ "Cache-Control",
+ `max-age=${
+ cacheSeconds / 2
+ }, s-maxage=${cacheSeconds}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
+ );
return res.send(
renderStatsCard(stats, {
diff --git a/api/pin.js b/api/pin.js
index ef149948d0ef6..4838b0f02fece 100644
--- a/api/pin.js
+++ b/api/pin.js
@@ -58,7 +58,12 @@ export default async (req, res) => {
cacheSeconds = CONSTANTS.FOUR_HOURS;
}
- res.setHeader("Cache-Control", `public, max-age=${cacheSeconds}`);
+ res.setHeader(
+ "Cache-Control",
+ `max-age=${
+ cacheSeconds / 2
+ }, s-maxage=${cacheSeconds}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
+ );
return res.send(
renderRepoCard(repoData, {
diff --git a/api/top-langs.js b/api/top-langs.js
index 1b6b980d77c4b..d183d3b455ca0 100644
--- a/api/top-langs.js
+++ b/api/top-langs.js
@@ -52,7 +52,12 @@ export default async (req, res) => {
CONSTANTS.ONE_DAY,
);
- res.setHeader("Cache-Control", `public, max-age=${cacheSeconds}`);
+ res.setHeader(
+ "Cache-Control",
+ `max-age=${
+ cacheSeconds / 2
+ }, s-maxage=${cacheSeconds}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
+ );
return res.send(
renderTopLanguages(topLangs, {
diff --git a/api/wakatime.js b/api/wakatime.js
index 7680b76e602f2..d439c5b7ac8c6 100644
--- a/api/wakatime.js
+++ b/api/wakatime.js
@@ -52,7 +52,12 @@ export default async (req, res) => {
cacheSeconds = CONSTANTS.FOUR_HOURS;
}
- res.setHeader("Cache-Control", `public, max-age=${cacheSeconds}`);
+ res.setHeader(
+ "Cache-Control",
+ `max-age=${
+ cacheSeconds / 2
+ }, s-maxage=${cacheSeconds}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
+ );
return res.send(
renderWakatimeCard(stats, {
diff --git a/tests/api.test.js b/tests/api.test.js
index e1830858be063..0037bcdb566b2 100644
--- a/tests/api.test.js
+++ b/tests/api.test.js
@@ -160,7 +160,12 @@ describe("Test /api/", () => {
expect(res.setHeader.mock.calls).toEqual([
["Content-Type", "image/svg+xml"],
- ["Cache-Control", `public, max-age=${CONSTANTS.FOUR_HOURS}`],
+ [
+ "Cache-Control",
+ `max-age=${CONSTANTS.FOUR_HOURS / 2}, s-maxage=${
+ CONSTANTS.FOUR_HOURS
+ }, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
+ ],
]);
});
@@ -170,7 +175,12 @@ describe("Test /api/", () => {
expect(res.setHeader.mock.calls).toEqual([
["Content-Type", "image/svg+xml"],
- ["Cache-Control", `public, max-age=${15000}`],
+ [
+ "Cache-Control",
+ `max-age=7500, s-maxage=${15000}, stale-while-revalidate=${
+ CONSTANTS.ONE_DAY
+ }`,
+ ],
]);
});
@@ -191,7 +201,12 @@ describe("Test /api/", () => {
expect(res.setHeader.mock.calls).toEqual([
["Content-Type", "image/svg+xml"],
- ["Cache-Control", `public, max-age=${CONSTANTS.ONE_DAY}`],
+ [
+ "Cache-Control",
+ `max-age=${CONSTANTS.ONE_DAY / 2}, s-maxage=${
+ CONSTANTS.ONE_DAY
+ }, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
+ ],
]);
}
@@ -202,7 +217,12 @@ describe("Test /api/", () => {
expect(res.setHeader.mock.calls).toEqual([
["Content-Type", "image/svg+xml"],
- ["Cache-Control", `public, max-age=${CONSTANTS.FOUR_HOURS}`],
+ [
+ "Cache-Control",
+ `max-age=${CONSTANTS.FOUR_HOURS / 2}, s-maxage=${
+ CONSTANTS.FOUR_HOURS
+ }, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
+ ],
]);
}
@@ -212,7 +232,12 @@ describe("Test /api/", () => {
expect(res.setHeader.mock.calls).toEqual([
["Content-Type", "image/svg+xml"],
- ["Cache-Control", `public, max-age=${CONSTANTS.FOUR_HOURS}`],
+ [
+ "Cache-Control",
+ `max-age=${CONSTANTS.FOUR_HOURS / 2}, s-maxage=${
+ CONSTANTS.FOUR_HOURS
+ }, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
+ ],
]);
}
});
From ada9cf4e0eeec24579ec12ee709fa7afd402fcf8 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 21 Nov 2022 11:08:05 +0100
Subject: [PATCH 124/905] feat: add INCLUDE_ORGS env variable (#2275)
This commit adds an INCLUDE_ORGS ENV variable that can be used to include results from
organizations into the GRS cards for self-deployed Vercel instances.
**Warning**
This is a hidden feature since we can not officially support this on the Public
Vercel instance due to GraphQL and Vercel rate/timeout limits. You can set this env
variable via Vercel's ENV variable menu (see
https://vercel.com/docs/concepts/projects/environment-variables).
---
src/common/utils.js | 2 +-
src/fetchers/stats-fetcher.js | 25 +++++++++++++++++++------
src/fetchers/top-languages-fetcher.js | 12 +++++++++---
3 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/src/common/utils.js b/src/common/utils.js
index 1215fc9ac8cc2..147f5408f81f3 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -77,7 +77,7 @@ const isValidHexColor = (hexColor) => {
/**
* Returns boolean if value is either "true" or "false" else the value as it is.
*
- * @param {string | boolean} value The value to parse.
+ * @param {string | boolean| undefined} value The value to parse.
* @returns {boolean | undefined } The parsed value.
*/
const parseBoolean = (value) => {
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index 7f6cb9e5e95b4..a8ed082c57102 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -7,6 +7,7 @@ import {
CustomError,
logger,
MissingParamError,
+ parseBoolean,
request,
wrapTextMultiline,
} from "../common/utils.js";
@@ -22,7 +23,7 @@ const fetcher = (variables, token) => {
return request(
{
query: `
- query userInfo($login: String!) {
+ query userInfo($login: String!, $ownerAffiliations: [RepositoryAffiliation]) {
user(login: $login) {
name
login
@@ -45,7 +46,7 @@ const fetcher = (variables, token) => {
followers {
totalCount
}
- repositories(ownerAffiliations: OWNER) {
+ repositories(ownerAffiliations: $ownerAffiliations) {
totalCount
}
}
@@ -70,9 +71,9 @@ const repositoriesFetcher = (variables, token) => {
return request(
{
query: `
- query userInfo($login: String!, $after: String) {
+ query userInfo($login: String!, $after: String, $ownerAffiliations: [RepositoryAffiliation]) {
user(login: $login) {
- repositories(first: 100, ownerAffiliations: OWNER, orderBy: {direction: DESC, field: STARGAZERS}, after: $after) {
+ repositories(first: 100, ownerAffiliations: $ownerAffiliations, orderBy: {direction: DESC, field: STARGAZERS}, after: $after) {
nodes {
name
stargazers {
@@ -149,7 +150,14 @@ const totalStarsFetcher = async (username, repoToHide) => {
let hasNextPage = true;
let endCursor = null;
while (hasNextPage) {
- const variables = { login: username, first: 100, after: endCursor };
+ const variables = {
+ login: username,
+ first: 100,
+ after: endCursor,
+ ownerAffiliations: parseBoolean(process.env.INCLUDE_ORGS)
+ ? ["OWNER", "COLLABORATOR"]
+ : ["OWNER"],
+ };
let res = await retryer(repositoriesFetcher, variables);
if (res.data.errors) {
@@ -203,7 +211,12 @@ const fetchStats = async (
rank: { level: "C", score: 0 },
};
- let res = await retryer(fetcher, { login: username });
+ let res = await retryer(fetcher, {
+ login: username,
+ ownerAffiliations: parseBoolean(process.env.INCLUDE_ORGS)
+ ? ["OWNER", "COLLABORATOR"]
+ : ["OWNER"],
+ });
// Catch GraphQL errors.
if (res.data.errors) {
diff --git a/src/fetchers/top-languages-fetcher.js b/src/fetchers/top-languages-fetcher.js
index 86d794435be08..cf8c3d16610ab 100644
--- a/src/fetchers/top-languages-fetcher.js
+++ b/src/fetchers/top-languages-fetcher.js
@@ -4,6 +4,7 @@ import {
CustomError,
logger,
MissingParamError,
+ parseBoolean,
request,
wrapTextMultiline,
} from "../common/utils.js";
@@ -19,10 +20,10 @@ const fetcher = (variables, token) => {
return request(
{
query: `
- query userInfo($login: String!) {
+ query userInfo($login: String!, $ownerAffiliations: [RepositoryAffiliation]) {
user(login: $login) {
# fetch only owner repos & not forks
- repositories(ownerAffiliations: OWNER, isFork: false, first: 100) {
+ repositories(ownerAffiliations: $ownerAffiliations, isFork: false, first: 100) {
nodes {
name
languages(first: 10, orderBy: {field: SIZE, direction: DESC}) {
@@ -57,7 +58,12 @@ const fetcher = (variables, token) => {
const fetchTopLanguages = async (username, exclude_repo = []) => {
if (!username) throw new MissingParamError(["username"]);
- const res = await retryer(fetcher, { login: username });
+ const res = await retryer(fetcher, {
+ login: username,
+ ownerAffiliations: parseBoolean(process.env.INCLUDE_ORGS)
+ ? ["OWNER", "COLLABORATOR"]
+ : ["OWNER"],
+ });
if (res.data.errors) {
logger.error(res.data.errors);
From 0efb982c2aa0c65eabfb8d774fa546a1685c0f28 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 21 Nov 2022 11:15:32 +0100
Subject: [PATCH 125/905] Revert "feat: add INCLUDE_ORGS env variable (#2275)"
(#2276)
This reverts commit ada9cf4e0eeec24579ec12ee709fa7afd402fcf8.
---
src/common/utils.js | 2 +-
src/fetchers/stats-fetcher.js | 25 ++++++-------------------
src/fetchers/top-languages-fetcher.js | 12 +++---------
3 files changed, 10 insertions(+), 29 deletions(-)
diff --git a/src/common/utils.js b/src/common/utils.js
index 147f5408f81f3..1215fc9ac8cc2 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -77,7 +77,7 @@ const isValidHexColor = (hexColor) => {
/**
* Returns boolean if value is either "true" or "false" else the value as it is.
*
- * @param {string | boolean| undefined} value The value to parse.
+ * @param {string | boolean} value The value to parse.
* @returns {boolean | undefined } The parsed value.
*/
const parseBoolean = (value) => {
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index a8ed082c57102..7f6cb9e5e95b4 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -7,7 +7,6 @@ import {
CustomError,
logger,
MissingParamError,
- parseBoolean,
request,
wrapTextMultiline,
} from "../common/utils.js";
@@ -23,7 +22,7 @@ const fetcher = (variables, token) => {
return request(
{
query: `
- query userInfo($login: String!, $ownerAffiliations: [RepositoryAffiliation]) {
+ query userInfo($login: String!) {
user(login: $login) {
name
login
@@ -46,7 +45,7 @@ const fetcher = (variables, token) => {
followers {
totalCount
}
- repositories(ownerAffiliations: $ownerAffiliations) {
+ repositories(ownerAffiliations: OWNER) {
totalCount
}
}
@@ -71,9 +70,9 @@ const repositoriesFetcher = (variables, token) => {
return request(
{
query: `
- query userInfo($login: String!, $after: String, $ownerAffiliations: [RepositoryAffiliation]) {
+ query userInfo($login: String!, $after: String) {
user(login: $login) {
- repositories(first: 100, ownerAffiliations: $ownerAffiliations, orderBy: {direction: DESC, field: STARGAZERS}, after: $after) {
+ repositories(first: 100, ownerAffiliations: OWNER, orderBy: {direction: DESC, field: STARGAZERS}, after: $after) {
nodes {
name
stargazers {
@@ -150,14 +149,7 @@ const totalStarsFetcher = async (username, repoToHide) => {
let hasNextPage = true;
let endCursor = null;
while (hasNextPage) {
- const variables = {
- login: username,
- first: 100,
- after: endCursor,
- ownerAffiliations: parseBoolean(process.env.INCLUDE_ORGS)
- ? ["OWNER", "COLLABORATOR"]
- : ["OWNER"],
- };
+ const variables = { login: username, first: 100, after: endCursor };
let res = await retryer(repositoriesFetcher, variables);
if (res.data.errors) {
@@ -211,12 +203,7 @@ const fetchStats = async (
rank: { level: "C", score: 0 },
};
- let res = await retryer(fetcher, {
- login: username,
- ownerAffiliations: parseBoolean(process.env.INCLUDE_ORGS)
- ? ["OWNER", "COLLABORATOR"]
- : ["OWNER"],
- });
+ let res = await retryer(fetcher, { login: username });
// Catch GraphQL errors.
if (res.data.errors) {
diff --git a/src/fetchers/top-languages-fetcher.js b/src/fetchers/top-languages-fetcher.js
index cf8c3d16610ab..86d794435be08 100644
--- a/src/fetchers/top-languages-fetcher.js
+++ b/src/fetchers/top-languages-fetcher.js
@@ -4,7 +4,6 @@ import {
CustomError,
logger,
MissingParamError,
- parseBoolean,
request,
wrapTextMultiline,
} from "../common/utils.js";
@@ -20,10 +19,10 @@ const fetcher = (variables, token) => {
return request(
{
query: `
- query userInfo($login: String!, $ownerAffiliations: [RepositoryAffiliation]) {
+ query userInfo($login: String!) {
user(login: $login) {
# fetch only owner repos & not forks
- repositories(ownerAffiliations: $ownerAffiliations, isFork: false, first: 100) {
+ repositories(ownerAffiliations: OWNER, isFork: false, first: 100) {
nodes {
name
languages(first: 10, orderBy: {field: SIZE, direction: DESC}) {
@@ -58,12 +57,7 @@ const fetcher = (variables, token) => {
const fetchTopLanguages = async (username, exclude_repo = []) => {
if (!username) throw new MissingParamError(["username"]);
- const res = await retryer(fetcher, {
- login: username,
- ownerAffiliations: parseBoolean(process.env.INCLUDE_ORGS)
- ? ["OWNER", "COLLABORATOR"]
- : ["OWNER"],
- });
+ const res = await retryer(fetcher, { login: username });
if (res.data.errors) {
logger.error(res.data.errors);
From ad3726ee491492ab6d312cba09f738986192fd0e Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Tue, 22 Nov 2022 09:18:22 +0100
Subject: [PATCH 126/905] fix: fix repoContrib confusion (#2269) (#2274)
This commit prevents confusion about the Contributed to stat. Currently,
only the last year's results are shown, but it looks like it is the
all-time contribution count (see #2269). This commit adds a ' (last year)'
suffix to prevent this confusion from happening.
---
src/cards/stats-card.js | 4 ++--
tests/renderStatsCard.test.js | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index b078728ea54c3..a44f17f31f0f4 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -154,7 +154,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
},
contribs: {
icon: icons.contribs,
- label: i18n.t("statcard.contribs"),
+ label: i18n.t("statcard.contribs") + " (last year)",
value: contributedTo,
id: "contribs",
},
@@ -186,7 +186,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
index,
showIcons: show_icons,
shiftValuePos:
- (!include_all_commits ? 50 : 35) + (isLongLocale ? 50 : 0),
+ (!include_all_commits ? 79.01 : 35) + (isLongLocale ? 50 : 0),
bold: text_bold,
}),
);
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 288048670f20b..e39e45b7870e3 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -344,7 +344,7 @@ describe("Test renderStatsCard", () => {
document.querySelector(
'g[transform="translate(0, 100)"]>.stagger>.stat.bold',
).textContent,
- ).toMatchInlineSnapshot(`"参与项目数:"`);
+ ).toMatchInlineSnapshot(`"参与项目数 (last year):"`);
});
it("should render without rounding", () => {
From 9eb0c3cbb40d551b93536c45100994d4c83b8c04 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Tue, 22 Nov 2022 09:46:41 +0100
Subject: [PATCH 127/905] feat: fix 'include_all_commits' inner card margin
(#2283)
---
src/cards/stats-card.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index a44f17f31f0f4..a049ecce1c7e3 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -185,8 +185,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
...STATS[key],
index,
showIcons: show_icons,
- shiftValuePos:
- (!include_all_commits ? 79.01 : 35) + (isLongLocale ? 50 : 0),
+ shiftValuePos: 79.01 + (isLongLocale ? 50 : 0),
bold: text_bold,
}),
);
From 42fdff624fb7a3b389792f27352be594c2a45e07 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 9 Jan 2023 15:42:45 +0100
Subject: [PATCH 128/905] build(deps): bump json5 from 2.2.1 to 2.2.3 (#2373)
Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3)
---
updated-dependencies:
- dependency-name: json5
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package-lock.json | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 048c316bfde58..64d79cfbe84d4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3929,9 +3929,9 @@
"dev": true
},
"node_modules/json5": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
- "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"bin": {
"json5": "lib/cli.js"
@@ -8656,9 +8656,9 @@
"dev": true
},
"json5": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
- "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true
},
"kleur": {
From 227711c6289679325b325ba8418a643354b76aa0 Mon Sep 17 00:00:00 2001
From: rickstaa
Date: Tue, 10 Jan 2023 10:08:33 +0000
Subject: [PATCH 129/905] test: update snapshots
---
tests/renderStatsCard.test.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index e39e45b7870e3..5afb1f0218e5d 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -329,7 +329,7 @@ describe("Test renderStatsCard", () => {
document.querySelector(
'g[transform="translate(0, 25)"]>.stagger>.stat.bold',
).textContent,
- ).toMatchInlineSnapshot(`"累计提交数(commit) (2022):"`);
+ ).toMatchInlineSnapshot(`"累计提交数(commit) (2023):"`);
expect(
document.querySelector(
'g[transform="translate(0, 50)"]>.stagger>.stat.bold',
From 77dcdab42c306fd49e71e32a2335d6c06a90baf1 Mon Sep 17 00:00:00 2001
From: Huzaifa Khilawala <55500003+RedHeadphone@users.noreply.github.com>
Date: Tue, 10 Jan 2023 17:51:35 +0530
Subject: [PATCH 130/905] Add loading Animation to Most used Language card
(#2197)
* add: text animation
* compact progress done
* cleaned code
* non compact animation done
* tests fixed + prettier
* revert: vercel.json
* remove: unnecessary import
* added parameter in docs
* style: improve syntax
Co-authored-by: rickstaa
---
api/top-langs.js | 2 +
readme.md | 1 +
src/cards/top-languages-card.js | 82 ++++++++++++++++++++++++--------
src/cards/types.d.ts | 1 +
src/common/createProgressNode.js | 19 ++++----
5 files changed, 76 insertions(+), 29 deletions(-)
diff --git a/api/top-langs.js b/api/top-langs.js
index d183d3b455ca0..19cccb894e33a 100644
--- a/api/top-langs.js
+++ b/api/top-langs.js
@@ -29,6 +29,7 @@ export default async (req, res) => {
locale,
border_radius,
border_color,
+ disable_animations,
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
@@ -75,6 +76,7 @@ export default async (req, res) => {
border_radius,
border_color,
locale: locale ? locale.toLowerCase() : null,
+ disable_animations: parseBoolean(disable_animations),
}),
);
} catch (err) {
diff --git a/readme.md b/readme.md
index bfe042fcc2032..716bda22758c6 100644
--- a/readme.md
+++ b/readme.md
@@ -304,6 +304,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`.
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
- `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`.
+- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
> **Warning**
> Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 602d1b811b5df..9396ff8e73d5e 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -39,46 +39,53 @@ const getLongestLang = (arr) =>
* Creates a node to display usage of a programming language in percentage
* using text and a horizontal progress bar.
*
- * @param {object[]} props Function properties.
+ * @param {object} props Function properties.
* @param {number} props.width The card width
* @param {string} props.name Name of the programming language.
* @param {string} props.color Color of the programming language.
* @param {string} props.progress Usage of the programming language in percentage.
+ * @param {number} props.index Index of the programming language.
* @returns {string} Programming language SVG node.
*/
-const createProgressTextNode = ({ width, color, name, progress }) => {
+const createProgressTextNode = ({ width, color, name, progress, index }) => {
+ const staggerDelay = (index + 3) * 150;
const paddingRight = 95;
const progressTextX = width - paddingRight + 10;
const progressWidth = width - paddingRight;
return `
- ${name}
- ${progress}%
- ${createProgressNode({
- x: 0,
- y: 25,
- color,
- width: progressWidth,
- progress,
- progressBarBackgroundColor: "#ddd",
- })}
+
+ ${name}
+ ${progress}%
+ ${createProgressNode({
+ x: 0,
+ y: 25,
+ color,
+ width: progressWidth,
+ progress,
+ progressBarBackgroundColor: "#ddd",
+ delay: staggerDelay + 300,
+ })}
+
`;
};
/**
* Creates a text only node to display usage of a programming language in percentage.
*
- * @param {object[]} props Function properties.
+ * @param {object} props Function properties.
* @param {Lang} props.lang Programming language object.
* @param {number} props.totalSize Total size of all languages.
+ * @param {number} props.index Index of the programming language.
* @returns {string} Compact layout programming language SVG node.
*/
-const createCompactLangNode = ({ lang, totalSize }) => {
+const createCompactLangNode = ({ lang, totalSize, index }) => {
const percentage = ((lang.size / totalSize) * 100).toFixed(2);
+ const staggerDelay = (index + 3) * 150;
const color = lang.color || "#858585";
return `
-
+
${lang.name} ${percentage}%
@@ -104,7 +111,6 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
createCompactLangNode({
lang,
totalSize,
- // @ts-ignore
index,
}),
);
@@ -134,12 +140,13 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
*/
const renderNormalLayout = (langs, width, totalLanguageSize) => {
return flexLayout({
- items: langs.map((lang) => {
+ items: langs.map((lang, index) => {
return createProgressTextNode({
- width: width,
+ width,
name: lang.name,
color: lang.color || DEFAULT_LANG_COLOR,
progress: ((lang.size / totalLanguageSize) * 100).toFixed(2),
+ index,
});
}),
gap: 40,
@@ -187,7 +194,7 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => {
return `
-
+
${compactProgressBar}
@@ -276,6 +283,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
langs_count = DEFAULT_LANGS_COUNT,
border_radius,
border_color,
+ disable_animations,
} = options;
const i18n = new I18n({
@@ -324,11 +332,43 @@ const renderTopLanguages = (topLangs, options = {}) => {
colors,
});
- card.disableAnimations();
+ if (disable_animations) card.disableAnimations();
+
card.setHideBorder(hide_border);
card.setHideTitle(hide_title);
card.setCSS(
- `.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${colors.textColor} }`,
+ `
+ @keyframes slideInAnimation {
+ from {
+ width: 0;
+ }
+ to {
+ width: calc(100%-100px);
+ }
+ }
+ @keyframes growWidthAnimation {
+ from {
+ width: 0;
+ }
+ to {
+ width: 100%;
+ }
+ }
+ .lang-name {
+ font: 400 11px "Segoe UI", Ubuntu, Sans-Serif;
+ fill: ${colors.textColor};
+ }
+ .stagger {
+ opacity: 0;
+ animation: fadeInAnimation 0.3s ease-in-out forwards;
+ }
+ #rect-mask rect{
+ animation: slideInAnimation 1s ease-in-out forwards;
+ }
+ .lang-progress{
+ animation: growWidthAnimation 0.6s ease-in-out forwards;
+ }
+ `,
);
return card.render(`
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index 502314c41fa92..c5945d48be71e 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -37,6 +37,7 @@ export type TopLangOptions = CommonOptions & {
layout: "compact" | "normal";
custom_title: string;
langs_count: number;
+ disable_animations: boolean;
};
type WakaTimeOptions = CommonOptions & {
diff --git a/src/common/createProgressNode.js b/src/common/createProgressNode.js
index c36818b193b2f..2825583c7406a 100644
--- a/src/common/createProgressNode.js
+++ b/src/common/createProgressNode.js
@@ -10,6 +10,7 @@ import { clampValue } from "./utils.js";
* @param {string} createProgressNodeParams.color Progress color.
* @param {string} createProgressNodeParams.progress Progress value.
* @param {string} createProgressNodeParams.progressBarBackgroundColor Progress bar bg color.
+ * @param {number} createProgressNodeParams.delay Delay before animation starts.
* @returns {string} Progress node.
*/
const createProgressNode = ({
@@ -19,20 +20,22 @@ const createProgressNode = ({
color,
progress,
progressBarBackgroundColor,
+ delay,
}) => {
const progressPercentage = clampValue(progress, 2, 100);
return `
-
-
+
+
+
`;
};
From 5ae959b57c0831bc79d43425e07d0fe7c6a58011 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Tue, 10 Jan 2023 13:25:06 +0100
Subject: [PATCH 131/905] ci: fix theme readme generation action (#2271)
---
scripts/push-theme-readme.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/push-theme-readme.sh b/scripts/push-theme-readme.sh
index 4a035db3041a0..1ab5de474ea5a 100755
--- a/scripts/push-theme-readme.sh
+++ b/scripts/push-theme-readme.sh
@@ -9,6 +9,6 @@ git config --global user.name "GitHub Readme Stats Bot"
git branch -d $BRANCH_NAME || true
git checkout -b $BRANCH_NAME
git add --all
-git commit --message "docs(theme): Auto update theme readme" || exit 0
+git commit --no-verify --message "docs(theme): Auto update theme readme"
git remote add origin-$BRANCH_NAME https://${PERSONAL_TOKEN}@github.com/${GH_REPO}.git
git push --force --quiet --set-upstream origin-$BRANCH_NAME $BRANCH_NAME
From 0850a9763058aa018b8538b34772f98bbf759aa2 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Thu, 12 Jan 2023 22:44:27 +0100
Subject: [PATCH 132/905] Revert "build(deps): bump json5 from 2.2.1 to 2.2.3
(#2373)" (#2393)
This reverts commit 42fdff624fb7a3b389792f27352be594c2a45e07.
---
package-lock.json | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 64d79cfbe84d4..048c316bfde58 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3929,9 +3929,9 @@
"dev": true
},
"node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
+ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"dev": true,
"bin": {
"json5": "lib/cli.js"
@@ -8656,9 +8656,9 @@
"dev": true
},
"json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
+ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"dev": true
},
"kleur": {
From 70f0264905d9370efa635b6a611c8719b8958efa Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Thu, 12 Jan 2023 22:48:28 +0100
Subject: [PATCH 133/905] Revert "ci: fix theme readme generation action
(#2271)" (#2394)
This reverts commit 5ae959b57c0831bc79d43425e07d0fe7c6a58011.
---
scripts/push-theme-readme.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/push-theme-readme.sh b/scripts/push-theme-readme.sh
index 1ab5de474ea5a..4a035db3041a0 100755
--- a/scripts/push-theme-readme.sh
+++ b/scripts/push-theme-readme.sh
@@ -9,6 +9,6 @@ git config --global user.name "GitHub Readme Stats Bot"
git branch -d $BRANCH_NAME || true
git checkout -b $BRANCH_NAME
git add --all
-git commit --no-verify --message "docs(theme): Auto update theme readme"
+git commit --message "docs(theme): Auto update theme readme" || exit 0
git remote add origin-$BRANCH_NAME https://${PERSONAL_TOKEN}@github.com/${GH_REPO}.git
git push --force --quiet --set-upstream origin-$BRANCH_NAME $BRANCH_NAME
From 4b8198fa2198da394b71e43fe4c59862a7014287 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Thu, 12 Jan 2023 22:52:34 +0100
Subject: [PATCH 134/905] Revert "Add loading Animation to Most used Language
card (#2197)" (#2396)
This reverts commit 77dcdab42c306fd49e71e32a2335d6c06a90baf1.
---
api/top-langs.js | 2 -
readme.md | 1 -
src/cards/top-languages-card.js | 82 ++++++++------------------------
src/cards/types.d.ts | 1 -
src/common/createProgressNode.js | 19 ++++----
5 files changed, 29 insertions(+), 76 deletions(-)
diff --git a/api/top-langs.js b/api/top-langs.js
index 19cccb894e33a..d183d3b455ca0 100644
--- a/api/top-langs.js
+++ b/api/top-langs.js
@@ -29,7 +29,6 @@ export default async (req, res) => {
locale,
border_radius,
border_color,
- disable_animations,
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
@@ -76,7 +75,6 @@ export default async (req, res) => {
border_radius,
border_color,
locale: locale ? locale.toLowerCase() : null,
- disable_animations: parseBoolean(disable_animations),
}),
);
} catch (err) {
diff --git a/readme.md b/readme.md
index 716bda22758c6..bfe042fcc2032 100644
--- a/readme.md
+++ b/readme.md
@@ -304,7 +304,6 @@ You can provide multiple comma-separated values in the bg_color option to render
- `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`.
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
- `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`.
-- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
> **Warning**
> Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 9396ff8e73d5e..602d1b811b5df 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -39,53 +39,46 @@ const getLongestLang = (arr) =>
* Creates a node to display usage of a programming language in percentage
* using text and a horizontal progress bar.
*
- * @param {object} props Function properties.
+ * @param {object[]} props Function properties.
* @param {number} props.width The card width
* @param {string} props.name Name of the programming language.
* @param {string} props.color Color of the programming language.
* @param {string} props.progress Usage of the programming language in percentage.
- * @param {number} props.index Index of the programming language.
* @returns {string} Programming language SVG node.
*/
-const createProgressTextNode = ({ width, color, name, progress, index }) => {
- const staggerDelay = (index + 3) * 150;
+const createProgressTextNode = ({ width, color, name, progress }) => {
const paddingRight = 95;
const progressTextX = width - paddingRight + 10;
const progressWidth = width - paddingRight;
return `
-
- ${name}
- ${progress}%
- ${createProgressNode({
- x: 0,
- y: 25,
- color,
- width: progressWidth,
- progress,
- progressBarBackgroundColor: "#ddd",
- delay: staggerDelay + 300,
- })}
-
+ ${name}
+ ${progress}%
+ ${createProgressNode({
+ x: 0,
+ y: 25,
+ color,
+ width: progressWidth,
+ progress,
+ progressBarBackgroundColor: "#ddd",
+ })}
`;
};
/**
* Creates a text only node to display usage of a programming language in percentage.
*
- * @param {object} props Function properties.
+ * @param {object[]} props Function properties.
* @param {Lang} props.lang Programming language object.
* @param {number} props.totalSize Total size of all languages.
- * @param {number} props.index Index of the programming language.
* @returns {string} Compact layout programming language SVG node.
*/
-const createCompactLangNode = ({ lang, totalSize, index }) => {
+const createCompactLangNode = ({ lang, totalSize }) => {
const percentage = ((lang.size / totalSize) * 100).toFixed(2);
- const staggerDelay = (index + 3) * 150;
const color = lang.color || "#858585";
return `
-
+
${lang.name} ${percentage}%
@@ -111,6 +104,7 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
createCompactLangNode({
lang,
totalSize,
+ // @ts-ignore
index,
}),
);
@@ -140,13 +134,12 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
*/
const renderNormalLayout = (langs, width, totalLanguageSize) => {
return flexLayout({
- items: langs.map((lang, index) => {
+ items: langs.map((lang) => {
return createProgressTextNode({
- width,
+ width: width,
name: lang.name,
color: lang.color || DEFAULT_LANG_COLOR,
progress: ((lang.size / totalLanguageSize) * 100).toFixed(2),
- index,
});
}),
gap: 40,
@@ -194,7 +187,7 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => {
return `
-
+
${compactProgressBar}
@@ -283,7 +276,6 @@ const renderTopLanguages = (topLangs, options = {}) => {
langs_count = DEFAULT_LANGS_COUNT,
border_radius,
border_color,
- disable_animations,
} = options;
const i18n = new I18n({
@@ -332,43 +324,11 @@ const renderTopLanguages = (topLangs, options = {}) => {
colors,
});
- if (disable_animations) card.disableAnimations();
-
+ card.disableAnimations();
card.setHideBorder(hide_border);
card.setHideTitle(hide_title);
card.setCSS(
- `
- @keyframes slideInAnimation {
- from {
- width: 0;
- }
- to {
- width: calc(100%-100px);
- }
- }
- @keyframes growWidthAnimation {
- from {
- width: 0;
- }
- to {
- width: 100%;
- }
- }
- .lang-name {
- font: 400 11px "Segoe UI", Ubuntu, Sans-Serif;
- fill: ${colors.textColor};
- }
- .stagger {
- opacity: 0;
- animation: fadeInAnimation 0.3s ease-in-out forwards;
- }
- #rect-mask rect{
- animation: slideInAnimation 1s ease-in-out forwards;
- }
- .lang-progress{
- animation: growWidthAnimation 0.6s ease-in-out forwards;
- }
- `,
+ `.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${colors.textColor} }`,
);
return card.render(`
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index c5945d48be71e..502314c41fa92 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -37,7 +37,6 @@ export type TopLangOptions = CommonOptions & {
layout: "compact" | "normal";
custom_title: string;
langs_count: number;
- disable_animations: boolean;
};
type WakaTimeOptions = CommonOptions & {
diff --git a/src/common/createProgressNode.js b/src/common/createProgressNode.js
index 2825583c7406a..c36818b193b2f 100644
--- a/src/common/createProgressNode.js
+++ b/src/common/createProgressNode.js
@@ -10,7 +10,6 @@ import { clampValue } from "./utils.js";
* @param {string} createProgressNodeParams.color Progress color.
* @param {string} createProgressNodeParams.progress Progress value.
* @param {string} createProgressNodeParams.progressBarBackgroundColor Progress bar bg color.
- * @param {number} createProgressNodeParams.delay Delay before animation starts.
* @returns {string} Progress node.
*/
const createProgressNode = ({
@@ -20,22 +19,20 @@ const createProgressNode = ({
color,
progress,
progressBarBackgroundColor,
- delay,
}) => {
const progressPercentage = clampValue(progress, 2, 100);
return `
-
-
-
+
+
`;
};
From 0ff426d258387ecd0ebbb9206d91b96781e61cf0 Mon Sep 17 00:00:00 2001
From: Anurag Hazra
Date: Fri, 13 Jan 2023 13:16:33 +0530
Subject: [PATCH 135/905] fix: retryer fixed (#2400)
---
src/common/retryer.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/common/retryer.js b/src/common/retryer.js
index e54eedbec6dd5..73833ef85b3a4 100644
--- a/src/common/retryer.js
+++ b/src/common/retryer.js
@@ -45,8 +45,9 @@ const retryer = async (fetcher, variables, retries = 0) => {
// prettier-ignore
// also checking for bad credentials if any tokens gets invalidated
const isBadCredential = err.response.data && err.response.data.message === "Bad credentials";
+ const isAccountSuspended = err.response.data && err.response.data.message === "Sorry. Your account was suspended.";
- if (isBadCredential) {
+ if (isBadCredential || isAccountSuspended) {
logger.log(`PAT_${retries + 1} Failed`);
retries++;
// directly return from the function
From ab9c563ec51a0843ab8ad0877d5f9dd491d23e00 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 16 Jan 2023 12:21:13 +0100
Subject: [PATCH 136/905] Revert "Revert "ci: fix theme readme generation
action (#2271)" (#2394)" (#2418)
This reverts commit 70f0264905d9370efa635b6a611c8719b8958efa.
---
scripts/push-theme-readme.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/push-theme-readme.sh b/scripts/push-theme-readme.sh
index 4a035db3041a0..1ab5de474ea5a 100755
--- a/scripts/push-theme-readme.sh
+++ b/scripts/push-theme-readme.sh
@@ -9,6 +9,6 @@ git config --global user.name "GitHub Readme Stats Bot"
git branch -d $BRANCH_NAME || true
git checkout -b $BRANCH_NAME
git add --all
-git commit --message "docs(theme): Auto update theme readme" || exit 0
+git commit --no-verify --message "docs(theme): Auto update theme readme"
git remote add origin-$BRANCH_NAME https://${PERSONAL_TOKEN}@github.com/${GH_REPO}.git
git push --force --quiet --set-upstream origin-$BRANCH_NAME $BRANCH_NAME
From ad9db67b4c551aba6e19cc5af9030d85ac1c4906 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 16 Jan 2023 12:28:31 +0100
Subject: [PATCH 137/905] refactor: update code formatting
---
src/common/retryer.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/common/retryer.js b/src/common/retryer.js
index 73833ef85b3a4..5351cbe8cf99a 100644
--- a/src/common/retryer.js
+++ b/src/common/retryer.js
@@ -45,7 +45,9 @@ const retryer = async (fetcher, variables, retries = 0) => {
// prettier-ignore
// also checking for bad credentials if any tokens gets invalidated
const isBadCredential = err.response.data && err.response.data.message === "Bad credentials";
- const isAccountSuspended = err.response.data && err.response.data.message === "Sorry. Your account was suspended.";
+ const isAccountSuspended =
+ err.response.data &&
+ err.response.data.message === "Sorry. Your account was suspended.";
if (isBadCredential || isAccountSuspended) {
logger.log(`PAT_${retries + 1} Failed`);
From 06a2a78cfcb1cd29c3b8b46d3899ffac10ab14b8 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 16 Jan 2023 12:30:39 +0100
Subject: [PATCH 138/905] Revert "Revert "Add loading Animation to Most used
Language card (#2197)" (#2396)" (#2419)
This reverts commit 4b8198fa2198da394b71e43fe4c59862a7014287.
---
api/top-langs.js | 2 +
readme.md | 1 +
src/cards/top-languages-card.js | 82 ++++++++++++++++++++++++--------
src/cards/types.d.ts | 1 +
src/common/createProgressNode.js | 19 ++++----
5 files changed, 76 insertions(+), 29 deletions(-)
diff --git a/api/top-langs.js b/api/top-langs.js
index d183d3b455ca0..19cccb894e33a 100644
--- a/api/top-langs.js
+++ b/api/top-langs.js
@@ -29,6 +29,7 @@ export default async (req, res) => {
locale,
border_radius,
border_color,
+ disable_animations,
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
@@ -75,6 +76,7 @@ export default async (req, res) => {
border_radius,
border_color,
locale: locale ? locale.toLowerCase() : null,
+ disable_animations: parseBoolean(disable_animations),
}),
);
} catch (err) {
diff --git a/readme.md b/readme.md
index bfe042fcc2032..716bda22758c6 100644
--- a/readme.md
+++ b/readme.md
@@ -304,6 +304,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`.
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
- `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`.
+- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
> **Warning**
> Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 602d1b811b5df..9396ff8e73d5e 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -39,46 +39,53 @@ const getLongestLang = (arr) =>
* Creates a node to display usage of a programming language in percentage
* using text and a horizontal progress bar.
*
- * @param {object[]} props Function properties.
+ * @param {object} props Function properties.
* @param {number} props.width The card width
* @param {string} props.name Name of the programming language.
* @param {string} props.color Color of the programming language.
* @param {string} props.progress Usage of the programming language in percentage.
+ * @param {number} props.index Index of the programming language.
* @returns {string} Programming language SVG node.
*/
-const createProgressTextNode = ({ width, color, name, progress }) => {
+const createProgressTextNode = ({ width, color, name, progress, index }) => {
+ const staggerDelay = (index + 3) * 150;
const paddingRight = 95;
const progressTextX = width - paddingRight + 10;
const progressWidth = width - paddingRight;
return `
- ${name}
- ${progress}%
- ${createProgressNode({
- x: 0,
- y: 25,
- color,
- width: progressWidth,
- progress,
- progressBarBackgroundColor: "#ddd",
- })}
+
+ ${name}
+ ${progress}%
+ ${createProgressNode({
+ x: 0,
+ y: 25,
+ color,
+ width: progressWidth,
+ progress,
+ progressBarBackgroundColor: "#ddd",
+ delay: staggerDelay + 300,
+ })}
+
`;
};
/**
* Creates a text only node to display usage of a programming language in percentage.
*
- * @param {object[]} props Function properties.
+ * @param {object} props Function properties.
* @param {Lang} props.lang Programming language object.
* @param {number} props.totalSize Total size of all languages.
+ * @param {number} props.index Index of the programming language.
* @returns {string} Compact layout programming language SVG node.
*/
-const createCompactLangNode = ({ lang, totalSize }) => {
+const createCompactLangNode = ({ lang, totalSize, index }) => {
const percentage = ((lang.size / totalSize) * 100).toFixed(2);
+ const staggerDelay = (index + 3) * 150;
const color = lang.color || "#858585";
return `
-
+
${lang.name} ${percentage}%
@@ -104,7 +111,6 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
createCompactLangNode({
lang,
totalSize,
- // @ts-ignore
index,
}),
);
@@ -134,12 +140,13 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
*/
const renderNormalLayout = (langs, width, totalLanguageSize) => {
return flexLayout({
- items: langs.map((lang) => {
+ items: langs.map((lang, index) => {
return createProgressTextNode({
- width: width,
+ width,
name: lang.name,
color: lang.color || DEFAULT_LANG_COLOR,
progress: ((lang.size / totalLanguageSize) * 100).toFixed(2),
+ index,
});
}),
gap: 40,
@@ -187,7 +194,7 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => {
return `
-
+
${compactProgressBar}
@@ -276,6 +283,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
langs_count = DEFAULT_LANGS_COUNT,
border_radius,
border_color,
+ disable_animations,
} = options;
const i18n = new I18n({
@@ -324,11 +332,43 @@ const renderTopLanguages = (topLangs, options = {}) => {
colors,
});
- card.disableAnimations();
+ if (disable_animations) card.disableAnimations();
+
card.setHideBorder(hide_border);
card.setHideTitle(hide_title);
card.setCSS(
- `.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${colors.textColor} }`,
+ `
+ @keyframes slideInAnimation {
+ from {
+ width: 0;
+ }
+ to {
+ width: calc(100%-100px);
+ }
+ }
+ @keyframes growWidthAnimation {
+ from {
+ width: 0;
+ }
+ to {
+ width: 100%;
+ }
+ }
+ .lang-name {
+ font: 400 11px "Segoe UI", Ubuntu, Sans-Serif;
+ fill: ${colors.textColor};
+ }
+ .stagger {
+ opacity: 0;
+ animation: fadeInAnimation 0.3s ease-in-out forwards;
+ }
+ #rect-mask rect{
+ animation: slideInAnimation 1s ease-in-out forwards;
+ }
+ .lang-progress{
+ animation: growWidthAnimation 0.6s ease-in-out forwards;
+ }
+ `,
);
return card.render(`
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index 502314c41fa92..c5945d48be71e 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -37,6 +37,7 @@ export type TopLangOptions = CommonOptions & {
layout: "compact" | "normal";
custom_title: string;
langs_count: number;
+ disable_animations: boolean;
};
type WakaTimeOptions = CommonOptions & {
diff --git a/src/common/createProgressNode.js b/src/common/createProgressNode.js
index c36818b193b2f..2825583c7406a 100644
--- a/src/common/createProgressNode.js
+++ b/src/common/createProgressNode.js
@@ -10,6 +10,7 @@ import { clampValue } from "./utils.js";
* @param {string} createProgressNodeParams.color Progress color.
* @param {string} createProgressNodeParams.progress Progress value.
* @param {string} createProgressNodeParams.progressBarBackgroundColor Progress bar bg color.
+ * @param {number} createProgressNodeParams.delay Delay before animation starts.
* @returns {string} Progress node.
*/
const createProgressNode = ({
@@ -19,20 +20,22 @@ const createProgressNode = ({
color,
progress,
progressBarBackgroundColor,
+ delay,
}) => {
const progressPercentage = clampValue(progress, 2, 100);
return `
-
-
+
+
+
`;
};
From 8bc69e761ff7c922f47e6561d7a2f4fd0cc153c7 Mon Sep 17 00:00:00 2001
From: Zohan Subhash
Date: Thu, 19 Jan 2023 14:00:46 +0530
Subject: [PATCH 139/905] Update readme.md (#2442)
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index 716bda22758c6..281c4877f9422 100644
--- a/readme.md
+++ b/readme.md
@@ -259,7 +259,7 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you
- `bg_color` - Card's background color _(hex color)_ **or** a gradient in the form of _angle,start,end_. Default: `fffefe`
- `hide_border` - Hides the card's border _(boolean)_. Default: `false`
- `theme` - name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme.
-- `cache_seconds` - set the cache header manually _(min: 7200, max: 86400)_. Default: `14400 seconds (4 hours)`.
+- `cache_seconds` - set the cache header manually _(min: 14400, max: 86400)_. Default: `14400 seconds (4 hours)`.
- `locale` - set the language in the card _(e.g. cn, de, es, etc.)_. Default: `en`.
- `border_radius` - Corner rounding on the card. Default: `4.5`.
From d5d1f44e1ccd8f36fc709cae2b42dd0b91f90b07 Mon Sep 17 00:00:00 2001
From: rickstaa
Date: Sat, 21 Jan 2023 11:30:50 +0100
Subject: [PATCH 140/905] test: fix e2e tests
---
tests/e2e/e2e.test.js | 43 +++++++++++++++++++------------------------
1 file changed, 19 insertions(+), 24 deletions(-)
diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js
index 48bf16a0e083a..38b707f8239e9 100644
--- a/tests/e2e/e2e.test.js
+++ b/tests/e2e/e2e.test.js
@@ -11,27 +11,22 @@ import { renderStatsCard } from "../../src/cards/stats-card.js";
import { renderTopLanguages } from "../../src/cards/top-languages-card.js";
import { renderWakatimeCard } from "../../src/cards/wakatime-card.js";
-const REPO = "dummy-cra";
-const USER = "grsdummy";
+const REPO = "cra-test";
+const USER = "catelinemnemosyne";
const STATS_DATA = {
- name: "grsdummy",
- totalPRs: 2,
- totalCommits: 2,
+ name: "Cateline Mnemosyne",
+ totalPRs: 1,
+ totalCommits: 7,
totalIssues: 1,
totalStars: 1,
- contributedTo: 2,
+ contributedTo: 1,
rank: {
level: "A+",
- score: 50.900829325065935,
+ score: 50.893750297869225,
},
};
const LANGS_DATA = {
- TypeScript: {
- color: "#3178c6",
- name: "TypeScript",
- size: 2049,
- },
HTML: {
color: "#e34c26",
name: "HTML",
@@ -42,19 +37,19 @@ const LANGS_DATA = {
name: "CSS",
size: 930,
},
- Python: {
+ JavaScript: {
color: "#3572A5",
- name: "Python",
- size: 671,
+ name: "JavaScript",
+ size: 1912,
},
};
const WAKATIME_DATA = {
human_readable_range: "last week",
is_already_updating: false,
- is_coding_activity_visible: false,
+ is_coding_activity_visible: true,
is_including_today: false,
- is_other_usage_visible: false,
+ is_other_usage_visible: true,
is_stuck: false,
is_up_to_date: false,
is_up_to_date_pending_future: false,
@@ -62,24 +57,24 @@ const WAKATIME_DATA = {
range: "last_7_days",
status: "pending_update",
timeout: 15,
- username: "grsdummy",
+ username: USER,
writes_only: false,
};
const REPOSITORY_DATA = {
- name: "dummy-cra",
- nameWithOwner: "grsdummy/dummy-cra",
+ name: "cra-test",
+ nameWithOwner: `${USER}/cra-test`,
isPrivate: false,
isArchived: false,
isTemplate: false,
stargazers: {
totalCount: 1,
},
- description: "Dummy create react app.",
+ description: "Simple cra test repo.",
primaryLanguage: {
- color: "#3178c6",
- id: "MDg6TGFuZ3VhZ2UyODc=",
- name: "TypeScript",
+ color: "#f1e05a",
+ id: "MDg6TGFuZ3VhZ2UxNDA=",
+ name: "JavaScript",
},
forkCount: 0,
starCount: 1,
From cfa84232e2cec0ddaed4a54699cfb8a7311e528e Mon Sep 17 00:00:00 2001
From: rickstaa
Date: Sat, 21 Jan 2023 11:32:25 +0100
Subject: [PATCH 141/905] test: update snapshots
---
tests/renderStatsCard.test.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index e39e45b7870e3..5afb1f0218e5d 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -329,7 +329,7 @@ describe("Test renderStatsCard", () => {
document.querySelector(
'g[transform="translate(0, 25)"]>.stagger>.stat.bold',
).textContent,
- ).toMatchInlineSnapshot(`"累计提交数(commit) (2022):"`);
+ ).toMatchInlineSnapshot(`"累计提交数(commit) (2023):"`);
expect(
document.querySelector(
'g[transform="translate(0, 50)"]>.stagger>.stat.bold',
From eab140241718725c5de32aeac5f6e8d14c31fbd0 Mon Sep 17 00:00:00 2001
From: rickstaa
Date: Sat, 21 Jan 2023 11:37:41 +0100
Subject: [PATCH 142/905] test: fix e2e test data
---
tests/e2e/e2e.test.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js
index 38b707f8239e9..999d2c96d6578 100644
--- a/tests/e2e/e2e.test.js
+++ b/tests/e2e/e2e.test.js
@@ -38,7 +38,7 @@ const LANGS_DATA = {
size: 930,
},
JavaScript: {
- color: "#3572A5",
+ color: "#f1e05a",
name: "JavaScript",
size: 1912,
},
From fbb49e3c80f2c4f84fd86834514bcf9638a011a7 Mon Sep 17 00:00:00 2001
From: rickstaa
Date: Sat, 21 Jan 2023 12:15:58 +0100
Subject: [PATCH 143/905] test: update e2e test data
---
tests/e2e/e2e.test.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js
index 999d2c96d6578..4d00646d02f67 100644
--- a/tests/e2e/e2e.test.js
+++ b/tests/e2e/e2e.test.js
@@ -11,7 +11,7 @@ import { renderStatsCard } from "../../src/cards/stats-card.js";
import { renderTopLanguages } from "../../src/cards/top-languages-card.js";
import { renderWakatimeCard } from "../../src/cards/wakatime-card.js";
-const REPO = "cra-test";
+const REPO = "curly-fiesta";
const USER = "catelinemnemosyne";
const STATS_DATA = {
name: "Cateline Mnemosyne",
From 4ff2c2a425dbeccde302e27042d3aa698bc8609c Mon Sep 17 00:00:00 2001
From: rickstaa
Date: Sat, 21 Jan 2023 17:52:51 +0100
Subject: [PATCH 144/905] feat: fix e2e tests
---
tests/e2e/e2e.test.js | 45 +++++++++++++++++++------------------------
1 file changed, 20 insertions(+), 25 deletions(-)
diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js
index 48bf16a0e083a..4d00646d02f67 100644
--- a/tests/e2e/e2e.test.js
+++ b/tests/e2e/e2e.test.js
@@ -11,27 +11,22 @@ import { renderStatsCard } from "../../src/cards/stats-card.js";
import { renderTopLanguages } from "../../src/cards/top-languages-card.js";
import { renderWakatimeCard } from "../../src/cards/wakatime-card.js";
-const REPO = "dummy-cra";
-const USER = "grsdummy";
+const REPO = "curly-fiesta";
+const USER = "catelinemnemosyne";
const STATS_DATA = {
- name: "grsdummy",
- totalPRs: 2,
- totalCommits: 2,
+ name: "Cateline Mnemosyne",
+ totalPRs: 1,
+ totalCommits: 7,
totalIssues: 1,
totalStars: 1,
- contributedTo: 2,
+ contributedTo: 1,
rank: {
level: "A+",
- score: 50.900829325065935,
+ score: 50.893750297869225,
},
};
const LANGS_DATA = {
- TypeScript: {
- color: "#3178c6",
- name: "TypeScript",
- size: 2049,
- },
HTML: {
color: "#e34c26",
name: "HTML",
@@ -42,19 +37,19 @@ const LANGS_DATA = {
name: "CSS",
size: 930,
},
- Python: {
- color: "#3572A5",
- name: "Python",
- size: 671,
+ JavaScript: {
+ color: "#f1e05a",
+ name: "JavaScript",
+ size: 1912,
},
};
const WAKATIME_DATA = {
human_readable_range: "last week",
is_already_updating: false,
- is_coding_activity_visible: false,
+ is_coding_activity_visible: true,
is_including_today: false,
- is_other_usage_visible: false,
+ is_other_usage_visible: true,
is_stuck: false,
is_up_to_date: false,
is_up_to_date_pending_future: false,
@@ -62,24 +57,24 @@ const WAKATIME_DATA = {
range: "last_7_days",
status: "pending_update",
timeout: 15,
- username: "grsdummy",
+ username: USER,
writes_only: false,
};
const REPOSITORY_DATA = {
- name: "dummy-cra",
- nameWithOwner: "grsdummy/dummy-cra",
+ name: "cra-test",
+ nameWithOwner: `${USER}/cra-test`,
isPrivate: false,
isArchived: false,
isTemplate: false,
stargazers: {
totalCount: 1,
},
- description: "Dummy create react app.",
+ description: "Simple cra test repo.",
primaryLanguage: {
- color: "#3178c6",
- id: "MDg6TGFuZ3VhZ2UyODc=",
- name: "TypeScript",
+ color: "#f1e05a",
+ id: "MDg6TGFuZ3VhZ2UxNDA=",
+ name: "JavaScript",
},
forkCount: 0,
starCount: 1,
From c1dc7b850c3ff0a5db4a60564a4eaf8b9fbcdbda Mon Sep 17 00:00:00 2001
From: rickstaa
Date: Sat, 21 Jan 2023 17:58:35 +0100
Subject: [PATCH 145/905] fix: fix e2e test data
---
tests/e2e/e2e.test.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js
index 4d00646d02f67..402e210fcee17 100644
--- a/tests/e2e/e2e.test.js
+++ b/tests/e2e/e2e.test.js
@@ -62,7 +62,7 @@ const WAKATIME_DATA = {
};
const REPOSITORY_DATA = {
- name: "cra-test",
+ name: REPO,
nameWithOwner: `${USER}/cra-test`,
isPrivate: false,
isArchived: false,
From 60fae292a349cd3d92942dc56bf67778c213cb0d Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sat, 21 Jan 2023 18:32:37 +0100
Subject: [PATCH 146/905] feat: enable multi page star fetching for private
vercel instances (#2159)
* feat: enable multi-page stars' fetching for private vercel instances
This commit enables multi-page stars' support from fetching on private Vercel
instances. This feature can be disabled on the public Vercel instance by adding
the `FETCH_SINGLE_PAGE_STARS=true` as an env variable in the public Vercel
instance. This variable will not be present when people deploy their own Vercel
instance, causing the code to fetch multiple star pages.
* fix: improve stats multi-page fetching behavoir
This commit makes sure that the GraphQL api is only called one time per
100 repositories. The old method added one unnecesairy GraphQL call.
* docs: update documentation
* style: improve code syntax
Co-authored-by: Matteo Pierro
* lol happy new year
* docs: remove rate limit documentation for now
Remove the `FETCH_SINGLE_PAGE_STARS` from documentation for now since it
might confuse people.
* fix: fix error in automatic merge
* feat: make sure env variable is read
Co-authored-by: Matteo Pierro
Co-authored-by: Anurag
---
readme.md | 8 +-
src/fetchers/stats-fetcher.js | 207 +++++++++++++++++-----------------
tests/api.test.js | 35 ++----
tests/fetchStats.test.js | 126 +++++++++++++++------
4 files changed, 210 insertions(+), 166 deletions(-)
diff --git a/readme.md b/readme.md
index 281c4877f9422..678c5c0b14af4 100644
--- a/readme.md
+++ b/readme.md
@@ -93,7 +93,7 @@ Visit and make a small donation to hel
- [Language Card Exclusive Options](#language-card-exclusive-options)
- [Wakatime Card Exclusive Option](#wakatime-card-exclusive-options)
- [Deploy Yourself](#deploy-on-your-own-vercel-instance)
- - [Keep your fork up to date](#keep-your-fork-up-to-date)
+ - [Keep your fork up to date](#keep-your-fork-up-to-date)
# GitHub Stats Card
@@ -264,7 +264,7 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you
- `border_radius` - Corner rounding on the card. Default: `4.5`.
> **Warning**
-> We use caching to decrease the load on our servers (see https://github.com/anuraghazra/github-readme-stats/issues/1471#issuecomment-1271551425). Our cards have a default cache of 4 hours (14400 seconds). Also, note that the cache is clamped to a minimum of 4 hours and a maximum of 24 hours.
+> We use caching to decrease the load on our servers (see ). Our cards have a default cache of 4 hours (14400 seconds). Also, note that the cache is clamped to a minimum of 4 hours and a maximum of 24 hours.
##### Gradient in bg_color
@@ -354,7 +354,7 @@ Use [show_owner](#customization) variable to include the repo's owner username
The top languages card shows a GitHub user's most frequently used top language.
> **Note**
-> Top Languages does not indicate my skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats._
+> Top Languages does not indicate my skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats.
### Usage
@@ -498,7 +498,7 @@ By default, GitHub does not lay out the cards side by side. To do that, you can
## Deploy on your own Vercel instance
-#### [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
+#### :film_projector: [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
> **Warning**
> If you are on the [hobby (i.e. free)](https://vercel.com/pricing) Vercel plan, please make sure you change the `maxDuration` parameter in the [vercel.json](https://github.com/anuraghazra/github-readme-stats/blob/master/vercel.json) file from `30` to `10` (see [#1416](https://github.com/anuraghazra/github-readme-stats/issues/1416#issuecomment-950275476) for more information).
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index 7f6cb9e5e95b4..a7df1e504db2f 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -1,5 +1,6 @@
// @ts-check
import axios from "axios";
+import * as dotenv from "dotenv";
import githubUsernameRegex from "github-username-regex";
import { calculateRank } from "../calculateRank.js";
import { retryer } from "../common/retryer.js";
@@ -11,46 +12,74 @@ import {
wrapTextMultiline,
} from "../common/utils.js";
+dotenv.config();
+
+// GraphQL queries.
+const GRAPHQL_REPOS_FIELD = `
+ repositories(first: 100, ownerAffiliations: OWNER, orderBy: {direction: DESC, field: STARGAZERS}, after: $after) {
+ totalCount
+ nodes {
+ name
+ stargazers {
+ totalCount
+ }
+ }
+ pageInfo {
+ hasNextPage
+ endCursor
+ }
+ }
+`;
+
+const GRAPHQL_REPOS_QUERY = `
+ query userInfo($login: String!, $after: String) {
+ user(login: $login) {
+ ${GRAPHQL_REPOS_FIELD}
+ }
+ }
+`;
+
+const GRAPHQL_STATS_QUERY = `
+ query userInfo($login: String!, $after: String) {
+ user(login: $login) {
+ name
+ login
+ contributionsCollection {
+ totalCommitContributions
+ restrictedContributionsCount
+ }
+ repositoriesContributedTo(first: 1, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) {
+ totalCount
+ }
+ pullRequests(first: 1) {
+ totalCount
+ }
+ openIssues: issues(states: OPEN) {
+ totalCount
+ }
+ closedIssues: issues(states: CLOSED) {
+ totalCount
+ }
+ followers {
+ totalCount
+ }
+ ${GRAPHQL_REPOS_FIELD}
+ }
+ }
+`;
+
/**
* Stats fetcher object.
*
* @param {import('axios').AxiosRequestHeaders} variables Fetcher variables.
* @param {string} token GitHub token.
- * @returns {Promise} Stats fetcher response.
+ * @returns {Promise} Stats fetcher response.
*/
const fetcher = (variables, token) => {
+ const query = !variables.after ? GRAPHQL_STATS_QUERY : GRAPHQL_REPOS_QUERY;
return request(
{
- query: `
- query userInfo($login: String!) {
- user(login: $login) {
- name
- login
- contributionsCollection {
- totalCommitContributions
- restrictedContributionsCount
- }
- repositoriesContributedTo(contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) {
- totalCount
- }
- pullRequests {
- totalCount
- }
- openIssues: issues(states: OPEN) {
- totalCount
- }
- closedIssues: issues(states: CLOSED) {
- totalCount
- }
- followers {
- totalCount
- }
- repositories(ownerAffiliations: OWNER) {
- totalCount
- }
- }
- }
- `,
+ query,
variables,
},
{
@@ -60,39 +89,42 @@ const fetcher = (variables, token) => {
};
/**
- * Fetch first 100 repositories for a given username.
+ * Fetch stats information for a given username.
*
- * @param {import('axios').AxiosRequestHeaders} variables Fetcher variables.
- * @param {string} token GitHub token.
- * @returns {Promise} Repositories fetcher response.
+ * @param {string} username Github username.
+ * @returns {Promise} GraphQL Stats object.
+ *
+ * @description This function supports multi-page fetching if the 'FETCH_MULTI_PAGE_STARS' environment variable is set to true.
*/
-const repositoriesFetcher = (variables, token) => {
- return request(
- {
- query: `
- query userInfo($login: String!, $after: String) {
- user(login: $login) {
- repositories(first: 100, ownerAffiliations: OWNER, orderBy: {direction: DESC, field: STARGAZERS}, after: $after) {
- nodes {
- name
- stargazers {
- totalCount
- }
- }
- pageInfo {
- hasNextPage
- endCursor
- }
- }
- }
- }
- `,
- variables,
- },
- {
- Authorization: `bearer ${token}`,
- },
- );
+const statsFetcher = async (username) => {
+ let stats;
+ let hasNextPage = true;
+ let endCursor = null;
+ while (hasNextPage) {
+ const variables = { login: username, first: 100, after: endCursor };
+ let res = await retryer(fetcher, variables);
+ if (res.data.errors) return res;
+
+ // Store stats data.
+ const repoNodes = res.data.data.user.repositories.nodes;
+ if (!stats) {
+ stats = res;
+ } else {
+ stats.data.data.user.repositories.nodes.push(...repoNodes);
+ }
+
+ // Disable multi page fetching on public Vercel instance due to rate limits.
+ const repoNodesWithStars = repoNodes.filter(
+ (node) => node.stargazers.totalCount !== 0,
+ );
+ hasNextPage =
+ process.env.FETCH_MULTI_PAGE_STARS === "true" &&
+ repoNodes.length === repoNodesWithStars.length &&
+ res.data.data.user.repositories.pageInfo.hasNextPage;
+ endCursor = res.data.data.user.repositories.pageInfo.endCursor;
+ }
+
+ return stats;
};
/**
@@ -137,46 +169,6 @@ const totalCommitsFetcher = async (username) => {
return 0;
};
-/**
- * Fetch all the stars for all the repositories of a given username.
- *
- * @param {string} username GitHub username.
- * @param {array} repoToHide Repositories to hide.
- * @returns {Promise} Total stars.
- */
-const totalStarsFetcher = async (username, repoToHide) => {
- let nodes = [];
- let hasNextPage = true;
- let endCursor = null;
- while (hasNextPage) {
- const variables = { login: username, first: 100, after: endCursor };
- let res = await retryer(repositoriesFetcher, variables);
-
- if (res.data.errors) {
- logger.error(res.data.errors);
- throw new CustomError(
- res.data.errors[0].message || "Could not fetch user",
- CustomError.USER_NOT_FOUND,
- );
- }
-
- const allNodes = res.data.data.user.repositories.nodes;
- const nodesWithStars = allNodes.filter(
- (node) => node.stargazers.totalCount !== 0,
- );
- nodes.push(...nodesWithStars);
- // hasNextPage =
- // allNodes.length === nodesWithStars.length &&
- // res.data.data.user.repositories.pageInfo.hasNextPage;
- hasNextPage = false; // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
- endCursor = res.data.data.user.repositories.pageInfo.endCursor;
- }
-
- return nodes
- .filter((data) => !repoToHide[data.name])
- .reduce((prev, curr) => prev + curr.stargazers.totalCount, 0);
-};
-
/**
* Fetch stats for a given username.
*
@@ -203,7 +195,7 @@ const fetchStats = async (
rank: { level: "C", score: 0 },
};
- let res = await retryer(fetcher, { login: username });
+ let res = await statsFetcher(username);
// Catch GraphQL errors.
if (res.data.errors) {
@@ -259,8 +251,15 @@ const fetchStats = async (
stats.contributedTo = user.repositoriesContributedTo.totalCount;
// Retrieve stars while filtering out repositories to be hidden
- stats.totalStars = await totalStarsFetcher(username, repoToHide);
+ stats.totalStars = user.repositories.nodes
+ .filter((data) => {
+ return !repoToHide[data.name];
+ })
+ .reduce((prev, curr) => {
+ return prev + curr.stargazers.totalCount;
+ }, 0);
+ // @ts-ignore // TODO: Fix this.
stats.rank = calculateRank({
totalCommits: stats.totalCommits,
totalRepos: user.repositories.totalCount,
diff --git a/tests/api.test.js b/tests/api.test.js
index 0037bcdb566b2..461f3e18abb6d 100644
--- a/tests/api.test.js
+++ b/tests/api.test.js
@@ -25,7 +25,7 @@ stats.rank = calculateRank({
issues: stats.totalIssues,
});
-const data = {
+const data_stats = {
data: {
user: {
name: stats.name,
@@ -40,15 +40,6 @@ const data = {
followers: { totalCount: 0 },
repositories: {
totalCount: 1,
- },
- },
- },
-};
-
-const repositoriesData = {
- data: {
- user: {
- repositories: {
nodes: [{ stargazers: { totalCount: 100 } }],
pageInfo: {
hasNextPage: false,
@@ -83,11 +74,7 @@ const faker = (query, data) => {
setHeader: jest.fn(),
send: jest.fn(),
};
- mock
- .onPost("https://api.github.com/graphql")
- .replyOnce(200, data)
- .onPost("https://api.github.com/graphql")
- .replyOnce(200, repositoriesData);
+ mock.onPost("https://api.github.com/graphql").replyOnce(200, data);
return { req, res };
};
@@ -98,7 +85,7 @@ afterEach(() => {
describe("Test /api/", () => {
it("should test the request", async () => {
- const { req, res } = faker({}, data);
+ const { req, res } = faker({}, data_stats);
await api(req, res);
@@ -133,7 +120,7 @@ describe("Test /api/", () => {
text_color: "fff",
bg_color: "fff",
},
- data,
+ data_stats,
);
await api(req, res);
@@ -154,7 +141,7 @@ describe("Test /api/", () => {
});
it("should have proper cache", async () => {
- const { req, res } = faker({}, data);
+ const { req, res } = faker({}, data_stats);
await api(req, res);
@@ -170,7 +157,7 @@ describe("Test /api/", () => {
});
it("should set proper cache", async () => {
- const { req, res } = faker({ cache_seconds: 15000 }, data);
+ const { req, res } = faker({ cache_seconds: 15000 }, data_stats);
await api(req, res);
expect(res.setHeader.mock.calls).toEqual([
@@ -196,7 +183,7 @@ describe("Test /api/", () => {
it("should set proper cache with clamped values", async () => {
{
- let { req, res } = faker({ cache_seconds: 200000 }, data);
+ let { req, res } = faker({ cache_seconds: 200000 }, data_stats);
await api(req, res);
expect(res.setHeader.mock.calls).toEqual([
@@ -212,7 +199,7 @@ describe("Test /api/", () => {
// note i'm using block scoped vars
{
- let { req, res } = faker({ cache_seconds: 0 }, data);
+ let { req, res } = faker({ cache_seconds: 0 }, data_stats);
await api(req, res);
expect(res.setHeader.mock.calls).toEqual([
@@ -227,7 +214,7 @@ describe("Test /api/", () => {
}
{
- let { req, res } = faker({ cache_seconds: -10000 }, data);
+ let { req, res } = faker({ cache_seconds: -10000 }, data_stats);
await api(req, res);
expect(res.setHeader.mock.calls).toEqual([
@@ -248,7 +235,7 @@ describe("Test /api/", () => {
username: "anuraghazra",
count_private: true,
},
- data,
+ data_stats,
);
await api(req, res);
@@ -288,7 +275,7 @@ describe("Test /api/", () => {
text_color: "fff",
bg_color: "fff",
},
- data,
+ data_stats,
);
await api(req, res);
diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js
index 192146ea5fbe0..04e943a75b50a 100644
--- a/tests/fetchStats.test.js
+++ b/tests/fetchStats.test.js
@@ -4,7 +4,8 @@ import MockAdapter from "axios-mock-adapter";
import { calculateRank } from "../src/calculateRank.js";
import { fetchStats } from "../src/fetchers/stats-fetcher.js";
-const data = {
+// Test parameters.
+const data_stats = {
data: {
user: {
name: "Anurag Hazra",
@@ -19,15 +20,6 @@ const data = {
followers: { totalCount: 100 },
repositories: {
totalCount: 5,
- },
- },
- },
-};
-
-const firstRepositoriesData = {
- data: {
- user: {
- repositories: {
nodes: [
{ name: "test-repo-1", stargazers: { totalCount: 100 } },
{ name: "test-repo-2", stargazers: { totalCount: 100 } },
@@ -42,7 +34,7 @@ const firstRepositoriesData = {
},
};
-const secondRepositoriesData = {
+const data_repo = {
data: {
user: {
repositories: {
@@ -59,7 +51,7 @@ const secondRepositoriesData = {
},
};
-const repositoriesWithZeroStarsData = {
+const data_repo_zero_stars = {
data: {
user: {
repositories: {
@@ -93,13 +85,12 @@ const error = {
const mock = new MockAdapter(axios);
beforeEach(() => {
+ process.env.FETCH_MULTI_PAGE_STARS = "false"; // Set to `false` to fetch only one page of stars.
mock
.onPost("https://api.github.com/graphql")
- .replyOnce(200, data)
+ .replyOnce(200, data_stats)
.onPost("https://api.github.com/graphql")
- .replyOnce(200, firstRepositoriesData);
- // .onPost("https://api.github.com/graphql") // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
- // .replyOnce(200, secondRepositoriesData); // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
+ .replyOnce(200, data_repo);
});
afterEach(() => {
@@ -114,8 +105,7 @@ describe("Test fetchStats", () => {
totalRepos: 5,
followers: 100,
contributions: 61,
- // stargazers: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
- stargazers: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
+ stargazers: 300,
prs: 300,
issues: 200,
});
@@ -126,8 +116,7 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
- // totalStars: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
- totalStars: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
+ totalStars: 300,
rank,
});
});
@@ -136,9 +125,9 @@ describe("Test fetchStats", () => {
mock.reset();
mock
.onPost("https://api.github.com/graphql")
- .replyOnce(200, data)
+ .replyOnce(200, data_stats)
.onPost("https://api.github.com/graphql")
- .replyOnce(200, repositoriesWithZeroStarsData);
+ .replyOnce(200, data_repo_zero_stars);
let stats = await fetchStats("anuraghazra");
const rank = calculateRank({
@@ -178,8 +167,7 @@ describe("Test fetchStats", () => {
totalRepos: 5,
followers: 100,
contributions: 61,
- // stargazers: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
- stargazers: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
+ stargazers: 300,
prs: 300,
issues: 200,
});
@@ -190,8 +178,7 @@ describe("Test fetchStats", () => {
totalCommits: 150,
totalIssues: 200,
totalPRs: 300,
- // totalStars: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
- totalStars: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
+ totalStars: 300,
rank,
});
});
@@ -207,8 +194,7 @@ describe("Test fetchStats", () => {
totalRepos: 5,
followers: 100,
contributions: 61,
- // stargazers: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
- stargazers: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
+ stargazers: 300,
prs: 300,
issues: 200,
});
@@ -219,8 +205,7 @@ describe("Test fetchStats", () => {
totalCommits: 1050,
totalIssues: 200,
totalPRs: 300,
- // totalStars: 400, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
- totalStars: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
+ totalStars: 300,
rank,
});
});
@@ -236,8 +221,7 @@ describe("Test fetchStats", () => {
totalRepos: 5,
followers: 100,
contributions: 61,
- // stargazers: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
- stargazers: 200, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
+ stargazers: 200,
prs: 300,
issues: 200,
});
@@ -248,8 +232,82 @@ describe("Test fetchStats", () => {
totalCommits: 1050,
totalIssues: 200,
totalPRs: 300,
- // totalStars: 300, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
- totalStars: 200, // NOTE: Temporarily disable fetching of multiple pages. Done because of #2130.
+ totalStars: 200,
+ rank,
+ });
+ });
+
+ it("should fetch two pages of stars if 'FETCH_MULTI_PAGE_STARS' env variable is set to `true`", async () => {
+ process.env.FETCH_MULTI_PAGE_STARS = true;
+
+ let stats = await fetchStats("anuraghazra");
+ const rank = calculateRank({
+ totalCommits: 100,
+ totalRepos: 5,
+ followers: 100,
+ contributions: 61,
+ stargazers: 400,
+ prs: 300,
+ issues: 200,
+ });
+
+ expect(stats).toStrictEqual({
+ contributedTo: 61,
+ name: "Anurag Hazra",
+ totalCommits: 100,
+ totalIssues: 200,
+ totalPRs: 300,
+ totalStars: 400,
+ rank,
+ });
+ });
+
+ it("should fetch one page of stars if 'FETCH_MULTI_PAGE_STARS' env variable is set to `false`", async () => {
+ process.env.FETCH_MULTI_PAGE_STARS = "false";
+
+ let stats = await fetchStats("anuraghazra");
+ const rank = calculateRank({
+ totalCommits: 100,
+ totalRepos: 5,
+ followers: 100,
+ contributions: 61,
+ stargazers: 300,
+ prs: 300,
+ issues: 200,
+ });
+
+ expect(stats).toStrictEqual({
+ contributedTo: 61,
+ name: "Anurag Hazra",
+ totalCommits: 100,
+ totalIssues: 200,
+ totalPRs: 300,
+ totalStars: 300,
+ rank,
+ });
+ });
+
+ it("should fetch one page of stars if 'FETCH_MULTI_PAGE_STARS' env variable is not set", async () => {
+ process.env.FETCH_MULTI_PAGE_STARS = undefined;
+
+ let stats = await fetchStats("anuraghazra");
+ const rank = calculateRank({
+ totalCommits: 100,
+ totalRepos: 5,
+ followers: 100,
+ contributions: 61,
+ stargazers: 300,
+ prs: 300,
+ issues: 200,
+ });
+
+ expect(stats).toStrictEqual({
+ contributedTo: 61,
+ name: "Anurag Hazra",
+ totalCommits: 100,
+ totalIssues: 200,
+ totalPRs: 300,
+ totalStars: 300,
rank,
});
});
From a17fa1cf5de746f54aadbfea0682a0c58beb4941 Mon Sep 17 00:00:00 2001
From: Anurag Hazra
Date: Sun, 22 Jan 2023 00:39:36 +0530
Subject: [PATCH 147/905] chore: resolve conflict (#2453)
* test: fix e2e tests
* test: update snapshots
* test: fix e2e test data
* test: update e2e test data
Co-authored-by: rickstaa
From b2bf4fa4878b585637a7f47d92cb10c62b4d1b06 Mon Sep 17 00:00:00 2001
From: Zohan Subhash
Date: Tue, 24 Jan 2023 20:04:26 +0530
Subject: [PATCH 148/905] fix: change prod deployment branch to vercel branch
to fix maxDuration bug (#2424)
* Create deploy-prep.yml
* Create deploy-prep.py
* Update vercel.json
* Update deploy-prep.yml
* Update vercel.json
* Added coauthor
Co-authored-by: Dou Xiaobo <93511091+douxiaobo@users.noreply.github.com>
* Update deploy-prep.yml
* refactor: format code
* Added if condition to disable deployments on forks
Co-authored-by: Rick Staa
* Update deploy-prep.yml
Co-authored-by: Dou Xiaobo <93511091+douxiaobo@users.noreply.github.com>
Co-authored-by: Anurag Hazra
Co-authored-by: rickstaa
---
.github/workflows/deploy-prep.py | 10 ++++++++++
.github/workflows/deploy-prep.yml | 20 ++++++++++++++++++++
vercel.json | 2 +-
3 files changed, 31 insertions(+), 1 deletion(-)
create mode 100644 .github/workflows/deploy-prep.py
create mode 100644 .github/workflows/deploy-prep.yml
diff --git a/.github/workflows/deploy-prep.py b/.github/workflows/deploy-prep.py
new file mode 100644
index 0000000000000..794c19a296122
--- /dev/null
+++ b/.github/workflows/deploy-prep.py
@@ -0,0 +1,10 @@
+import os
+
+file = open('./vercel.json', 'r')
+str = file.read()
+file = open('./vercel.json', 'w')
+
+str = str.replace('"maxDuration": 10', '"maxDuration": 30')
+
+file.write(str)
+file.close()
diff --git a/.github/workflows/deploy-prep.yml b/.github/workflows/deploy-prep.yml
new file mode 100644
index 0000000000000..0626e13d575a7
--- /dev/null
+++ b/.github/workflows/deploy-prep.yml
@@ -0,0 +1,20 @@
+name: Deployment Prep
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - master
+
+jobs:
+ config:
+ if: github.repository == 'anuraghazra/github-readme-stats'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Deployment Prep
+ run: python ./.github/workflows/deploy-prep.py
+ - uses: stefanzweifel/git-auto-commit-action@v4
+ with:
+ branch: vercel
+ create_branch: true
+ push_options: "--force"
diff --git a/vercel.json b/vercel.json
index aee61ce054fd0..ddf82eb15666f 100644
--- a/vercel.json
+++ b/vercel.json
@@ -2,7 +2,7 @@
"functions": {
"api/*.js": {
"memory": 128,
- "maxDuration": 30
+ "maxDuration": 10
}
},
"redirects": [
From cd5cbcdb095d766f5dbab2b8b13ed3b38cab7b2a Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Tue, 24 Jan 2023 15:40:11 +0100
Subject: [PATCH 149/905] fix: fixes card overflow problem #2452 (#2460)
This commit makes sure that the card width is formatted correctly.
---
src/cards/stats-card.js | 36 ++++++++++++++++++++++++-----------
tests/renderStatsCard.test.js | 20 +++++++++++--------
2 files changed, 37 insertions(+), 19 deletions(-)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index a049ecce1c7e3..f39a968f18065 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -12,6 +12,11 @@ import {
import { getStyles } from "../getStyles.js";
import { statCardLocales } from "../translations.js";
+const CARD_MIN_WIDTH = 287;
+const CARD_DEFAULT_WIDTH = 287;
+const RANK_CARD_MIN_WIDTH = 420;
+const RANK_CARD_DEFAULT_WIDTH = 450;
+
/**
* Create a stats card text item.
*
@@ -218,11 +223,17 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
When hide_rank=false, the minimum card_width is 340 px + the icon width (if show_icons=true).
Numbers are picked by looking at existing dimensions on production.
*/
- const iconWidth = show_icons ? 16 : 0;
- const minCardWidth = hide_rank
- ? clampValue(50 /* padding */ + calculateTextWidth() * 2, 270, Infinity)
- : 340 + iconWidth;
- const defaultCardWidth = hide_rank ? 270 : 495;
+ const iconWidth = show_icons ? 16 + /* padding */ 1 : 0;
+ const minCardWidth =
+ (hide_rank
+ ? clampValue(
+ 50 /* padding */ + calculateTextWidth() * 2,
+ CARD_MIN_WIDTH,
+ Infinity,
+ )
+ : RANK_CARD_MIN_WIDTH) + iconWidth;
+ const defaultCardWidth =
+ (hide_rank ? CARD_DEFAULT_WIDTH : RANK_CARD_DEFAULT_WIDTH) + iconWidth;
let width = isNaN(card_width) ? defaultCardWidth : card_width;
if (width < minCardWidth) {
width = minCardWidth;
@@ -251,18 +262,21 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
/**
* Calculates the right rank circle translation values such that the rank circle
- * keeps respecting the padding.
+ * keeps respecting the following padding:
*
- * width > 450: The default left padding of 50 px will be used.
- * width < 450: The left and right padding will shrink equally.
+ * width > RANK_CARD_DEFAULT_WIDTH: The default right padding of 70 px will be used.
+ * width < RANK_CARD_DEFAULT_WIDTH: The left and right padding will be enlarged
+ * equally from a certain minimum at RANK_CARD_MIN_WIDTH.
*
* @returns {number} - Rank circle translation value.
*/
const calculateRankXTranslation = () => {
- if (width < 450) {
- return width - 95 + (45 * (450 - 340)) / 110;
+ const minXTranslation = RANK_CARD_MIN_WIDTH + iconWidth - 70;
+ if (width > RANK_CARD_DEFAULT_WIDTH) {
+ const xMaxExpansion = minXTranslation + (450 - minCardWidth) / 2;
+ return xMaxExpansion + width - RANK_CARD_DEFAULT_WIDTH;
} else {
- return width - 95;
+ return minXTranslation + (width - minCardWidth) / 2;
}
};
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 5afb1f0218e5d..748b7a32cd32b 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -78,16 +78,17 @@ describe("Test renderStatsCard", () => {
it("should render with custom width set", () => {
document.body.innerHTML = renderStatsCard(stats);
- expect(document.querySelector("svg")).toHaveAttribute("width", "495");
+ expect(document.querySelector("svg")).toHaveAttribute("width", "450");
- document.body.innerHTML = renderStatsCard(stats, { card_width: 400 });
- expect(document.querySelector("svg")).toHaveAttribute("width", "400");
+ document.body.innerHTML = renderStatsCard(stats, { card_width: 500 });
+ expect(document.querySelector("svg")).toHaveAttribute("width", "500");
});
it("should render with custom width set and limit minimum width", () => {
document.body.innerHTML = renderStatsCard(stats, { card_width: 1 });
- expect(document.querySelector("svg")).toHaveAttribute("width", "340");
+ expect(document.querySelector("svg")).toHaveAttribute("width", "420");
+ // Test default minimum card width without rank circle.
document.body.innerHTML = renderStatsCard(stats, {
card_width: 1,
hide_rank: true,
@@ -97,6 +98,7 @@ describe("Test renderStatsCard", () => {
"305.81250000000006",
);
+ // Test minimum card width with rank and icons.
document.body.innerHTML = renderStatsCard(stats, {
card_width: 1,
hide_rank: true,
@@ -104,22 +106,24 @@ describe("Test renderStatsCard", () => {
});
expect(document.querySelector("svg")).toHaveAttribute(
"width",
- "305.81250000000006",
+ "322.81250000000006",
);
+ // Test minimum card width with icons but without rank.
document.body.innerHTML = renderStatsCard(stats, {
card_width: 1,
hide_rank: false,
show_icons: true,
});
- expect(document.querySelector("svg")).toHaveAttribute("width", "356");
+ expect(document.querySelector("svg")).toHaveAttribute("width", "437");
+ // Test minimum card width without icons or rank.
document.body.innerHTML = renderStatsCard(stats, {
card_width: 1,
hide_rank: false,
show_icons: false,
});
- expect(document.querySelector("svg")).toHaveAttribute("width", "340");
+ expect(document.querySelector("svg")).toHaveAttribute("width", "420");
});
it("should render default colors properly", () => {
@@ -312,7 +316,7 @@ describe("Test renderStatsCard", () => {
expect(
document.body.getElementsByTagName("svg")[0].getAttribute("width"),
- ).toBe("270");
+ ).toBe("287");
});
it("should render translations", () => {
From 99d9d3cde0e4f306704a9680738f79002328319c Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Wed, 25 Jan 2023 09:20:36 +0100
Subject: [PATCH 150/905] ci: prevent certain actions from running on forks
(#2466)
---
.github/workflows/e2e-test.yml | 1 +
.github/workflows/empty-issues-closer.yaml | 1 +
.github/workflows/label-pr.yml | 1 +
.github/workflows/stale-theme-pr-closer.yaml | 1 +
.github/workflows/top-issues-dashboard.yml | 1 +
5 files changed, 5 insertions(+)
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index b9d275f5d5828..d45c76ba08e58 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -5,6 +5,7 @@ on:
jobs:
e2eTests:
if:
+ github.repository == 'anuraghazra/github-readme-stats' &&
github.event_name == 'deployment_status' &&
github.event.deployment_status.state == 'success'
name: Perform 2e2 tests
diff --git a/.github/workflows/empty-issues-closer.yaml b/.github/workflows/empty-issues-closer.yaml
index b20eef32fefb8..a65ea63b12dd3 100644
--- a/.github/workflows/empty-issues-closer.yaml
+++ b/.github/workflows/empty-issues-closer.yaml
@@ -8,6 +8,7 @@ on:
jobs:
closeEmptyIssuesAndTemplates:
+ if: github.repository == 'anuraghazra/github-readme-stats'
name: Close empty issues
runs-on: ubuntu-latest
steps:
diff --git a/.github/workflows/label-pr.yml b/.github/workflows/label-pr.yml
index c401d32ee4b9c..03715bfab00d6 100644
--- a/.github/workflows/label-pr.yml
+++ b/.github/workflows/label-pr.yml
@@ -4,6 +4,7 @@ on:
jobs:
triage:
+ if: github.repository == 'anuraghazra/github-readme-stats'
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
diff --git a/.github/workflows/stale-theme-pr-closer.yaml b/.github/workflows/stale-theme-pr-closer.yaml
index 9a6249825263e..aa104feb528ca 100644
--- a/.github/workflows/stale-theme-pr-closer.yaml
+++ b/.github/workflows/stale-theme-pr-closer.yaml
@@ -5,6 +5,7 @@ on:
jobs:
closeOldThemePrs:
+ if: github.repository == 'anuraghazra/github-readme-stats'
name: Close stale 'invalid' theme PRs
runs-on: ubuntu-latest
strategy:
diff --git a/.github/workflows/top-issues-dashboard.yml b/.github/workflows/top-issues-dashboard.yml
index 2b36e529de454..3a9ec82d35149 100644
--- a/.github/workflows/top-issues-dashboard.yml
+++ b/.github/workflows/top-issues-dashboard.yml
@@ -5,6 +5,7 @@ on:
jobs:
showAndLabelTopIssues:
+ if: github.repository == 'anuraghazra/github-readme-stats'
name: Update top issues Dashboard.
runs-on: ubuntu-latest
steps:
From 077d40561a4eb74ab56a81942155985a7579103a Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sat, 28 Jan 2023 15:22:02 +0100
Subject: [PATCH 151/905] feat: add PAT monitoring functions (#2178)
* feat: add PAT monitoring functions
This commit adds two monitoring functions that can be used to check
whether the PATs are functioning correctly:
- status/up: Returns whether the PATs are rate limited.
- status/pat-info: Returns information about the PATs.
* feat: add shields.io dynamic badge json response
This commit adds the ability to set the return format of the
`/api/status/up` cloud function. When this format is set to `shields` a
dynamic shields.io badge json is returned.
* feat: add 'json' type to up monitor
* feat: cleanup status functions
* ci: decrease pat-info rate limiting time
* feat: decrease monitoring functions rate limits
* refactor: pat code
* feat: add PAT monitoring functions
This commit adds two monitoring functions that can be used to check
whether the PATs are functioning correctly:
- status/up: Returns whether the PATs are rate limited.
- status/pat-info: Returns information about the PATs.
* feat: add shields.io dynamic badge json response
This commit adds the ability to set the return format of the
`/api/status/up` cloud function. When this format is set to `shields` a
dynamic shields.io badge json is returned.
* feat: add 'json' type to up monitor
* feat: cleanup status functions
* ci: decrease pat-info rate limiting time
* feat: decrease monitoring functions rate limits
* refactor: pat code
* test: fix pat-info tests
* Update api/status/pat-info.js
Co-authored-by: Anurag Hazra
* test: fix broken tests
* chore: fix suspended account
* chore: simplify and refactor
* chore: fix test
* chore: add resetIn field
---------
Co-authored-by: Anurag
---
api/status/pat-info.js | 131 ++++++++++++++++++++++
api/status/up.js | 103 +++++++++++++++++
package-lock.json | 2 +-
package.json | 2 +-
src/common/utils.js | 14 +++
tests/pat-info.test.js | 241 ++++++++++++++++++++++++++++++++++++++++
tests/status.up.test.js | 194 ++++++++++++++++++++++++++++++++
7 files changed, 685 insertions(+), 2 deletions(-)
create mode 100644 api/status/pat-info.js
create mode 100644 api/status/up.js
create mode 100644 tests/pat-info.test.js
create mode 100644 tests/status.up.test.js
diff --git a/api/status/pat-info.js b/api/status/pat-info.js
new file mode 100644
index 0000000000000..720611d424919
--- /dev/null
+++ b/api/status/pat-info.js
@@ -0,0 +1,131 @@
+/**
+ * @file Contains a simple cloud function that can be used to check which PATs are no
+ * longer working. It returns a list of valid PATs, expired PATs and PATs with errors.
+ *
+ * @description This function is currently rate limited to 1 request per 10 minutes.
+ */
+
+import { logger, request, dateDiff } from "../../src/common/utils.js";
+export const RATE_LIMIT_SECONDS = 60 * 10; // 1 request per 10 minutes
+
+/**
+ * Simple uptime check fetcher for the PATs.
+ *
+ * @param {import('axios').AxiosRequestHeaders} variables
+ * @param {string} token
+ */
+const uptimeFetcher = (variables, token) => {
+ return request(
+ {
+ query: `
+ query {
+ rateLimit {
+ remaining
+ resetAt
+ },
+ }`,
+ variables,
+ },
+ {
+ Authorization: `bearer ${token}`,
+ },
+ );
+};
+
+const getAllPATs = () => {
+ return Object.keys(process.env).filter((key) => /PAT_\d*$/.exec(key));
+};
+
+/**
+ * Check whether any of the PATs is expired.
+ */
+const getPATInfo = async (fetcher, variables) => {
+ const details = {};
+ const PATs = getAllPATs();
+
+ for (const pat of PATs) {
+ try {
+ const response = await fetcher(variables, process.env[pat]);
+ const errors = response.data.errors;
+ const hasErrors = Boolean(errors);
+ const errorType = errors?.[0]?.type;
+ const isRateLimited =
+ (hasErrors && errorType === "RATE_LIMITED") ||
+ response.data.data?.rateLimit?.remaining === 0;
+
+ // Store PATs with errors.
+ if (hasErrors && errorType !== "RATE_LIMITED") {
+ details[pat] = {
+ status: "error",
+ error: {
+ type: errors[0].type,
+ message: errors[0].message,
+ },
+ };
+ continue;
+ } else if (isRateLimited) {
+ const date1 = new Date();
+ const date2 = new Date(response.data?.data?.rateLimit?.resetAt);
+ details[pat] = {
+ status: "exhausted",
+ remaining: 0,
+ resetIn: dateDiff(date2, date1) + " minutes",
+ };
+ } else {
+ details[pat] = {
+ status: "valid",
+ remaining: response.data.data.rateLimit.remaining,
+ };
+ }
+ } catch (err) {
+ // Store the PAT if it is expired.
+ const errorMessage = err.response?.data?.message?.toLowerCase();
+ if (errorMessage === "bad credentials") {
+ details[pat] = {
+ status: "expired",
+ };
+ } else if (errorMessage === "sorry. your account was suspended.") {
+ details[pat] = {
+ status: "suspended",
+ };
+ } else {
+ throw err;
+ }
+ }
+ }
+
+ const filterPATsByStatus = (status) => {
+ return Object.keys(details).filter((pat) => details[pat].status === status);
+ };
+
+ return {
+ validPATs: filterPATsByStatus("valid"),
+ expiredPATs: filterPATsByStatus("expired"),
+ exhaustedPATS: filterPATsByStatus("exhausted"),
+ errorPATs: filterPATsByStatus("error"),
+ details,
+ };
+};
+
+/**
+ * Cloud function that returns information about the used PATs.
+ */
+export default async (_, res) => {
+ res.setHeader("Content-Type", "application/json");
+ try {
+ // Add header to prevent abuse.
+ const PATsInfo = await getPATInfo(uptimeFetcher, {});
+ if (PATsInfo) {
+ res.setHeader(
+ "Cache-Control",
+ `max-age=0, s-maxage=${RATE_LIMIT_SECONDS}`,
+ );
+ }
+ res.send(JSON.stringify(PATsInfo, null, 2));
+ } catch (err) {
+ // Throw error if something went wrong.
+ logger.error(err);
+ res.setHeader("Cache-Control", "no-store");
+ res.send("Something went wrong: " + err.message);
+ }
+};
diff --git a/api/status/up.js b/api/status/up.js
new file mode 100644
index 0000000000000..33fe8f900c395
--- /dev/null
+++ b/api/status/up.js
@@ -0,0 +1,103 @@
+/**
+ * @file Contains a simple cloud function that can be used to check if the PATs are still
+ * functional.
+ *
+ * @description This function is currently rate limited to 1 request per 10 minutes.
+ */
+
+import retryer from "../../src/common/retryer.js";
+import { logger, request } from "../../src/common/utils.js";
+
+export const RATE_LIMIT_SECONDS = 60 * 10; // 1 request per 10 minutes
+
+/**
+ * Simple uptime check fetcher for the PATs.
+ *
+ * @param {import('axios').AxiosRequestHeaders} variables
+ * @param {string} token
+ */
+const uptimeFetcher = (variables, token) => {
+ return request(
+ {
+ query: `
+ query {
+ rateLimit {
+ remaining
+ }
+ }
+ `,
+ variables,
+ },
+ {
+ Authorization: `bearer ${token}`,
+ },
+ );
+};
+
+/**
+ * Creates Json response that can be used for shields.io dynamic card generation.
+ *
+ * @param {*} up Whether the PATs are up or not.
+ * @returns Dynamic shields.io JSON response object.
+ *
+ * @see https://shields.io/endpoint.
+ */
+const shieldsUptimeBadge = (up) => {
+ const schemaVersion = 1;
+ const isError = true;
+ const label = "Public Instance";
+ const message = up ? "up" : "down";
+ const color = up ? "brightgreen" : "red";
+ return {
+ schemaVersion,
+ label,
+ message,
+ color,
+ isError,
+ };
+};
+
+/**
+ * Cloud function that returns whether the PATs are still functional.
+ */
+export default async (req, res) => {
+ let { type } = req.query;
+ type = type ? type.toLowerCase() : "boolean";
+
+ res.setHeader("Content-Type", "application/json");
+
+ try {
+ let PATsValid = true;
+ try {
+ await retryer(uptimeFetcher, {});
+ } catch (err) {
+ PATsValid = false;
+ }
+
+ if (PATsValid) {
+ res.setHeader(
+ "Cache-Control",
+ `max-age=0, s-maxage=${RATE_LIMIT_SECONDS}`,
+ );
+ } else {
+ res.setHeader("Cache-Control", "no-store");
+ }
+
+ switch (type) {
+ case "shields":
+ res.send(shieldsUptimeBadge(PATsValid));
+ break;
+ case "json":
+ res.send({ up: PATsValid });
+ break;
+ default:
+ res.send(PATsValid);
+ break;
+ }
+ } catch (err) {
+ // Return fail boolean if something went wrong.
+ logger.error(err);
+ res.setHeader("Cache-Control", "no-store");
+ res.send("Something went wrong: " + err.message);
+ }
+};
diff --git a/package-lock.json b/package-lock.json
index 048c316bfde58..ebc7570a41923 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,7 +22,7 @@
"@testing-library/dom": "^8.17.1",
"@testing-library/jest-dom": "^5.16.5",
"@uppercod/css-to-object": "^1.1.1",
- "axios-mock-adapter": "^1.18.1",
+ "axios-mock-adapter": "^1.21.2",
"color-contrast-checker": "^2.1.0",
"hjson": "^3.2.2",
"husky": "^8.0.0",
diff --git a/package.json b/package.json
index 95b1a11dad93f..606d4f5440a24 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,7 @@
"@testing-library/dom": "^8.17.1",
"@testing-library/jest-dom": "^5.16.5",
"@uppercod/css-to-object": "^1.1.1",
- "axios-mock-adapter": "^1.18.1",
+ "axios-mock-adapter": "^1.21.2",
"color-contrast-checker": "^2.1.0",
"hjson": "^3.2.2",
"husky": "^8.0.0",
diff --git a/src/common/utils.js b/src/common/utils.js
index 1215fc9ac8cc2..c600c717ae3e5 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -424,6 +424,19 @@ const parseEmojis = (str) => {
});
};
+/**
+ * Get diff in minutes
+ * @param {Date} d1
+ * @param {Date} d2
+ * @returns {number}
+ */
+const dateDiff = (d1, d2) => {
+ const date1 = new Date(d1);
+ const date2 = new Date(d2);
+ const diff = date1.getTime() - date2.getTime();
+ return Math.round(diff / (1000 * 60));
+};
+
export {
ERROR_CARD_LENGTH,
renderError,
@@ -447,4 +460,5 @@ export {
lowercaseTrim,
chunkArray,
parseEmojis,
+ dateDiff,
};
diff --git a/tests/pat-info.test.js b/tests/pat-info.test.js
new file mode 100644
index 0000000000000..9635ab24c837c
--- /dev/null
+++ b/tests/pat-info.test.js
@@ -0,0 +1,241 @@
+/**
+ * @file Tests for the status/pat-info cloud function.
+ */
+import dotenv from "dotenv";
+dotenv.config();
+
+import { jest } from "@jest/globals";
+import axios from "axios";
+import MockAdapter from "axios-mock-adapter";
+import patInfo, { RATE_LIMIT_SECONDS } from "../api/status/pat-info.js";
+
+const mock = new MockAdapter(axios);
+
+const successData = {
+ data: {
+ rateLimit: {
+ remaining: 4986,
+ },
+ },
+};
+
+const faker = (query) => {
+ const req = {
+ query: { ...query },
+ };
+ const res = {
+ setHeader: jest.fn(),
+ send: jest.fn(),
+ };
+
+ return { req, res };
+};
+
+const rate_limit_error = {
+ errors: [
+ {
+ type: "RATE_LIMITED",
+ message: "API rate limit exceeded for user ID.",
+ },
+ ],
+ data: {
+ rateLimit: {
+ resetAt: Date.now(),
+ },
+ },
+};
+
+const other_error = {
+ errors: [
+ {
+ type: "SOME_ERROR",
+ message: "This is a error",
+ },
+ ],
+};
+
+const bad_credentials_error = {
+ message: "Bad credentials",
+};
+
+afterEach(() => {
+ mock.reset();
+});
+
+describe("Test /api/status/pat-info", () => {
+ beforeAll(() => {
+ // reset patenv first so that dotenv doesn't populate them with local envs
+ process.env = {};
+ process.env.PAT_1 = "testPAT1";
+ process.env.PAT_2 = "testPAT2";
+ process.env.PAT_3 = "testPAT3";
+ process.env.PAT_4 = "testPAT4";
+ });
+
+ it("should return only 'validPATs' if all PATs are valid", async () => {
+ mock
+ .onPost("https://api.github.com/graphql")
+ .replyOnce(200, rate_limit_error)
+ .onPost("https://api.github.com/graphql")
+ .reply(200, successData);
+
+ const { req, res } = faker({}, {});
+ await patInfo(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(
+ JSON.stringify(
+ {
+ validPATs: ["PAT_2", "PAT_3", "PAT_4"],
+ expiredPATs: [],
+ exhaustedPATS: ["PAT_1"],
+ errorPATs: [],
+ details: {
+ PAT_1: {
+ status: "exhausted",
+ remaining: 0,
+ resetIn: "0 minutes",
+ },
+ PAT_2: {
+ status: "valid",
+ remaining: 4986,
+ },
+ PAT_3: {
+ status: "valid",
+ remaining: 4986,
+ },
+ PAT_4: {
+ status: "valid",
+ remaining: 4986,
+ },
+ },
+ },
+ null,
+ 2,
+ ),
+ );
+ });
+
+ it("should return `errorPATs` if a PAT causes an error to be thrown", async () => {
+ mock
+ .onPost("https://api.github.com/graphql")
+ .replyOnce(200, other_error)
+ .onPost("https://api.github.com/graphql")
+ .reply(200, successData);
+
+ const { req, res } = faker({}, {});
+ await patInfo(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(
+ JSON.stringify(
+ {
+ validPATs: ["PAT_2", "PAT_3", "PAT_4"],
+ expiredPATs: [],
+ exhaustedPATS: [],
+ errorPATs: ["PAT_1"],
+ details: {
+ PAT_1: {
+ status: "error",
+ error: {
+ type: "SOME_ERROR",
+ message: "This is a error",
+ },
+ },
+ PAT_2: {
+ status: "valid",
+ remaining: 4986,
+ },
+ PAT_3: {
+ status: "valid",
+ remaining: 4986,
+ },
+ PAT_4: {
+ status: "valid",
+ remaining: 4986,
+ },
+ },
+ },
+ null,
+ 2,
+ ),
+ );
+ });
+
+ it("should return `expiredPaths` if a PAT returns a 'Bad credentials' error", async () => {
+ mock
+ .onPost("https://api.github.com/graphql")
+ .replyOnce(404, bad_credentials_error)
+ .onPost("https://api.github.com/graphql")
+ .reply(200, successData);
+
+ const { req, res } = faker({}, {});
+ await patInfo(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(
+ JSON.stringify(
+ {
+ validPATs: ["PAT_2", "PAT_3", "PAT_4"],
+ expiredPATs: ["PAT_1"],
+ exhaustedPATS: [],
+ errorPATs: [],
+ details: {
+ PAT_1: {
+ status: "expired",
+ },
+ PAT_2: {
+ status: "valid",
+ remaining: 4986,
+ },
+ PAT_3: {
+ status: "valid",
+ remaining: 4986,
+ },
+ PAT_4: {
+ status: "valid",
+ remaining: 4986,
+ },
+ },
+ },
+ null,
+ 2,
+ ),
+ );
+ });
+
+ it("should throw an error if something goes wrong", async () => {
+ mock.onPost("https://api.github.com/graphql").networkError();
+
+ const { req, res } = faker({}, {});
+ await patInfo(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith("Something went wrong: Network Error");
+ });
+
+ it("should have proper cache when no error is thrown", async () => {
+ mock.onPost("https://api.github.com/graphql").reply(200, successData);
+
+ const { req, res } = faker({}, {});
+ await patInfo(req, res);
+
+ expect(res.setHeader.mock.calls).toEqual([
+ ["Content-Type", "application/json"],
+ ["Cache-Control", `max-age=0, s-maxage=${RATE_LIMIT_SECONDS}`],
+ ]);
+ });
+
+ it("should have proper cache when error is thrown", async () => {
+ mock.reset();
+ mock.onPost("https://api.github.com/graphql").networkError();
+
+ const { req, res } = faker({}, {});
+ await patInfo(req, res);
+
+ expect(res.setHeader.mock.calls).toEqual([
+ ["Content-Type", "application/json"],
+ ["Cache-Control", "no-store"],
+ ]);
+ });
+});
diff --git a/tests/status.up.test.js b/tests/status.up.test.js
new file mode 100644
index 0000000000000..7cf0144b7112d
--- /dev/null
+++ b/tests/status.up.test.js
@@ -0,0 +1,194 @@
+/**
+ * @file Tests for the status/up cloud function.
+ */
+import { jest } from "@jest/globals";
+import axios from "axios";
+import MockAdapter from "axios-mock-adapter";
+import up, { RATE_LIMIT_SECONDS } from "../api/status/up.js";
+
+const mock = new MockAdapter(axios);
+
+const successData = {
+ rateLimit: {
+ remaining: 4986,
+ },
+};
+
+const faker = (query) => {
+ const req = {
+ query: { ...query },
+ };
+ const res = {
+ setHeader: jest.fn(),
+ send: jest.fn(),
+ };
+
+ return { req, res };
+};
+
+const rate_limit_error = {
+ errors: [
+ {
+ type: "RATE_LIMITED",
+ },
+ ],
+};
+
+const bad_credentials_error = {
+ message: "Bad credentials",
+};
+
+const shields_up = {
+ schemaVersion: 1,
+ label: "Public Instance",
+ isError: true,
+ message: "up",
+ color: "brightgreen",
+};
+const shields_down = {
+ schemaVersion: 1,
+ label: "Public Instance",
+ isError: true,
+ message: "down",
+ color: "red",
+};
+
+afterEach(() => {
+ mock.reset();
+});
+
+describe("Test /api/status/up", () => {
+ it("should return `true` if request was successful", async () => {
+ mock.onPost("https://api.github.com/graphql").replyOnce(200, successData);
+
+ const { req, res } = faker({}, {});
+ await up(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(true);
+ });
+
+ it("should return `false` if all PATs are rate limited", async () => {
+ mock.onPost("https://api.github.com/graphql").reply(200, rate_limit_error);
+
+ const { req, res } = faker({}, {});
+ await up(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(false);
+ });
+
+ it("should return JSON `true` if request was successful and type='json'", async () => {
+ mock.onPost("https://api.github.com/graphql").replyOnce(200, successData);
+
+ const { req, res } = faker({ type: "json" }, {});
+ await up(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith({ up: true });
+ });
+
+ it("should return JSON `false` if all PATs are rate limited and type='json'", async () => {
+ mock.onPost("https://api.github.com/graphql").reply(200, rate_limit_error);
+
+ const { req, res } = faker({ type: "json" }, {});
+ await up(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith({ up: false });
+ });
+
+ it("should return UP shields.io config if request was successful and type='shields'", async () => {
+ mock.onPost("https://api.github.com/graphql").replyOnce(200, successData);
+
+ const { req, res } = faker({ type: "shields" }, {});
+ await up(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(shields_up);
+ });
+
+ it("should return DOWN shields.io config if all PATs are rate limited and type='shields'", async () => {
+ mock.onPost("https://api.github.com/graphql").reply(200, rate_limit_error);
+
+ const { req, res } = faker({ type: "shields" }, {});
+ await up(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(shields_down);
+ });
+
+ it("should return `true` if the first PAT is rate limited but the second PATs works", async () => {
+ mock
+ .onPost("https://api.github.com/graphql")
+ .replyOnce(200, rate_limit_error)
+ .onPost("https://api.github.com/graphql")
+ .replyOnce(200, successData);
+
+ const { req, res } = faker({}, {});
+ await up(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(true);
+ });
+
+ it("should return `true` if the first PAT has 'Bad credentials' but the second PAT works", async () => {
+ mock
+ .onPost("https://api.github.com/graphql")
+ .replyOnce(404, bad_credentials_error)
+ .onPost("https://api.github.com/graphql")
+ .replyOnce(200, successData);
+
+ const { req, res } = faker({}, {});
+ await up(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(true);
+ });
+
+ it("should return `false` if all pats have 'Bad credentials'", async () => {
+ mock
+ .onPost("https://api.github.com/graphql")
+ .reply(404, bad_credentials_error);
+
+ const { req, res } = faker({}, {});
+ await up(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(false);
+ });
+
+ it("should throw an error if the request fails", async () => {
+ mock.onPost("https://api.github.com/graphql").networkError();
+
+ const { req, res } = faker({}, {});
+ await up(req, res);
+
+ expect(res.setHeader).toBeCalledWith("Content-Type", "application/json");
+ expect(res.send).toBeCalledWith(false);
+ });
+
+ it("should have proper cache when no error is thrown", async () => {
+ mock.onPost("https://api.github.com/graphql").replyOnce(200, successData);
+
+ const { req, res } = faker({}, {});
+ await up(req, res);
+
+ expect(res.setHeader.mock.calls).toEqual([
+ ["Content-Type", "application/json"],
+ ["Cache-Control", `max-age=0, s-maxage=${RATE_LIMIT_SECONDS}`],
+ ]);
+ });
+
+ it("should have proper cache when error is thrown", async () => {
+ mock.onPost("https://api.github.com/graphql").networkError();
+
+ const { req, res } = faker({}, {});
+ await up(req, res);
+
+ expect(res.setHeader.mock.calls).toEqual([
+ ["Content-Type", "application/json"],
+ ["Cache-Control", "no-store"],
+ ]);
+ });
+});
From 7aa502d45377c73f89c6d1096c29cd862188aa2e Mon Sep 17 00:00:00 2001
From: Anurag Hazra
Date: Sat, 28 Jan 2023 20:32:40 +0530
Subject: [PATCH 152/905] chore: minor changes in pat info (#2481)
---
api/status/pat-info.js | 14 +++++++++++---
tests/pat-info.test.js | 9 ++++++---
2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/api/status/pat-info.js b/api/status/pat-info.js
index 720611d424919..775e06896427c 100644
--- a/api/status/pat-info.js
+++ b/api/status/pat-info.js
@@ -6,7 +6,7 @@
*/
import { logger, request, dateDiff } from "../../src/common/utils.js";
-export const RATE_LIMIT_SECONDS = 60 * 10; // 1 request per 10 minutes
+export const RATE_LIMIT_SECONDS = 60 * 5; // 1 request per 10 minutes
/**
* Simple uptime check fetcher for the PATs.
@@ -98,12 +98,20 @@ const getPATInfo = async (fetcher, variables) => {
return Object.keys(details).filter((pat) => details[pat].status === status);
};
+ const sortedDetails = Object.keys(details)
+ .sort()
+ .reduce((obj, key) => {
+ obj[key] = details[key];
+ return obj;
+ }, {});
+
return {
validPATs: filterPATsByStatus("valid"),
expiredPATs: filterPATsByStatus("expired"),
- exhaustedPATS: filterPATsByStatus("exhausted"),
+ exhaustedPATs: filterPATsByStatus("exhausted"),
+ suspendedPATs: filterPATsByStatus("suspended"),
errorPATs: filterPATsByStatus("error"),
- details,
+ details: sortedDetails,
};
};
diff --git a/tests/pat-info.test.js b/tests/pat-info.test.js
index 9635ab24c837c..23aca8c40e5ca 100644
--- a/tests/pat-info.test.js
+++ b/tests/pat-info.test.js
@@ -88,7 +88,8 @@ describe("Test /api/status/pat-info", () => {
{
validPATs: ["PAT_2", "PAT_3", "PAT_4"],
expiredPATs: [],
- exhaustedPATS: ["PAT_1"],
+ exhaustedPATs: ["PAT_1"],
+ suspendedPATs: [],
errorPATs: [],
details: {
PAT_1: {
@@ -132,7 +133,8 @@ describe("Test /api/status/pat-info", () => {
{
validPATs: ["PAT_2", "PAT_3", "PAT_4"],
expiredPATs: [],
- exhaustedPATS: [],
+ exhaustedPATs: [],
+ suspendedPATs: [],
errorPATs: ["PAT_1"],
details: {
PAT_1: {
@@ -178,7 +180,8 @@ describe("Test /api/status/pat-info", () => {
{
validPATs: ["PAT_2", "PAT_3", "PAT_4"],
expiredPATs: ["PAT_1"],
- exhaustedPATS: [],
+ exhaustedPATs: [],
+ suspendedPATs: [],
errorPATs: [],
details: {
PAT_1: {
From 112000667c01f18fd161f204ae3ee796ec2e3011 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sun, 29 Jan 2023 15:19:01 +0100
Subject: [PATCH 153/905] ci: add update languages action (#2484)
* ci: add update languages action
* ci: make sure PR is created when upstream languages are updated
---
.github/workflows/update-langs.yaml | 44 +++++++++++++++++++++++++++++
src/common/languageColors.json | 18 ++++++++++++
2 files changed, 62 insertions(+)
create mode 100644 .github/workflows/update-langs.yaml
diff --git a/.github/workflows/update-langs.yaml b/.github/workflows/update-langs.yaml
new file mode 100644
index 0000000000000..ad6bfb6213b8f
--- /dev/null
+++ b/.github/workflows/update-langs.yaml
@@ -0,0 +1,44 @@
+name: Update supported languages
+on:
+ schedule:
+ - cron: "0 0 */30 * *"
+
+jobs:
+ updateLanguages:
+ if: github.repository == 'anuraghazra/github-readme-stats'
+ name: Update supported languages
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ node-version: [16.x]
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Setup Node
+ uses: actions/setup-node@v3
+ with:
+ node-version: ${{ matrix.node-version }}
+ cache: npm
+
+ - name: Install dependencies
+ run: npm ci
+ env:
+ CI: true
+
+ - name: Run update-languages-json.js script
+ run: npm run generate-langs-json
+
+ - name: Create Pull Request if upstream language file is changed
+ uses: peter-evans/create-pull-request@v4
+ with:
+ commit-message: "refactor: update languages JSON"
+ branch: "update_langs/patch"
+ delete-branch: true
+ title: Update languages JSON
+ body:
+ "The
+ [update-langs](https://github.com/anuraghazra/github-readme-stats/actions/workflows/update-langs.yaml)
+ action found new/updated languages in the [upstream languages JSON
+ file](https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml)."
+ labels: "ci, lang-card"
diff --git a/src/common/languageColors.json b/src/common/languageColors.json
index 7e8cd551264b8..47bfb1cfa3435 100644
--- a/src/common/languageColors.json
+++ b/src/common/languageColors.json
@@ -102,6 +102,7 @@
"Csound Score": "#1a1a1a",
"Cuda": "#3A4E3A",
"Curry": "#531242",
+ "Cypher": "#34c0eb",
"Cython": "#fedf5b",
"D": "#ba595e",
"DM": "#447265",
@@ -124,6 +125,7 @@
"Earthly": "#2af0ff",
"Easybuild": "#069406",
"Ecere Projects": "#913960",
+ "Ecmarkup": "#eb8131",
"EditorConfig": "#fff1f2",
"Eiffel": "#4d6977",
"Elixir": "#6e4a7e",
@@ -215,6 +217,7 @@
"Idris": "#b30000",
"Ignore List": "#000000",
"ImageJ Macro": "#99AAFF",
+ "Imba": "#16cec6",
"Inno Setup": "#264b99",
"Io": "#a9188d",
"Ioke": "#078193",
@@ -286,6 +289,7 @@
"Mathematica": "#dd1100",
"Max": "#c4a79c",
"Mercury": "#ff2b2b",
+ "Mermaid": "#ff3670",
"Meson": "#007800",
"Metal": "#8f14e9",
"MiniYAML": "#ff1111",
@@ -318,6 +322,10 @@
"Nu": "#c9df40",
"NumPy": "#9C8AF9",
"Nunjucks": "#3d8137",
+ "OASv2-json": "#85ea2d",
+ "OASv2-yaml": "#85ea2d",
+ "OASv3-json": "#85ea2d",
+ "OASv3-yaml": "#85ea2d",
"OCaml": "#3be133",
"ObjectScript": "#424893",
"Objective-C": "#438eff",
@@ -327,14 +335,18 @@
"Omgrofl": "#cabbff",
"Opal": "#f7ede0",
"Open Policy Agent": "#7d9199",
+ "OpenAPI Specification v2": "#85ea2d",
+ "OpenAPI Specification v3": "#85ea2d",
"OpenCL": "#ed2e2d",
"OpenEdge ABL": "#5ce600",
"OpenQASM": "#AA70FF",
"OpenSCAD": "#e5cd45",
+ "Option List": "#476732",
"Org": "#77aa99",
"Oxygene": "#cdd0e3",
"Oz": "#fab738",
"P4": "#7055b5",
+ "PDDL": "#0d00ff",
"PEG.js": "#234d6b",
"PHP": "#4F5D95",
"PLSQL": "#dad8d8",
@@ -351,6 +363,7 @@
"PigLatin": "#fcd7de",
"Pike": "#005390",
"PogoScript": "#d80074",
+ "Polar": "#ae81ff",
"Portugol": "#f8bd00",
"PostCSS": "#dc3a0c",
"PostScript": "#da291c",
@@ -414,6 +427,7 @@
"Sass": "#a53b70",
"Scala": "#c22d40",
"Scaml": "#bd181a",
+ "Scenic": "#fdc700",
"Scheme": "#1e4aec",
"Scilab": "#ca0f21",
"Self": "#0579aa",
@@ -421,6 +435,7 @@
"Shell": "#89e051",
"ShellCheck Config": "#cecfcb",
"Shen": "#120F14",
+ "Simple File Verification": "#C9BFED",
"Singularity": "#64E6AD",
"Slash": "#007eff",
"Slice": "#003fa2",
@@ -428,6 +443,7 @@
"SmPL": "#c94949",
"Smalltalk": "#596706",
"Smarty": "#f0c040",
+ "Smithy": "#c44536",
"Solidity": "#AA6746",
"SourcePawn": "#f69e1d",
"Squirrel": "#800000",
@@ -478,6 +494,7 @@
"Vim Script": "#199f4b",
"Vim Snippet": "#199f4b",
"Visual Basic .NET": "#945db7",
+ "Visual Basic 6.0": "#2c6353",
"Volt": "#1F1F1F",
"Vue": "#41b883",
"Vyper": "#2980b9",
@@ -514,6 +531,7 @@
"fish": "#4aae47",
"hoon": "#00b171",
"jq": "#c7254e",
+ "just": "#384d54",
"kvlang": "#1da6e0",
"mIRC Script": "#3d57c3",
"mcfunction": "#E22837",
From 888663a47728a4e82a78dcc6fd95ce53bdaffc70 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B0=95=EB=AF=BC=EC=A7=80?=
<68285922+Meezzi@users.noreply.github.com>
Date: Tue, 14 Feb 2023 09:50:12 +0900
Subject: [PATCH 154/905] Add `rose` theme (#2480)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: 강민지 <68285922+Kminzzi@users.noreply.github.com>
---
themes/index.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/themes/index.js b/themes/index.js
index a5d3abae8cb6f..60825d132a119 100644
--- a/themes/index.js
+++ b/themes/index.js
@@ -374,6 +374,13 @@ export const themes = {
border_color: "170F0C",
bg_color: "170F0C",
},
+ rose: {
+ title_color: "8d192b",
+ text_color: "862931",
+ icon_color: "B71F36",
+ border_color: "e9d8d4",
+ bg_color: "e9d8d4",
+ },
};
export default themes;
From ba7c2f8b55eac8452e479c8bd38b044d204d0424 Mon Sep 17 00:00:00 2001
From: Amir
Date: Thu, 16 Feb 2023 04:53:11 +0330
Subject: [PATCH 155/905] Support hide_progress for top-langs feature (#2514)
* Add support for hide_progress in top languages feature
* Fix mistake
* Add documents for all languages
* Remove unnecessary value check
* Update top-languages-card.js
* Revert document for all languages except English
* Update documentation
* Update documentation
---------
Co-authored-by: Zohan Subhash
---
api/top-langs.js | 2 ++
readme.md | 13 +++++++++++
src/cards/top-languages-card.js | 39 +++++++++++++++++++++++----------
src/cards/types.d.ts | 1 +
4 files changed, 44 insertions(+), 11 deletions(-)
diff --git a/api/top-langs.js b/api/top-langs.js
index 19cccb894e33a..e67d953323441 100644
--- a/api/top-langs.js
+++ b/api/top-langs.js
@@ -30,6 +30,7 @@ export default async (req, res) => {
border_radius,
border_color,
disable_animations,
+ hide_progress,
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
@@ -77,6 +78,7 @@ export default async (req, res) => {
border_color,
locale: locale ? locale.toLowerCase() : null,
disable_animations: parseBoolean(disable_animations),
+ hide_progress: parseBoolean(hide_progress),
}),
);
} catch (err) {
diff --git a/readme.md b/readme.md
index 678c5c0b14af4..29852bf9c6515 100644
--- a/readme.md
+++ b/readme.md
@@ -305,6 +305,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
- `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`.
- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
+- `hide_progress` - It uses the compact layout option, hides percentages, and removes the bars. Default: `false`.
> **Warning**
> Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
@@ -398,6 +399,14 @@ You can use the `&layout=compact` option to change the card design.
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
```
+### Hide Progress Bars
+
+You can use the `&hide_progress=true` option to hide the percentages and the progress bars (layout will be automatically set to `compact`).
+
+```md
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+```
+
### Demo
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats)
@@ -406,6 +415,10 @@ You can use the `&layout=compact` option to change the card design.
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+- Hidden progress bars
+
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+
# Wakatime Week Stats
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 9396ff8e73d5e..be1328c0c8fe3 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -76,10 +76,11 @@ const createProgressTextNode = ({ width, color, name, progress, index }) => {
* @param {object} props Function properties.
* @param {Lang} props.lang Programming language object.
* @param {number} props.totalSize Total size of all languages.
+ * @param {boolean} props.hideProgress Whether to hide percentage.
* @param {number} props.index Index of the programming language.
* @returns {string} Compact layout programming language SVG node.
*/
-const createCompactLangNode = ({ lang, totalSize, index }) => {
+const createCompactLangNode = ({ lang, totalSize, hideProgress, index }) => {
const percentage = ((lang.size / totalSize) * 100).toFixed(2);
const staggerDelay = (index + 3) * 150;
const color = lang.color || "#858585";
@@ -88,7 +89,7 @@ const createCompactLangNode = ({ lang, totalSize, index }) => {
- ${lang.name} ${percentage}%
+ ${lang.name} ${hideProgress ? "" : percentage + "%"}
`;
@@ -100,9 +101,10 @@ const createCompactLangNode = ({ lang, totalSize, index }) => {
* @param {object[]} props Function properties.
* @param {Lang[]} props.langs Array of programming languages.
* @param {number} props.totalSize Total size of all languages.
+ * @param {boolean} props.hideProgress Whether to hide percentage.
* @returns {string} Programming languages SVG node.
*/
-const createLanguageTextNode = ({ langs, totalSize }) => {
+const createLanguageTextNode = ({ langs, totalSize, hideProgress }) => {
const longestLang = getLongestLang(langs);
const chunked = chunkArray(langs, langs.length / 2);
const layouts = chunked.map((array) => {
@@ -111,6 +113,7 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
createCompactLangNode({
lang,
totalSize,
+ hideProgress,
index,
}),
);
@@ -160,9 +163,10 @@ const renderNormalLayout = (langs, width, totalLanguageSize) => {
* @param {Lang[]} langs Array of programming languages.
* @param {number} width Card width.
* @param {number} totalLanguageSize Total size of all languages.
+ * @param {boolean} hideProgress Whether to hide progress bar.
* @returns {string} Compact layout card SVG object.
*/
-const renderCompactLayout = (langs, width, totalLanguageSize) => {
+const renderCompactLayout = (langs, width, totalLanguageSize, hideProgress) => {
const paddingRight = 50;
const offsetWidth = width - paddingRight;
// progressOffset holds the previous language's width and used to offset the next language
@@ -193,15 +197,21 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => {
.join("");
return `
-
+ ${
+ !hideProgress
+ ? `
+
${compactProgressBar}
-
-
+ `
+ : ""
+ }
+
${createLanguageTextNode({
langs,
totalSize: totalLanguageSize,
+ hideProgress: hideProgress,
})}
`;
@@ -276,6 +286,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
text_color,
bg_color,
hide,
+ hide_progress,
theme,
layout,
custom_title,
@@ -305,11 +316,17 @@ const renderTopLanguages = (topLangs, options = {}) => {
let height = calculateNormalLayoutHeight(langs.length);
let finalLayout = "";
- if (layout === "compact") {
+ if (layout === "compact" || hide_progress == true) {
width = width + 50; // padding
- height = calculateCompactLayoutHeight(langs.length);
-
- finalLayout = renderCompactLayout(langs, width, totalLanguageSize);
+ height =
+ calculateCompactLayoutHeight(langs.length) + (hide_progress ? -25 : 0);
+
+ finalLayout = renderCompactLayout(
+ langs,
+ width,
+ totalLanguageSize,
+ hide_progress,
+ );
} else {
finalLayout = renderNormalLayout(langs, width, totalLanguageSize);
}
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index c5945d48be71e..52ee0edb6a459 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -38,6 +38,7 @@ export type TopLangOptions = CommonOptions & {
custom_title: string;
langs_count: number;
disable_animations: boolean;
+ hide_progress: boolean;
};
type WakaTimeOptions = CommonOptions & {
From 5f20e6c97a35d77c4b2839b340bfc188ed23a056 Mon Sep 17 00:00:00 2001
From: Mohamed Hassan
Date: Sat, 25 Feb 2023 08:49:30 +0200
Subject: [PATCH 156/905] add holi_theme (#2539)
* add holi_theme
* add holi_theme
---
themes/index.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/themes/index.js b/themes/index.js
index 60825d132a119..5ed0f782fd90a 100644
--- a/themes/index.js
+++ b/themes/index.js
@@ -381,6 +381,13 @@ export const themes = {
border_color: "e9d8d4",
bg_color: "e9d8d4",
},
+ holi_theme: {
+ title_color: "5FABEE",
+ text_color: "D6E7FF",
+ icon_color: "5FABEE",
+ border_color: "85A4C0",
+ bg_color: "030314",
+ },
};
export default themes;
From a6ff0fa521f87f112f124bc7a9d0b435d4d166b4 Mon Sep 17 00:00:00 2001
From: Oleksandr Perlov
Date: Sat, 25 Feb 2023 08:50:00 +0200
Subject: [PATCH 157/905] Add one_dark_pro (#2507)
This colors were taken from One Dark Pro theme in VSCode extention. Please add it and I will use it in my profile
Co-authored-by: Zohan Subhash
---
themes/index.js | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/themes/index.js b/themes/index.js
index 5ed0f782fd90a..e55c12f89bdce 100644
--- a/themes/index.js
+++ b/themes/index.js
@@ -374,6 +374,12 @@ export const themes = {
border_color: "170F0C",
bg_color: "170F0C",
},
+ one_dark_pro: {
+ title_color: "61AFEF",
+ text_color: "E5C06E",
+ icon_color: "C678DD",
+ border_color: "3B4048",
+ bg_color: "23272E",
rose: {
title_color: "8d192b",
text_color: "862931",
From f3f7a4837d48cb82abd61e8b16631f0f161fca9f Mon Sep 17 00:00:00 2001
From: Cateline Mnemosyne
<123184375+catelinemnemosyne@users.noreply.github.com>
Date: Sat, 25 Feb 2023 09:55:12 +0100
Subject: [PATCH 158/905] fix: fix JSON themes bug. (#2544)
This fixes a JSON bug that was introduced in https://github.com/anuraghazra/github-readme-stats/pull/2507.
---
themes/index.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/themes/index.js b/themes/index.js
index e55c12f89bdce..01c9a8eee79d6 100644
--- a/themes/index.js
+++ b/themes/index.js
@@ -380,6 +380,7 @@ export const themes = {
icon_color: "C678DD",
border_color: "3B4048",
bg_color: "23272E",
+ },
rose: {
title_color: "8d192b",
text_color: "862931",
From 55a303b4a621b9f1ac1ce0c6fe298139df7d2ac1 Mon Sep 17 00:00:00 2001
From: Zohan Subhash
Date: Sat, 25 Feb 2023 17:20:14 +0530
Subject: [PATCH 159/905] Add auto-labelling for documentation updates (#2526)
---
.github/labeler.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/labeler.yml b/.github/labeler.yml
index be97765f07e42..fad3eeeb8d101 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -1,3 +1,4 @@
themes: themes/index.js
doc-translation: docs/*
card-i18n: src/translations.js
+documentation: readme.md
From 91345ed55fab44acac016a25d7083fc74b0b1592 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sat, 25 Feb 2023 12:51:54 +0100
Subject: [PATCH 160/905] ci: fix unsafe directory bug (#2518)
This commit fixes a bug that was introduced due to a upstream change in
the git package. See https://stackoverflow.com/questions/71849415/i-cannot-add-the-parent-directory-to-safe-directory-in-git/71904131#71904131
for more information.
---
.github/workflows/generate-theme-doc.yml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.github/workflows/generate-theme-doc.yml b/.github/workflows/generate-theme-doc.yml
index d5fac06381943..75f6511f09015 100644
--- a/.github/workflows/generate-theme-doc.yml
+++ b/.github/workflows/generate-theme-doc.yml
@@ -23,6 +23,10 @@ jobs:
node-version: ${{ matrix.node-version }}
cache: npm
+ # Fix the unsafe repo error which was introduced by the CVE-2022-24765 git patches.
+ - name: Fix unsafe repo error
+ run: git config --global --add safe.directory ${{ github.workspace }}
+
- name: npm install, generate readme
run: |
npm ci
From 8898d013b67481844213e065407cbe64ef6f3292 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Raphael=20Gon=C3=A7alves?=
<89359384+raphaelricardo10@users.noreply.github.com>
Date: Sat, 25 Feb 2023 09:02:42 -0300
Subject: [PATCH 161/905] Update readme.md (#2414)
fix: missing "&" in show_icons=true in Showing icons section
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index 29852bf9c6515..83f573eddef12 100644
--- a/readme.md
+++ b/readme.md
@@ -133,7 +133,7 @@ You can add the count of all your private contributions to the total commits cou
### Showing icons
-To enable icons, you can pass `show_icons=true` in the query param, like so:
+To enable icons, you can pass `&show_icons=true` in the query param, like so:
```md
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true)
From a3c6f874af5c7140c67d3db4e15f85fb92171fd8 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sat, 25 Feb 2023 13:32:08 +0100
Subject: [PATCH 162/905] test: update snapshots (#2519)
---
src/cards/wakatime-card.js | 26 ++++++++++-
.../renderWakatimeCard.test.js.snap | 44 +++++++++++++++++++
2 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index e7af1df710f9c..2c329558b8a35 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -118,6 +118,7 @@ const createTextNode = ({
// @ts-ignore
name: label,
progressBarBackgroundColor,
+ delay: staggerDelay + 300,
});
return `
@@ -276,11 +277,12 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
} else {
finalLayout = flexLayout({
items: filteredLanguages.length
- ? filteredLanguages.map((language) => {
+ ? filteredLanguages.map((language, index) => {
return createTextNode({
id: language.name,
label: language.name,
value: language.text,
+ index: index,
percent: language.percent,
// @ts-ignore
progressBarColor: titleColor,
@@ -321,7 +323,29 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
card.setCSS(
`
${cssStyles}
+ @keyframes slideInAnimation {
+ from {
+ width: 0;
+ }
+ to {
+ width: calc(100%-100px);
+ }
+ }
+ @keyframes growWidthAnimation {
+ from {
+ width: 0;
+ }
+ to {
+ width: 100%;
+ }
+ }
.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
+ #rect-mask rect{
+ animation: slideInAnimation 1s ease-in-out forwards;
+ }
+ .lang-progress{
+ animation: growWidthAnimation 0.6s ease-in-out forwards;
+ }
`,
);
diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap
index 1c0bd701fbbfe..6dfaf98e9742a 100644
--- a/tests/__snapshots__/renderWakatimeCard.test.js.snap
+++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap
@@ -69,7 +69,29 @@ exports[`Test Render Wakatime Card should render correctly with compact layout 1
}
+ @keyframes slideInAnimation {
+ from {
+ width: 0;
+ }
+ to {
+ width: calc(100%-100px);
+ }
+ }
+ @keyframes growWidthAnimation {
+ from {
+ width: 0;
+ }
+ to {
+ width: 100%;
+ }
+ }
.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58 }
+ #rect-mask rect{
+ animation: slideInAnimation 1s ease-in-out forwards;
+ }
+ .lang-progress{
+ animation: growWidthAnimation 0.6s ease-in-out forwards;
+ }
@@ -227,7 +249,29 @@ exports[`Test Render Wakatime Card should render correctly with compact layout w
}
+ @keyframes slideInAnimation {
+ from {
+ width: 0;
+ }
+ to {
+ width: calc(100%-100px);
+ }
+ }
+ @keyframes growWidthAnimation {
+ from {
+ width: 0;
+ }
+ to {
+ width: 100%;
+ }
+ }
.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58 }
+ #rect-mask rect{
+ animation: slideInAnimation 1s ease-in-out forwards;
+ }
+ .lang-progress{
+ animation: growWidthAnimation 0.6s ease-in-out forwards;
+ }
From 2ab8b85ae39e7b3307c27328916b97e96f1da00f Mon Sep 17 00:00:00 2001
From: Rehman
Date: Sat, 25 Feb 2023 19:01:49 +0530
Subject: [PATCH 163/905] fix: for issue #2534 (#2536)
---
src/cards/top-languages-card.js | 3 +--
tests/renderTopLanguages.test.js | 6 +++---
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index be1328c0c8fe3..ce8e12a839c77 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -13,7 +13,7 @@ import {
import { langCardLocales } from "../translations.js";
const DEFAULT_CARD_WIDTH = 300;
-const MIN_CARD_WIDTH = 230;
+const MIN_CARD_WIDTH = 280;
const DEFAULT_LANGS_COUNT = 5;
const DEFAULT_LANG_COLOR = "#858585";
const CARD_PADDING = 25;
@@ -317,7 +317,6 @@ const renderTopLanguages = (topLangs, options = {}) => {
let finalLayout = "";
if (layout === "compact" || hide_progress == true) {
- width = width + 50; // padding
height =
calculateCompactLayoutHeight(langs.length) + (hide_progress ? -25 : 0);
diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js
index 8ae4bbd0c16e6..de9e21f129bdf 100644
--- a/tests/renderTopLanguages.test.js
+++ b/tests/renderTopLanguages.test.js
@@ -216,7 +216,7 @@ describe("Test renderTopLanguages", () => {
);
expect(queryAllByTestId(document.body, "lang-progress")[0]).toHaveAttribute(
"width",
- "120",
+ "100",
);
expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent(
@@ -224,7 +224,7 @@ describe("Test renderTopLanguages", () => {
);
expect(queryAllByTestId(document.body, "lang-progress")[1]).toHaveAttribute(
"width",
- "120",
+ "100",
);
expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent(
@@ -232,7 +232,7 @@ describe("Test renderTopLanguages", () => {
);
expect(queryAllByTestId(document.body, "lang-progress")[2]).toHaveAttribute(
"width",
- "60",
+ "50",
);
});
From 1d528da1dcfe301861810e7e559e70da262c4d4f Mon Sep 17 00:00:00 2001
From: Zohan Subhash
Date: Sat, 25 Feb 2023 19:34:00 +0530
Subject: [PATCH 164/905] Add option to deploy using other services (#2525)
* Create express.js
* Update readme.md
* Update readme.md
---
express.js | 15 +++++++++++++++
readme.md | 25 +++++++++++++++++++++++--
2 files changed, 38 insertions(+), 2 deletions(-)
create mode 100644 express.js
diff --git a/express.js b/express.js
new file mode 100644
index 0000000000000..0a139625e06bb
--- /dev/null
+++ b/express.js
@@ -0,0 +1,15 @@
+import statsCard from './api/index.js'
+import repoCard from './api/pin.js'
+import langCard from './api/top-langs.js'
+import wakatimeCard from './api/wakatime.js'
+import express from 'express'
+import dotenv from 'dotenv'
+
+dotenv.config()
+const app = express()
+app.listen(process.env.port || 9000)
+
+app.get('/', statsCard)
+app.get('/pin', repoCard)
+app.get('/top-langs', langCard)
+app.get('/wakatime', wakatimeCard)
diff --git a/readme.md b/readme.md
index 83f573eddef12..7a60228460126 100644
--- a/readme.md
+++ b/readme.md
@@ -92,7 +92,9 @@ Visit and make a small donation to hel
- [Repo Card Exclusive Options](#repo-card-exclusive-options)
- [Language Card Exclusive Options](#language-card-exclusive-options)
- [Wakatime Card Exclusive Option](#wakatime-card-exclusive-options)
-- [Deploy Yourself](#deploy-on-your-own-vercel-instance)
+- [Deploy Yourself](#deploy-on-your-own)
+ - [On Vercel](#on-vercel)
+ - [On other platforms](#on-other-platforms)
- [Keep your fork up to date](#keep-your-fork-up-to-date)
# GitHub Stats Card
@@ -509,7 +511,9 @@ By default, GitHub does not lay out the cards side by side. To do that, you can
```
-## Deploy on your own Vercel instance
+## Deploy on your own
+
+### On Vercel
#### :film_projector: [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
@@ -546,6 +550,23 @@ Since the GitHub API only allows 5k requests per hour, my `https://github-readme
+### On other platforms
+
+> **Warning**
+> This way of using GRS is not officially supported and was added to cater to some particular use cases where Vercel could not be used (e.g. #2341). The support for this method, therefore, is limited.
+
+
+:hammer_and_wrench: Step-by-step guide for deploying on other platforms
+
+1. Fork or clone this repo as per your needs
+2. Add `express` to the dependencies section of `package.json`
+https://github.com/anuraghazra/github-readme-stats/blob/ba7c2f8b55eac8452e479c8bd38b044d204d0424/package.json#L54-L61
+3. Run `npm i` if needed (initial setup)
+4. Run `node express.js` to start the server, or set the entry point to `express.js` in `package.json` if you're deploying on a managed service
+https://github.com/anuraghazra/github-readme-stats/blob/ba7c2f8b55eac8452e479c8bd38b044d204d0424/package.json#L11
+5. You're done 🎉
+
+
### Keep your fork up to date
You can keep your fork, and thus your private Vercel instance up to date with the upstream using GitHubs' [Sync Fork button](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork). You can also use the [pull](https://github.com/wei/pull) package created by [@wei](https://github.com/wei) to automate this process.
From 82224fa68a453c82b7d5458c5431d3efb01f1853 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sat, 25 Feb 2023 15:12:11 +0100
Subject: [PATCH 165/905] ci: update e2e tests (#2548)
---
.gitignore | 2 ++
tests/e2e/e2e.test.js | 6 +++---
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/.gitignore b/.gitignore
index 2cdfa3d334808..25017502d486a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@ vercel_token
# IDE
.vscode
*.code-workspace
+
+.vercel
diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js
index 402e210fcee17..f34859d4c8be0 100644
--- a/tests/e2e/e2e.test.js
+++ b/tests/e2e/e2e.test.js
@@ -15,14 +15,14 @@ const REPO = "curly-fiesta";
const USER = "catelinemnemosyne";
const STATS_DATA = {
name: "Cateline Mnemosyne",
- totalPRs: 1,
- totalCommits: 7,
+ totalPRs: 2,
+ totalCommits: 8,
totalIssues: 1,
totalStars: 1,
contributedTo: 1,
rank: {
level: "A+",
- score: 50.893750297869225,
+ score: 50.88831151384285,
},
};
From d5fbfb4345a89c264b8b07b16dedf933fa60691a Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sat, 25 Feb 2023 15:14:47 +0100
Subject: [PATCH 166/905] ci: fix a bug in the theme preview action (#2549)
---
scripts/preview-theme.js | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index 38faf873ce3d5..aae892c602fdb 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -298,12 +298,13 @@ const themeNameAlreadyExists = (name) => {
return themes[name] !== undefined;
};
+const DRY_RUN = process.env.DRY_RUN === "true" || false;
+
/**
* Main function.
*/
export const run = async (prNumber) => {
try {
- const dryRun = process.env.DRY_RUN === "true" || false;
debug("Retrieve action information from context...");
debug(`Context: ${inspect(github.context)}`);
let commentBody = `
@@ -513,7 +514,7 @@ export const run = async (prNumber) => {
// Create or update theme-preview comment.
debug("Create or update theme-preview comment...");
let comment_url;
- if (!dryRun) {
+ if (!DRY_RUN) {
comment_url = await upsertComment(octokit, {
comment_id: comment?.id,
issue_number: pullRequestId,
@@ -535,7 +536,7 @@ export const run = async (prNumber) => {
const reviewReason = themesValid
? undefined
: INVALID_REVIEW_COMMENT(comment_url);
- if (!dryRun) {
+ if (!DRY_RUN) {
await addReview(
octokit,
pullRequestId,
@@ -558,7 +559,7 @@ export const run = async (prNumber) => {
}
} catch (error) {
debug("Set review state to `REQUEST_CHANGES` and add `invalid` label...");
- if (!dryRun) {
+ if (!DRY_RUN) {
await addReview(
octokit,
pullRequestId,
From 252c2b419d8adbba76e02463b198409f7d1d5977 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sun, 26 Feb 2023 03:44:42 +0100
Subject: [PATCH 167/905] refactor: format code (#2550)
---
express.js | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/express.js b/express.js
index 0a139625e06bb..6ce92ff035181 100644
--- a/express.js
+++ b/express.js
@@ -1,15 +1,15 @@
-import statsCard from './api/index.js'
-import repoCard from './api/pin.js'
-import langCard from './api/top-langs.js'
-import wakatimeCard from './api/wakatime.js'
-import express from 'express'
-import dotenv from 'dotenv'
+import statsCard from "./api/index.js";
+import repoCard from "./api/pin.js";
+import langCard from "./api/top-langs.js";
+import wakatimeCard from "./api/wakatime.js";
+import express from "express";
+import dotenv from "dotenv";
-dotenv.config()
-const app = express()
-app.listen(process.env.port || 9000)
+dotenv.config();
+const app = express();
+app.listen(process.env.port || 9000);
-app.get('/', statsCard)
-app.get('/pin', repoCard)
-app.get('/top-langs', langCard)
-app.get('/wakatime', wakatimeCard)
+app.get("/", statsCard);
+app.get("/pin", repoCard);
+app.get("/top-langs", langCard);
+app.get("/wakatime", wakatimeCard);
From d60d53cdb43c27d48ba2fc2973ae8143579b6dd9 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 1 Mar 2023 06:47:56 +0530
Subject: [PATCH 168/905] refactor: update languages JSON (#2554)
Co-authored-by: rickstaa
---
src/common/languageColors.json | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/common/languageColors.json b/src/common/languageColors.json
index 47bfb1cfa3435..b50cba6f30b08 100644
--- a/src/common/languageColors.json
+++ b/src/common/languageColors.json
@@ -79,6 +79,7 @@
"Ceylon": "#dfa535",
"Chapel": "#8dc63f",
"ChucK": "#3f8000",
+ "Circom": "#707575",
"Cirru": "#ccccff",
"Clarion": "#db901e",
"Clarity": "#5546ff",
@@ -116,6 +117,7 @@
"DirectX 3D File": "#aace60",
"Dockerfile": "#384d54",
"Dogescript": "#cca760",
+ "Dotenv": "#e5d559",
"Dylan": "#6c616e",
"E": "#ccce35",
"ECL": "#8a1267",
@@ -149,7 +151,7 @@
"Forth": "#341708",
"Fortran": "#4d41b1",
"Fortran Free Form": "#4d41b1",
- "FreeBasic": "#867db1",
+ "FreeBasic": "#141AC9",
"FreeMarker": "#0050b2",
"Frege": "#00cafe",
"Futhark": "#5f021f",
@@ -182,6 +184,7 @@
"Go": "#00ADD8",
"Go Checksums": "#00ADD8",
"Go Module": "#00ADD8",
+ "Godot Resource": "#355570",
"Golo": "#88562A",
"Gosu": "#82937f",
"Grace": "#615f8b",
@@ -192,6 +195,7 @@
"Groovy": "#4298b8",
"Groovy Server Pages": "#4298b8",
"HAProxy": "#106da9",
+ "HCL": "#844FBA",
"HLSL": "#aace60",
"HOCON": "#9ff8ee",
"HTML": "#e34c26",
@@ -225,6 +229,7 @@
"Isabelle ROOT": "#FEFE00",
"J": "#9EEDFF",
"JAR Manifest": "#b07219",
+ "JCL": "#d90e09",
"JFlex": "#DBCA00",
"JSON": "#292929",
"JSON with Comments": "#292929",
@@ -247,9 +252,11 @@
"Jsonnet": "#0064bd",
"Julia": "#a270ba",
"Jupyter Notebook": "#DA5B0B",
+ "Just": "#384d54",
"KRL": "#28430A",
"Kaitai Struct": "#773b37",
"KakouneScript": "#6f8042",
+ "KerboScript": "#41adf0",
"KiCad Layout": "#2f4aab",
"KiCad Legacy Layout": "#2f4aab",
"KiCad Schematic": "#2f4aab",
@@ -362,6 +369,7 @@
"PicoLisp": "#6067af",
"PigLatin": "#fcd7de",
"Pike": "#005390",
+ "PlantUML": "#fbbd16",
"PogoScript": "#d80074",
"Polar": "#ae81ff",
"Portugol": "#f8bd00",
@@ -379,6 +387,7 @@
"Puppet": "#302B6D",
"PureBasic": "#5a6986",
"PureScript": "#1D222D",
+ "Pyret": "#ee1e10",
"Python": "#3572A5",
"Python console": "#3572A5",
"Python traceback": "#3572A5",
@@ -531,7 +540,6 @@
"fish": "#4aae47",
"hoon": "#00b171",
"jq": "#c7254e",
- "just": "#384d54",
"kvlang": "#1da6e0",
"mIRC Script": "#3d57c3",
"mcfunction": "#E22837",
From 8849b5f5fc708ea2f64d5c7176580252e17bc81a Mon Sep 17 00:00:00 2001
From: Zohan Subhash
Date: Wed, 1 Mar 2023 15:03:49 +0530
Subject: [PATCH 169/905] Preview theme workflow fix (#2557)
* Fix octokit error
* ci: make octokit instance global
---------
Co-authored-by: rickstaa
---
scripts/preview-theme.js | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index aae892c602fdb..d94d084aa85e7 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -44,6 +44,9 @@ const REQUIRED_COLOR_PROPS = ACCEPTED_COLOR_PROPS.slice(0, 4);
const INVALID_REVIEW_COMMENT = (commentUrl) =>
`Some themes are invalid. See the [Automated Theme Preview](${commentUrl}) comment above for more information.`;
+// Retrieve octokit instance.
+const OCTOKIT = github.getOctokit(getGithubToken());
+
/**
* Retrieve PR number from the event payload.
*
@@ -312,7 +315,6 @@ export const run = async (prNumber) => {
\r${THEME_CONTRIB_GUIDELINESS}
`;
const ccc = new ColorContrastChecker();
- const octokit = github.getOctokit(getGithubToken());
const pullRequestId = prNumber ? prNumber : getPrNumber();
const commenter = getCommenter();
const { owner, repo } = getRepoInfo(github.context);
@@ -322,7 +324,7 @@ export const run = async (prNumber) => {
// Retrieve the PR diff and preview-theme comment.
debug("Retrieve PR diff...");
- const res = await octokit.pulls.get({
+ const res = await OCTOKIT.pulls.get({
owner,
repo,
pull_number: pullRequestId,
@@ -332,7 +334,7 @@ export const run = async (prNumber) => {
});
debug("Retrieve preview-theme comment...");
const comment = await findComment(
- octokit,
+ OCTOKIT,
pullRequestId,
owner,
repo,
@@ -515,7 +517,7 @@ export const run = async (prNumber) => {
debug("Create or update theme-preview comment...");
let comment_url;
if (!DRY_RUN) {
- comment_url = await upsertComment(octokit, {
+ comment_url = await upsertComment(OCTOKIT, {
comment_id: comment?.id,
issue_number: pullRequestId,
owner,
@@ -538,7 +540,7 @@ export const run = async (prNumber) => {
: INVALID_REVIEW_COMMENT(comment_url);
if (!DRY_RUN) {
await addReview(
- octokit,
+ OCTOKIT,
pullRequestId,
owner,
repo,
@@ -546,7 +548,7 @@ export const run = async (prNumber) => {
reviewReason,
);
await addRemoveLabel(
- octokit,
+ OCTOKIT,
pullRequestId,
owner,
repo,
@@ -561,7 +563,7 @@ export const run = async (prNumber) => {
debug("Set review state to `REQUEST_CHANGES` and add `invalid` label...");
if (!DRY_RUN) {
await addReview(
- octokit,
+ OCTOKIT,
pullRequestId,
owner,
repo,
@@ -569,7 +571,7 @@ export const run = async (prNumber) => {
error.message,
);
await addRemoveLabel(
- octokit,
+ OCTOKIT,
pullRequestId,
owner,
repo,
From a1c3c6accc1e8a0be00dd0db5a32d63d86055daa Mon Sep 17 00:00:00 2001
From: Zohan Subhash
Date: Wed, 1 Mar 2023 21:21:25 +0530
Subject: [PATCH 170/905] ci: preview theme workflow fix (#2559)
* Fix octokit error
* ci: make octokit instance global
* Fix preview theme (move declarations to global)
* refactor: make constants uppercase
---------
Co-authored-by: rickstaa
---
scripts/preview-theme.js | 50 ++++++++++++++++++++--------------------
1 file changed, 25 insertions(+), 25 deletions(-)
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index d94d084aa85e7..f5a24a80a326d 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -46,6 +46,8 @@ const INVALID_REVIEW_COMMENT = (commentUrl) =>
// Retrieve octokit instance.
const OCTOKIT = github.getOctokit(getGithubToken());
+const PULL_REQUEST_ID = prNumber ? prNumber : getPrNumber();
+const { OWNER, REPO } = getRepoInfo(github.context);
/**
* Retrieve PR number from the event payload.
@@ -315,19 +317,17 @@ export const run = async (prNumber) => {
\r${THEME_CONTRIB_GUIDELINESS}
`;
const ccc = new ColorContrastChecker();
- const pullRequestId = prNumber ? prNumber : getPrNumber();
const commenter = getCommenter();
- const { owner, repo } = getRepoInfo(github.context);
- debug(`Owner: ${owner}`);
- debug(`Repo: ${repo}`);
+ debug(`Owner: ${OWNER}`);
+ debug(`Repo: ${REPO}`);
debug(`Commenter: ${commenter}`);
// Retrieve the PR diff and preview-theme comment.
debug("Retrieve PR diff...");
const res = await OCTOKIT.pulls.get({
- owner,
- repo,
- pull_number: pullRequestId,
+ OWNER,
+ REPO,
+ pull_number: PULL_REQUEST_ID,
mediaType: {
format: "diff",
},
@@ -335,9 +335,9 @@ export const run = async (prNumber) => {
debug("Retrieve preview-theme comment...");
const comment = await findComment(
OCTOKIT,
- pullRequestId,
- owner,
- repo,
+ PULL_REQUEST_ID,
+ OWNER,
+ REPO,
commenter,
);
@@ -519,9 +519,9 @@ export const run = async (prNumber) => {
if (!DRY_RUN) {
comment_url = await upsertComment(OCTOKIT, {
comment_id: comment?.id,
- issue_number: pullRequestId,
- owner,
- repo,
+ issue_number: PULL_REQUEST_ID,
+ OWNER,
+ REPO,
body: commentBody,
});
} else {
@@ -541,17 +541,17 @@ export const run = async (prNumber) => {
if (!DRY_RUN) {
await addReview(
OCTOKIT,
- pullRequestId,
- owner,
- repo,
+ PULL_REQUEST_ID,
+ OWNER,
+ REPO,
reviewState,
reviewReason,
);
await addRemoveLabel(
OCTOKIT,
- pullRequestId,
- owner,
- repo,
+ PULL_REQUEST_ID,
+ OWNER,
+ REPO,
"invalid",
!themesValid,
);
@@ -564,17 +564,17 @@ export const run = async (prNumber) => {
if (!DRY_RUN) {
await addReview(
OCTOKIT,
- pullRequestId,
- owner,
- repo,
+ PULL_REQUEST_ID,
+ OWNER,
+ REPO,
"REQUEST_CHANGES",
error.message,
);
await addRemoveLabel(
OCTOKIT,
- pullRequestId,
- owner,
- repo,
+ PULL_REQUEST_ID,
+ OWNER,
+ REPO,
"invalid",
true,
);
From 9ec2c8367a38e008a1c4ea740d2408bdc3c20842 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Thu, 2 Mar 2023 03:14:43 +0100
Subject: [PATCH 171/905] refactor: fix code comments and change 'up' rate
limit (#2560)
---
api/status/pat-info.js | 4 ++--
api/status/up.js | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/api/status/pat-info.js b/api/status/pat-info.js
index 775e06896427c..69d869ea2553e 100644
--- a/api/status/pat-info.js
+++ b/api/status/pat-info.js
@@ -2,11 +2,11 @@
* @file Contains a simple cloud function that can be used to check which PATs are no
* longer working. It returns a list of valid PATs, expired PATs and PATs with errors.
*
- * @description This function is currently rate limited to 1 request per 10 minutes.
+ * @description This function is currently rate limited to 1 request per 5 minutes.
*/
import { logger, request, dateDiff } from "../../src/common/utils.js";
-export const RATE_LIMIT_SECONDS = 60 * 5; // 1 request per 10 minutes
+export const RATE_LIMIT_SECONDS = 60 * 5; // 1 request per 5 minutes
/**
* Simple uptime check fetcher for the PATs.
diff --git a/api/status/up.js b/api/status/up.js
index 33fe8f900c395..678a20b0b5c14 100644
--- a/api/status/up.js
+++ b/api/status/up.js
@@ -2,13 +2,13 @@
* @file Contains a simple cloud function that can be used to check if the PATs are still
* functional.
*
- * @description This function is currently rate limited to 1 request per 10 minutes.
+ * @description This function is currently rate limited to 1 request per 5 minutes.
*/
import retryer from "../../src/common/retryer.js";
import { logger, request } from "../../src/common/utils.js";
-export const RATE_LIMIT_SECONDS = 60 * 10; // 1 request per 10 minutes
+export const RATE_LIMIT_SECONDS = 60 * 5; // 1 request per 5 minutes
/**
* Simple uptime check fetcher for the PATs.
From 7bc8f19a7fd7787287c02e42761602746e55c1d2 Mon Sep 17 00:00:00 2001
From: Zohan Subhash
Date: Thu, 2 Mar 2023 22:51:39 +0530
Subject: [PATCH 172/905] Preview action fix (#2561)
* Fix error
* refactor: remove unused code
---------
Co-authored-by: Rick Staa
---
scripts/preview-theme.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index f5a24a80a326d..baccaa61a3a78 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -46,7 +46,7 @@ const INVALID_REVIEW_COMMENT = (commentUrl) =>
// Retrieve octokit instance.
const OCTOKIT = github.getOctokit(getGithubToken());
-const PULL_REQUEST_ID = prNumber ? prNumber : getPrNumber();
+const PULL_REQUEST_ID = getPrNumber();
const { OWNER, REPO } = getRepoInfo(github.context);
/**
@@ -308,7 +308,7 @@ const DRY_RUN = process.env.DRY_RUN === "true" || false;
/**
* Main function.
*/
-export const run = async (prNumber) => {
+export const run = async () => {
try {
debug("Retrieve action information from context...");
debug(`Context: ${inspect(github.context)}`);
From 976771080facb86c3e4b455fef18278021f7f984 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Fri, 3 Mar 2023 09:07:02 +0100
Subject: [PATCH 173/905] ci: fix theme preview action (#2563)
---
scripts/preview-theme.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index baccaa61a3a78..2cfe0f25cad3a 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -46,8 +46,8 @@ const INVALID_REVIEW_COMMENT = (commentUrl) =>
// Retrieve octokit instance.
const OCTOKIT = github.getOctokit(getGithubToken());
-const PULL_REQUEST_ID = getPrNumber();
const { OWNER, REPO } = getRepoInfo(github.context);
+var PULL_REQUEST_ID;
/**
* Retrieve PR number from the event payload.
@@ -318,6 +318,7 @@ export const run = async () => {
`;
const ccc = new ColorContrastChecker();
const commenter = getCommenter();
+ PULL_REQUEST_ID = getPrNumber();
debug(`Owner: ${OWNER}`);
debug(`Repo: ${REPO}`);
debug(`Commenter: ${commenter}`);
From 1e61f9f3fe955fa25ab27dd1e06ddbfd788f4fda Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Fri, 3 Mar 2023 15:57:11 +0100
Subject: [PATCH 174/905] fix theme preview (#2564)
* ci: fix theme preview action
* fix: fix some bugs in the 'theme-preveiw' action
---
scripts/preview-theme.js | 41 +++++++++++++++++++++++++++++++---------
1 file changed, 32 insertions(+), 9 deletions(-)
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index 2cfe0f25cad3a..c0bb9eb5522d8 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -43,12 +43,24 @@ const ACCEPTED_COLOR_PROPS = Object.keys(COLOR_PROPS);
const REQUIRED_COLOR_PROPS = ACCEPTED_COLOR_PROPS.slice(0, 4);
const INVALID_REVIEW_COMMENT = (commentUrl) =>
`Some themes are invalid. See the [Automated Theme Preview](${commentUrl}) comment above for more information.`;
-
-// Retrieve octokit instance.
-const OCTOKIT = github.getOctokit(getGithubToken());
-const { OWNER, REPO } = getRepoInfo(github.context);
+var OCTOKIT;
+var OWNER;
+var REPO;
var PULL_REQUEST_ID;
+/**
+ * Incorrect JSON format error.
+ * @extends Error
+ * @param {string} message Error message.
+ * @returns {Error} IncorrectJsonFormatError.
+ */
+class IncorrectJsonFormatError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "IncorrectJsonFormatError";
+ }
+}
+
/**
* Retrieve PR number from the event payload.
*
@@ -274,7 +286,9 @@ const parseJSON = (json) => {
if (typeof parsedJson === "object") {
return parsedJson;
} else {
- throw new Error("PR diff is not a valid theme JSON object.");
+ throw new IncorrectJsonFormatError(
+ "PR diff is not a valid theme JSON object.",
+ );
}
} catch (error) {
let parsedJson = json
@@ -289,7 +303,9 @@ const parseJSON = (json) => {
}
return Hjson.parse(parsedJson.join(""));
} else {
- throw error;
+ throw new IncorrectJsonFormatError(
+ `Theme JSON file could not be parsed: ${error.message}`,
+ );
}
}
};
@@ -317,6 +333,11 @@ export const run = async () => {
\r${THEME_CONTRIB_GUIDELINESS}
`;
const ccc = new ColorContrastChecker();
+ OCTOKIT = github.getOctokit(getGithubToken());
+ PULL_REQUEST_ID = getPrNumber();
+ const { owner, repo } = getRepoInfo(github.context);
+ OWNER = owner;
+ REPO = repo;
const commenter = getCommenter();
PULL_REQUEST_ID = getPrNumber();
debug(`Owner: ${OWNER}`);
@@ -326,8 +347,8 @@ export const run = async () => {
// Retrieve the PR diff and preview-theme comment.
debug("Retrieve PR diff...");
const res = await OCTOKIT.pulls.get({
- OWNER,
- REPO,
+ owner: OWNER,
+ repo: REPO,
pull_number: PULL_REQUEST_ID,
mediaType: {
format: "diff",
@@ -569,7 +590,9 @@ export const run = async () => {
OWNER,
REPO,
"REQUEST_CHANGES",
- error.message,
+ "**Something went wrong in the theme preview action:** `" +
+ error.message +
+ "`",
);
await addRemoveLabel(
OCTOKIT,
From ed18914fa4c131b076cbc6cff29db3ffbdc48787 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sun, 5 Mar 2023 11:22:08 +0100
Subject: [PATCH 175/905] ci: fixes theme preview action (#2566)
---
scripts/preview-theme.js | 44 ++++++++++++++++++++++++++++++----------
1 file changed, 33 insertions(+), 11 deletions(-)
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index c0bb9eb5522d8..3179780d8438c 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -143,15 +143,36 @@ const findComment = async (octokit, issueNumber, owner, repo, commenter) => {
* Create or update the preview comment.
*
* @param {Object} octokit Octokit instance.
- * @param {Object} props Comment properties.
+ * @param {number} issueNumber Issue number.
+ * @param {Object} repo Repository name.
+ * @param {Object} owner Owner of the repository.
+ * @param {number} commentId Comment ID.
+ * @param {string} body Comment body.
* @return {string} The comment URL.
*/
-const upsertComment = async (octokit, props) => {
+const upsertComment = async (
+ octokit,
+ issueNumber,
+ repo,
+ owner,
+ commentId,
+ body,
+) => {
let resp;
- if (props.comment_id !== undefined) {
- resp = await octokit.issues.updateComment(props);
+ if (commentId !== undefined) {
+ resp = await octokit.issues.updateComment({
+ owner,
+ repo,
+ comment_id: commentId,
+ body,
+ });
} else {
- resp = await octokit.issues.createComment(props);
+ resp = await octokit.issues.createComment({
+ owner,
+ repo,
+ issue_number: issueNumber,
+ body,
+ });
}
return resp.data.html_url;
};
@@ -539,13 +560,14 @@ export const run = async () => {
debug("Create or update theme-preview comment...");
let comment_url;
if (!DRY_RUN) {
- comment_url = await upsertComment(OCTOKIT, {
- comment_id: comment?.id,
- issue_number: PULL_REQUEST_ID,
- OWNER,
+ comment_url = await upsertComment(
+ OCTOKIT,
+ PULL_REQUEST_ID,
REPO,
- body: commentBody,
- });
+ OWNER,
+ comment?.id,
+ commentBody,
+ );
} else {
info(`DRY_RUN: Comment body: ${commentBody}`);
comment_url = "";
From b93aee34d0101aed1de0b5d7cc68c3bb19614d52 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 6 Mar 2023 05:03:06 +0100
Subject: [PATCH 176/905] ci: improve theme preview action (#2572)
---
scripts/preview-theme.js | 41 +++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index 3179780d8438c..e18c01b8615af 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -312,18 +312,30 @@ const parseJSON = (json) => {
);
}
} catch (error) {
- let parsedJson = json
+ // Remove trailing commas (if any).
+ let parsedJson = json.replace(/(,\s*})/g, "}");
+
+ // Remove JS comments (if any).
+ parsedJson = parsedJson.replace(/\/\/[A-z\s]*\s/g, "");
+
+ // Fix incorrect open bracket (if any).
+ const splitJson = parsedJson
.split(/([\s\r\s]*}[\s\r\s]*,[\s\r\s]*)(?=[\w"-]+:)/)
- .filter((x) => typeof x !== "string" || !!x.trim());
- if (parsedJson[0].replace(/\s+/g, "") === "},") {
- parsedJson[0] = "},";
- if (!/\s*}\s*,?\s*$/.test(parsedJson[1])) {
- parsedJson.push(parsedJson.shift());
+ .filter((x) => typeof x !== "string" || !!x.trim()); // Split json into array of strings and objects.
+ if (splitJson[0].replace(/\s+/g, "") === "},") {
+ splitJson[0] = "},";
+ if (!/\s*}\s*,?\s*$/.test(splitJson[1])) {
+ splitJson.push(splitJson.shift());
} else {
- parsedJson.shift();
+ splitJson.shift();
}
- return Hjson.parse(parsedJson.join(""));
- } else {
+ parsedJson = splitJson.join("");
+ }
+
+ // Try to parse the fixed json.
+ try {
+ return Hjson.parse(parsedJson);
+ } catch (error) {
throw new IncorrectJsonFormatError(
`Theme JSON file could not be parsed: ${error.message}`,
);
@@ -387,10 +399,17 @@ export const run = async () => {
// Retrieve theme changes from the PR diff.
debug("Retrieve themes...");
const diff = parse(res.data);
+
+ // Retrieve all theme changes from the PR diff and convert to JSON.
+ debug("Retrieve theme changes...");
const content = diff
.find((file) => file.to === "themes/index.js")
- .chunks[0].changes.filter((c) => c.type === "add")
- .map((c) => c.content.replace("+", ""))
+ .chunks.map((chunk) =>
+ chunk.changes
+ .filter((c) => c.type === "add")
+ .map((c) => c.content.replace("+", ""))
+ .join(""),
+ )
.join("");
const themeObject = parseJSON(content);
if (
From c5063b92b6e260dcc405a0a4cd27552dc103f8f5 Mon Sep 17 00:00:00 2001
From: Etanarvazac Revorix
Date: Tue, 7 Mar 2023 20:06:04 -0500
Subject: [PATCH 177/905] Added "Shadow" set (Red, Green, Blue, transparent BG)
(#2529)
* Added "Shadow" set (Red, Green, Blue, transparent BG)
3 additional themes sticking primarily to flat colors, which the exception of icons and border being slightly darker. All 3 themes also have transparent backgrounds that will show differently per-user via GiHub's own light and dark themes. Transparency should also still provide easy readability for both.
* Test
Just want to see if we can make the themes have a transparent background.
* Shadows moved under Transparent
---------
Co-authored-by: Zohan Subhash
---
themes/index.js | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/themes/index.js b/themes/index.js
index 01c9a8eee79d6..d348a2ba1a769 100644
--- a/themes/index.js
+++ b/themes/index.js
@@ -18,6 +18,27 @@ export const themes = {
text_color: "417E87",
bg_color: "ffffff00",
},
+ shadow_red: {
+ title_color: "9A0000",
+ text_color: "444",
+ icon_color: "4F0000",
+ border_color: "4F0000",
+ bg_color: "ffffff00",
+ },
+ shadow_green: {
+ title_color: "007A00",
+ text_color: "444",
+ icon_color: "003D00",
+ border_color: "003D00",
+ bg_color: "ffffff00",
+ },
+ shadow_blue: {
+ title_color: "00779A",
+ text_color: "444",
+ icon_color: "004450",
+ border_color: "004490",
+ bg_color: "ffffff00",
+ },
dark: {
title_color: "fff",
icon_color: "79ff97",
From 2bd9d457ac7f10bd5f1303c6a14f3ec22c2ee9c6 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Thu, 9 Mar 2023 09:45:50 +0000
Subject: [PATCH 178/905] ci: fix theme docs generate bug (#2573)
---
scripts/push-theme-readme.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/scripts/push-theme-readme.sh b/scripts/push-theme-readme.sh
index 1ab5de474ea5a..132a4b508e8e4 100755
--- a/scripts/push-theme-readme.sh
+++ b/scripts/push-theme-readme.sh
@@ -6,6 +6,7 @@ export BRANCH_NAME=updated-theme-readme
git --version
git config --global user.email "no-reply@githubreadmestats.com"
git config --global user.name "GitHub Readme Stats Bot"
+git config --global --add safe.directory ${GITHUB_WORKSPACE}
git branch -d $BRANCH_NAME || true
git checkout -b $BRANCH_NAME
git add --all
From 32998295b7ef9742ea0168213807d7e8ec5c72a6 Mon Sep 17 00:00:00 2001
From: Eduardo Zaniboni <67515606+eduardozaniboni@users.noreply.github.com>
Date: Tue, 14 Mar 2023 06:12:29 -0300
Subject: [PATCH 179/905] update my theme (#2576)
---
themes/index.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/themes/index.js b/themes/index.js
index d348a2ba1a769..0121cf0bc14d1 100644
--- a/themes/index.js
+++ b/themes/index.js
@@ -409,7 +409,7 @@ export const themes = {
border_color: "e9d8d4",
bg_color: "e9d8d4",
},
- holi_theme: {
+ holi: {
title_color: "5FABEE",
text_color: "D6E7FF",
icon_color: "5FABEE",
From b928f51442ff224507f519ceaca67d09afffa2b1 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 31 Mar 2023 06:40:22 +0530
Subject: [PATCH 180/905] refactor: update languages JSON (#2596)
Co-authored-by: rickstaa
---
src/common/languageColors.json | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/common/languageColors.json b/src/common/languageColors.json
index b50cba6f30b08..3937eec5a2bf5 100644
--- a/src/common/languageColors.json
+++ b/src/common/languageColors.json
@@ -133,6 +133,7 @@
"Elixir": "#6e4a7e",
"Elm": "#60B5CC",
"Elvish": "#55BB55",
+ "Elvish Transcript": "#55BB55",
"Emacs Lisp": "#c065db",
"EmberScript": "#FFF4F3",
"Erlang": "#B83998",
@@ -453,6 +454,7 @@
"Smalltalk": "#596706",
"Smarty": "#f0c040",
"Smithy": "#c44536",
+ "Snakemake": "#419179",
"Solidity": "#AA6746",
"SourcePawn": "#f69e1d",
"Squirrel": "#800000",
@@ -466,6 +468,7 @@
"SugarSS": "#2fcc9f",
"SuperCollider": "#46390b",
"Svelte": "#ff3e00",
+ "Sway": "#dea584",
"Swift": "#F05138",
"SystemVerilog": "#DAE1C2",
"TI Program": "#A0AA87",
From d8244a7fe5eaffaf7264e592290b9b1f9aaf849d Mon Sep 17 00:00:00 2001
From: Caeden Perelli-Harris
Date: Sat, 1 Apr 2023 05:47:56 +0100
Subject: [PATCH 181/905] Add format stats option (#2155)
* feat: added `format_stats` option (#2128)
* refactor: change `format_stats` to `short_values` (#2128)
* test: create shorten values test (#2128)
* Update readme.md
Co-authored-by: Rick Staa
* refactor: rename ``short_values`` to ``number_format``
* Update readme.md
Co-authored-by: Rick Staa
* Update src/cards/stats-card.js
Co-authored-by: Rick Staa
* refactor: format codebase
---------
Co-authored-by: Rick Staa
---
api/index.js | 2 ++
readme.md | 1 +
src/cards/stats-card.js | 6 +++++-
src/cards/types.d.ts | 1 +
tests/renderStatsCard.test.js | 9 +++++++++
5 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/api/index.js b/api/index.js
index b449d43b49080..e89c74688d116 100644
--- a/api/index.js
+++ b/api/index.js
@@ -35,6 +35,7 @@ export default async (req, res) => {
locale,
disable_animations,
border_radius,
+ number_format,
border_color,
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
@@ -88,6 +89,7 @@ export default async (req, res) => {
custom_title,
border_radius,
border_color,
+ number_format,
locale: locale ? locale.toLowerCase() : null,
disable_animations: parseBoolean(disable_animations),
}),
diff --git a/readme.md b/readme.md
index 7a60228460126..91a1cfa9f8870 100644
--- a/readme.md
+++ b/readme.md
@@ -289,6 +289,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `text_bold` - Use bold text _(boolean)_. Default: `true`.
- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
- `ring_color` - Color of the rank circle _(hex color)_. Defaults to the theme ring color if it exists and otherwise the title color.
+- `number_format` - Switch between two available formats for displaying the card values `short` (i.e. `6.6k`) and `long` (i.e. `6626`). Default: `short`.
> **Note**
> When hide_rank=`true`, the minimum card width is 270 px + the title length and padding.
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index f39a968f18065..c60ea51d5119c 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -39,8 +39,10 @@ const createTextNode = ({
showIcons,
shiftValuePos,
bold,
+ number_format,
}) => {
- const kValue = kFormatter(value);
+ const kValue =
+ number_format.toLowerCase() === "long" ? value : kFormatter(value);
const staggerDelay = (index + 3) * 150;
const labelOffset = showIcons ? `x="25"` : "";
@@ -103,6 +105,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
custom_title,
border_radius,
border_color,
+ number_format = "short",
locale,
disable_animations = false,
} = options;
@@ -192,6 +195,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
showIcons: show_icons,
shiftValuePos: 79.01 + (isLongLocale ? 50 : 0),
bold: text_bold,
+ number_format,
}),
);
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index 52ee0edb6a459..a3abc23e98a36 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -22,6 +22,7 @@ export type StatCardOptions = CommonOptions & {
line_height: number | string;
custom_title: string;
disable_animations: boolean;
+ number_format: string;
};
export type RepoCardOptions = CommonOptions & {
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 748b7a32cd32b..110121ac9e4b6 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -357,4 +357,13 @@ describe("Test renderStatsCard", () => {
document.body.innerHTML = renderStatsCard(stats, {});
expect(document.querySelector("rect")).toHaveAttribute("rx", "4.5");
});
+
+ it("should shorten values", () => {
+ stats["totalCommits"] = 1999;
+
+ document.body.innerHTML = renderStatsCard(stats);
+ expect(getByTestId(document.body, "commits").textContent).toBe("2k");
+ document.body.innerHTML = renderStatsCard(stats, { number_format: "long" });
+ expect(getByTestId(document.body, "commits").textContent).toBe("1999");
+ });
});
From 4d1d83d5e5691a5aaa8a65d230924d6072bbc16d Mon Sep 17 00:00:00 2001
From: Fabiano Couto
Date: Sat, 1 Apr 2023 08:22:00 -0300
Subject: [PATCH 182/905] add github_dark_dimmed theme (#2594)
* feat(theme): add github_dark_dimmed theme
* feat(theme): change github_dark_dimmed icon color
* contrast ratio adjustment
contrast ratio adjustment on github_dark_dimmed theme
* feat(theme): readme preview
* feat(theme): github themes next to each other
* github themes next to each other
---
themes/README.md | 14 ++++++++------
themes/index.js | 7 +++++++
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/themes/README.md b/themes/README.md
index b8649d43b9564..5993b6a07a9b8 100644
--- a/themes/README.md
+++ b/themes/README.md
@@ -32,10 +32,11 @@ Use `?theme=THEME_NAME` parameter like so :-
| `jolly` ![jolly][jolly] | `maroongold` ![maroongold][maroongold] | `yeblu` ![yeblu][yeblu] |
| `blueberry` ![blueberry][blueberry] | `slateorange` ![slateorange][slateorange] | `kacho_ga` ![kacho_ga][kacho_ga] |
| `outrun` ![outrun][outrun] | `ocean_dark` ![ocean_dark][ocean_dark] | `city_lights` ![city_lights][city_lights] |
-| `github_dark` ![github_dark][github_dark] | `discord_old_blurple` ![discord_old_blurple][discord_old_blurple] | `aura_dark` ![aura_dark][aura_dark] |
+| `github_dark` ![github_dark][github_dark] | `github_dark_dimmed` ![github_dark_dimmed][github_dark_dimmed] | `discord_old_blurple` ![discord_old_blurple][discord_old_blurple] |
| `panda` ![panda][panda] | `noctis_minimus` ![noctis_minimus][noctis_minimus] | `cobalt2` ![cobalt2][cobalt2] |
| `swift` ![swift][swift] | `aura` ![aura][aura] | `apprentice` ![apprentice][apprentice] |
| `moltack` ![moltack][moltack] | `codeSTACKr` ![codeSTACKr][codeSTACKr] | `rose_pine` ![rose_pine][rose_pine] |
+| `aura_dark` ![aura_dark][aura_dark] | | |
| [Add your theme][add-theme] | | |
## Repo Card
@@ -60,10 +61,11 @@ Use `?theme=THEME_NAME` parameter like so :-
| `jolly` ![jolly][jolly_repo] | `maroongold` ![maroongold][maroongold_repo] | `yeblu` ![yeblu][yeblu_repo] |
| `blueberry` ![blueberry][blueberry_repo] | `slateorange` ![slateorange][slateorange_repo] | `kacho_ga` ![kacho_ga][kacho_ga_repo] |
| `outrun` ![outrun][outrun_repo] | `ocean_dark` ![ocean_dark][ocean_dark_repo] | `city_lights` ![city_lights][city_lights_repo] |
-| `github_dark` ![github_dark][github_dark_repo] | `discord_old_blurple` ![discord_old_blurple][discord_old_blurple_repo] | `aura_dark` ![aura_dark][aura_dark_repo] |
+| `github_dark` ![github_dark][github_dark_repo] | `github_dark_dimmed` ![github_dark_dimmed][github_dark_dimmed_repo] | `discord_old_blurple` ![discord_old_blurple][discord_old_blurple_repo] |
| `panda` ![panda][panda_repo] | `noctis_minimus` ![noctis_minimus][noctis_minimus_repo] | `cobalt2` ![cobalt2][cobalt2_repo] |
| `swift` ![swift][swift_repo] | `aura` ![aura][aura_repo] | `apprentice` ![apprentice][apprentice_repo] |
| `moltack` ![moltack][moltack_repo] | `codeSTACKr` ![codeSTACKr][codeSTACKr_repo] | `rose_pine` ![rose_pine][rose_pine_repo] |
+| `aura_dark` ![aura_dark][aura_dark_repo] | | |
| [Add your theme][add-theme] | | |
@@ -117,8 +119,8 @@ Use `?theme=THEME_NAME` parameter like so :-
[ocean_dark]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=ocean_dark
[city_lights]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=city_lights
[github_dark]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=github_dark
+[github_dark_dimmed]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=github_dark_dimmed
[discord_old_blurple]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=discord_old_blurple
-[aura_dark]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=aura_dark
[panda]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=panda
[noctis_minimus]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=noctis_minimus
[cobalt2]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=cobalt2
@@ -128,7 +130,7 @@ Use `?theme=THEME_NAME` parameter like so :-
[moltack]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=moltack
[codeSTACKr]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=codeSTACKr
[rose_pine]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=rose_pine
-
+[aura_dark]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=aura_dark
[default_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=default
[default_repocard_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=default_repocard
@@ -180,8 +182,8 @@ Use `?theme=THEME_NAME` parameter like so :-
[ocean_dark_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=ocean_dark
[city_lights_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=city_lights
[github_dark_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=github_dark
+[github_dark_dimmed_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=github_dark_dimmed
[discord_old_blurple_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=discord_old_blurple
-[aura_dark_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=aura_dark
[panda_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=panda
[noctis_minimus_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=noctis_minimus
[cobalt2_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=cobalt2
@@ -191,7 +193,7 @@ Use `?theme=THEME_NAME` parameter like so :-
[moltack_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=moltack
[codeSTACKr_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=codeSTACKr
[rose_pine_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=rose_pine
-
+[aura_dark_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=aura_dark
[add-theme]: https://github.com/anuraghazra/github-readme-stats/edit/master/themes/index.js
diff --git a/themes/index.js b/themes/index.js
index 0121cf0bc14d1..ab8eab6a0d0e9 100644
--- a/themes/index.js
+++ b/themes/index.js
@@ -321,6 +321,13 @@ export const themes = {
text_color: "C3D1D9",
bg_color: "0D1117",
},
+ github_dark_dimmed: {
+ title_color: "539bf5",
+ icon_color: "539bf5",
+ text_color: "ADBAC7",
+ bg_color: "24292F",
+ border_color: "373E47",
+ },
discord_old_blurple: {
title_color: "7289DA",
icon_color: "7289DA",
From 879937c11d08154f9afa0de7dab7b4945e452276 Mon Sep 17 00:00:00 2001
From: Fabiano Couto
Date: Mon, 24 Apr 2023 10:56:14 -0300
Subject: [PATCH 183/905] feat(RankIcon): add rank_icon option (#2628)
* feat(theme): add github_dark_dimmed theme
* feat(theme): change github_dark_dimmed icon color
* contrast ratio adjustment
contrast ratio adjustment on github_dark_dimmed theme
* feat(theme): readme preview
* feat(theme): github themes next to each other
* github themes next to each other
* feat(RankIcon): add rank icon option
* feat(RankIcon): extract rankIcon to icons file
* feat(RankIcon): update readme
* feat(RankIcon): test coverage
* Update readme.md
Co-authored-by: Rick Staa
---------
Co-authored-by: Rick Staa
---
api/index.js | 2 ++
readme.md | 13 +++++++++----
src/cards/stats-card.js | 13 +++----------
src/cards/types.d.ts | 4 ++++
src/common/icons.js | 25 ++++++++++++++++++++++++-
tests/renderStatsCard.test.js | 17 +++++++++++++++++
6 files changed, 59 insertions(+), 15 deletions(-)
diff --git a/api/index.js b/api/index.js
index e89c74688d116..29ff87f9af863 100644
--- a/api/index.js
+++ b/api/index.js
@@ -37,6 +37,7 @@ export default async (req, res) => {
border_radius,
number_format,
border_color,
+ rank_icon,
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
@@ -92,6 +93,7 @@ export default async (req, res) => {
number_format,
locale: locale ? locale.toLowerCase() : null,
disable_animations: parseBoolean(disable_animations),
+ rank_icon,
}),
);
} catch (err) {
diff --git a/readme.md b/readme.md
index 91a1cfa9f8870..fe04a88e81bba 100644
--- a/readme.md
+++ b/readme.md
@@ -216,10 +216,10 @@ You can use [GitHub's theme context](https://github.blog/changelog/2021-11-24-sp
##### Use GitHub's new media feature
You can use [GitHub's new media feature](https://github.blog/changelog/2022-05-19-specify-theme-context-for-images-in-markdown-beta/) in HTML to specify whether to display images for light or dark themes. This is done using the HTML `` element in combination with the `prefers-color-scheme` media feature.
-
+
```html
-
@@ -235,7 +235,7 @@ You can use [GitHub's new media feature](https://github.blog/changelog/2022-05-1
:eyes: Show example
-
@@ -260,7 +260,7 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you
- `border_color` - Card's border color _(hex color)_. Default: `e4e2e2` (Does not apply when `hide_border` is enabled).
- `bg_color` - Card's background color _(hex color)_ **or** a gradient in the form of _angle,start,end_. Default: `fffefe`
- `hide_border` - Hides the card's border _(boolean)_. Default: `false`
-- `theme` - name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme.
+- `theme` - name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme.
- `cache_seconds` - set the cache header manually _(min: 14400, max: 86400)_. Default: `14400 seconds (4 hours)`.
- `locale` - set the language in the card _(e.g. cn, de, es, etc.)_. Default: `en`.
- `border_radius` - Corner rounding on the card. Default: `4.5`.
@@ -280,6 +280,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `hide_title` - _(boolean)_. Default: `false`.
- `card_width` - Set the card's width manually _(number)_. Default: `500px (approx.)`.
- `hide_rank` - _(boolean)_ hides the rank and automatically resizes the card width. Default: `false`.
+- `rank_icon` - Shows alternative rank icon (i.e. `github` or `default`). Default: `default`.
- `show_icons` - _(boolean)_. Default: `false`.
- `include_all_commits` - Count total commits instead of just the current year commits _(boolean)_. Default: `false`.
- `count_private` - Count private commits _(boolean)_. Default: `false`.
@@ -459,6 +460,10 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&hide=issues&show_icons=true)
+- Shows Github logo instead rank level
+
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&rank_icon=github)
+
- Customize Border Color
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&border_color=2e4058)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index c60ea51d5119c..cdb468d301f78 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -1,7 +1,7 @@
// @ts-check
import { Card } from "../common/Card.js";
import { I18n } from "../common/I18n.js";
-import { icons } from "../common/icons.js";
+import { icons, rankIcon } from "../common/icons.js";
import {
clampValue,
flexLayout,
@@ -108,6 +108,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
number_format = "short",
locale,
disable_animations = false,
+ rank_icon = "default",
} = options;
const lheight = parseInt(String(line_height), 10);
@@ -294,15 +295,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
-
- ${rank.level}
-
+ ${rankIcon(rank_icon, rank?.level)}
`;
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index a3abc23e98a36..02a41b5769387 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -1,4 +1,5 @@
type ThemeNames = keyof typeof import("../../themes/index.js");
+type RankIcon = "default" | "github";
export type CommonOptions = {
title_color: string;
@@ -23,6 +24,9 @@ export type StatCardOptions = CommonOptions & {
custom_title: string;
disable_animations: boolean;
number_format: string;
+ ring_color: string;
+ text_bold: boolean;
+ rank_icon: RankIcon;
};
export type RepoCardOptions = CommonOptions & {
diff --git a/src/common/icons.js b/src/common/icons.js
index 5282a93ec8725..948ca0bc427d1 100644
--- a/src/common/icons.js
+++ b/src/common/icons.js
@@ -8,5 +8,28 @@ const icons = {
fork: ``,
};
-export { icons };
+/**
+ * Get rank icon
+ *
+ * @returns {string} - The SVG code of the rank icon
+ */
+const rankIcon = (rankIcon, rankLevel) => {
+ switch (rankIcon) {
+ case "github":
+ return `
+
+
+
+ `;
+ case "default":
+ default:
+ return `
+
+ ${rankLevel}
+
+ `;
+ }
+};
+
+export { icons, rankIcon };
export default icons;
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 110121ac9e4b6..25c5feb604864 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -366,4 +366,21 @@ describe("Test renderStatsCard", () => {
document.body.innerHTML = renderStatsCard(stats, { number_format: "long" });
expect(getByTestId(document.body, "commits").textContent).toBe("1999");
});
+
+ it("should render default rank icon with level A+", () => {
+ document.body.innerHTML = renderStatsCard(stats, {
+ rank_icon: "default",
+ });
+ expect(queryByTestId(document.body, "level-rank-icon")).toBeDefined();
+ expect(
+ queryByTestId(document.body, "level-rank-icon").textContent.trim(),
+ ).toBe("A+");
+ });
+
+ it("should render github rank icon", () => {
+ document.body.innerHTML = renderStatsCard(stats, {
+ rank_icon: "github",
+ });
+ expect(queryByTestId(document.body, "github-rank-icon")).toBeDefined();
+ });
});
From aec73d293ec6a8523b8889811d2e38f4cd3bc261 Mon Sep 17 00:00:00 2001
From: LOKESH SINGH <77314004+LokeshXs@users.noreply.github.com>
Date: Mon, 24 Apr 2023 23:54:05 +0530
Subject: [PATCH 184/905] Updated the custom error there was a Typo. (#2618)
"Something went while trying to retrieve the stats data using the GraphQL API." -> "Something went wrong while trying to retrieve the stats data using the GraphQL API."
---
src/fetchers/stats-fetcher.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index a7df1e504db2f..fc06fce15fa86 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -213,7 +213,7 @@ const fetchStats = async (
);
}
throw new CustomError(
- "Something went while trying to retrieve the stats data using the GraphQL API.",
+ "Something went wrong while trying to retrieve the stats data using the GraphQL API.",
CustomError.GRAPHQL_ERROR,
);
}
From be0d96615d9ae3cf4b4fc6cc07921ddca7efae11 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Mon, 24 Apr 2023 21:24:41 +0300
Subject: [PATCH 185/905] Fix typos inside wakatime test name (#2617)
---
tests/renderWakatimeCard.test.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/renderWakatimeCard.test.js b/tests/renderWakatimeCard.test.js
index 67969bef50063..25e7ab4d802cd 100644
--- a/tests/renderWakatimeCard.test.js
+++ b/tests/renderWakatimeCard.test.js
@@ -55,7 +55,7 @@ describe("Test Render Wakatime Card", () => {
expect(document.querySelector("rect")).toHaveAttribute("rx", "4.5");
});
- it('should show "no coding activitiy this week" message when there hasn not been activity', () => {
+ it('should show "no coding activity this week" message when there has not been activity', () => {
document.body.innerHTML = renderWakatimeCard(
{
...wakaTimeData.data,
From da5f82ff02c203a493abd1778715f0f498f7c37d Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Tue, 25 Apr 2023 09:15:16 +0300
Subject: [PATCH 186/905] removed redundant comparison (#957)
---
src/cards/stats-card.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index cdb468d301f78..92701d8103c95 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -183,7 +183,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
"nl",
"zh-tw",
];
- const isLongLocale = longLocales.includes(locale) === true;
+ const isLongLocale = longLocales.includes(locale);
// filter out hidden stats defined by user & create the text nodes
const statItems = Object.keys(STATS)
From 8aacec098ba92e697c9ec3b5b1b67657bfaf366e Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Tue, 25 Apr 2023 09:16:37 +0300
Subject: [PATCH 187/905] dev (#1782)
---
docs/readme_cn.md | 2 ++
docs/readme_de.md | 2 ++
docs/readme_fr.md | 2 ++
docs/readme_it.md | 2 ++
docs/readme_ja.md | 2 ++
docs/readme_kr.md | 2 ++
docs/readme_nl.md | 2 ++
docs/readme_np.md | 4 ++++
8 files changed, 18 insertions(+)
diff --git a/docs/readme_cn.md b/docs/readme_cn.md
index 17fd2b710f220..f04324c9f4452 100644
--- a/docs/readme_cn.md
+++ b/docs/readme_cn.md
@@ -53,6 +53,8 @@
Nederlands
.
नेपाली
+ .
+ Türkçe
喜欢这个项目?请考虑捐赠来帮助它完善!
diff --git a/docs/readme_de.md b/docs/readme_de.md
index 55523fe342ef0..87f68faa7465a 100644
--- a/docs/readme_de.md
+++ b/docs/readme_de.md
@@ -54,6 +54,8 @@
Nederlands
.
नेपाली
+ .
+ Türkçe
Du magst das Projekt? Wie wäre es mit einer kleinen Spende um es weiterhin am Leben zu erhalten?
diff --git a/docs/readme_fr.md b/docs/readme_fr.md
index 20996bd66dda8..bf0ab9811b4b0 100644
--- a/docs/readme_fr.md
+++ b/docs/readme_fr.md
@@ -53,6 +53,8 @@
Nederlands
.
नेपाली
+ .
+ Türkçe
Vous aimez ce projet? Pensez à faire un don pour l'améliorer!
diff --git a/docs/readme_it.md b/docs/readme_it.md
index 1b2df96a5044d..05aa3e5c526ae 100644
--- a/docs/readme_it.md
+++ b/docs/readme_it.md
@@ -53,6 +53,8 @@
Nederlands
.
नेपाली
+ .
+ Türkçe
Se ti piace questo progetto, considera la possibilità di donare per aiutare a renderlo migliore!
diff --git a/docs/readme_ja.md b/docs/readme_ja.md
index b00c77a7712a1..0318984e40b97 100644
--- a/docs/readme_ja.md
+++ b/docs/readme_ja.md
@@ -53,6 +53,8 @@
Nederlands
.
नेपाली
+ .
+ Türkçe
diff --git a/docs/readme_kr.md b/docs/readme_kr.md
index ce0b4ad0379ee..1d64d50d2c0b7 100644
--- a/docs/readme_kr.md
+++ b/docs/readme_kr.md
@@ -53,6 +53,8 @@
Nederlands
.
नेपाली
+ .
+ Türkçe
기능들이 마음에 드시나요? 괜찮으시다면, 서비스 개선을 위해 기부를 고려해주세요!
diff --git a/docs/readme_nl.md b/docs/readme_nl.md
index 597f0c86445e3..bab581762572c 100644
--- a/docs/readme_nl.md
+++ b/docs/readme_nl.md
@@ -53,6 +53,8 @@
Nederlands
.
नेपाली
+ .
+ Türkçe
Bevalt het project? Doneer om het te verbeteren!
diff --git a/docs/readme_np.md b/docs/readme_np.md
index 654427fbda654..510e836f2d8b6 100644
--- a/docs/readme_np.md
+++ b/docs/readme_np.md
@@ -49,8 +49,12 @@
Italiano
·
한국어
+ .
+ Nederlands
·
नेपाली
+ .
+ Türkçe
परियोजना मनपर्यो? तपाईं मद्दत गर्न सक्नुहुन्छ यो परियोजना बढ्न
From 21a9ba4faeae5072f5c46009ab2f11bc3258508b Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Tue, 25 Apr 2023 09:17:10 +0300
Subject: [PATCH 188/905] fix path to powered by vercel image (#1792)
---
docs/readme_tr.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/readme_tr.md b/docs/readme_tr.md
index 7b11cf3706f1e..4e67c7ed00f13 100644
--- a/docs/readme_tr.md
+++ b/docs/readme_tr.md
@@ -409,7 +409,7 @@ Teşekkürler! :heart:
---
-[![https://vercel.com?utm_source=github_readme_stats_team&utm_campaign=oss](./powered-by-vercel.svg)](https://vercel.com?utm_source=github_readme_stats_team&utm_campaign=oss)
+[![https://vercel.com?utm_source=github_readme_stats_team&utm_campaign=oss](../powered-by-vercel.svg)](https://vercel.com?utm_source=github_readme_stats_team&utm_campaign=oss)
Katkılara açığız! <3
From da46a5093cd0f6c4a537196cb9e67865bbbe3aed Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Tue, 25 Apr 2023 09:17:50 +0300
Subject: [PATCH 189/905] Synchonize cache seconds min value inside docs
translations with main readme (#2616)
---
docs/readme_cn.md | 2 +-
docs/readme_de.md | 2 +-
docs/readme_es.md | 2 +-
docs/readme_fr.md | 2 +-
docs/readme_it.md | 2 +-
docs/readme_ja.md | 2 +-
docs/readme_kr.md | 2 +-
docs/readme_nl.md | 2 +-
docs/readme_np.md | 2 +-
docs/readme_pt-BR.md | 2 +-
docs/readme_tr.md | 2 +-
11 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/docs/readme_cn.md b/docs/readme_cn.md
index f04324c9f4452..d6487b6618264 100644
--- a/docs/readme_cn.md
+++ b/docs/readme_cn.md
@@ -140,7 +140,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
- `bg_color` - 卡片背景颜色 _(十六进制色码)_ **或者** 以 _angle,start,end_ 的形式渐变
- `hide_border` - 隐藏卡的边框 _(布尔值)_
- `theme` - 主题名称,从[所有可用主题](../themes/README.md)中选择
-- `cache_seconds` - 手动设置缓存头 _(最小值: 1800,最大值: 86400)_
+- `cache_seconds` - 手动设置缓存头 _(最小值: 14400,最大值: 86400)_
- `locale` - 在卡片中设置语言 _(例如 cn, de, es, 等等)_
##### bg_color 渐变
diff --git a/docs/readme_de.md b/docs/readme_de.md
index 87f68faa7465a..8756670eaf4b9 100644
--- a/docs/readme_de.md
+++ b/docs/readme_de.md
@@ -130,7 +130,7 @@ Du kannst das Erscheinungsbild deiner `Stats Card` oder `Repo Card`, mithilfe vo
- `bg_color` - Hintergrundfarbe _(hex color)_ **oder** ein Farbverlauf in der Form von _winkel,start,ende_
- `hide_border` - Blendet den Rand der Karte aus _(Boolean)_
- `theme` - Name des Erscheinungsbildes/Themes [alle verfügbaren Themes](../themes/README.md)
-- `cache_seconds` - manuelles festlegen der Cachezeiten _(min: 1800, max: 86400)_
+- `cache_seconds` - manuelles festlegen der Cachezeiten _(min: 14400, max: 86400)_
- `locale` - Stellen Sie die Sprache auf der Karte ein _(z.B. cn, de, es, etc.)_
##### Farbverlauf in bg_color
diff --git a/docs/readme_es.md b/docs/readme_es.md
index 5ddceec7b5e99..b477e5c729cab 100644
--- a/docs/readme_es.md
+++ b/docs/readme_es.md
@@ -142,7 +142,7 @@ Puedes personalizar el aspecto de tu `Tarjeta de Estadísticas` o `Tarjeta de Re
- `bg_color` - Color de fondo _(hex color)_
- `hide_border` - Oculta el borde de la tarjeta _(booleano)_
- `theme` - Nombre del tema, elige uno de [todos los temas disponible ](../themes/README.md)
-- `cache_seconds` - Cache _(min: 1800, max: 86400)_
+- `cache_seconds` - Cache _(min: 14400, max: 86400)_
- `locale` - configurar el idioma en la tarjeta _(p.ej. cn, de, es, etc.)_
##### Gradiente en `bg_color`
diff --git a/docs/readme_fr.md b/docs/readme_fr.md
index bf0ab9811b4b0..ce0d3d495cc10 100644
--- a/docs/readme_fr.md
+++ b/docs/readme_fr.md
@@ -140,7 +140,7 @@ Vous pouvez personnaliser l'apparence de votre `Carte des stats` ou `Carte de d
- `bg_color` - Couleur du fond de la carte _(hex color)_ **ou** un gradiant de la forme _angle,start,end_
- `hide_border` - Cache la bordure de la carte _(booléen)_
- `theme` - Nom du thème, parmis [tous les thèmes disponibles](../themes/README.md)
-- `cache_seconds` - Paramétrer le cache manuellement _(min: 1800, max: 86400)_
+- `cache_seconds` - Paramétrer le cache manuellement _(min: 14400, max: 86400)_
- `locale` - définir la langue de la carte _(par exemple. cn, de, es, etc.)_
##### Gradient in bg_color
diff --git a/docs/readme_it.md b/docs/readme_it.md
index 05aa3e5c526ae..e54af7dc488ad 100644
--- a/docs/readme_it.md
+++ b/docs/readme_it.md
@@ -140,7 +140,7 @@ Puoi personalizzare l'aspetto delle tue `Stats Card` o delle `Repo Card` in qual
- `bg_color` - Colore dello sfondo _(in esadecimale)_ **oppure** un gradiente nella forma _angolo,inizio,fine_
- `hide_border` - Nasconde il bordo della carta _(booleano)_
- `theme` - Nome del tema, dai un'occhiata a [tutti i temi disponibili](../themes/README.md)
-- `cache_seconds` - Specifica manualmente il valore di cache, in secondi _(min: 1800, max: 86400)_
+- `cache_seconds` - Specifica manualmente il valore di cache, in secondi _(min: 14400, max: 86400)_
- `locale` - Impostare la lingua nella scheda _(per esempio. cn, de, es, eccetera.)_
##### Gradiente nello sfondo
diff --git a/docs/readme_ja.md b/docs/readme_ja.md
index 0318984e40b97..2c2def7fca1a6 100644
--- a/docs/readme_ja.md
+++ b/docs/readme_ja.md
@@ -141,7 +141,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
- `bg_color` - 背景の色 _(16 進数カラーコード)_ **または** _angle,start,end_ の形式でグラデーションを指定することも可
- `hide_border` - カードの境界線を非表示にします _(ブール値)_
- `theme` - [使用可能なテーマ一覧](../themes/README.md) から選んだテーマ名
-- `cache_seconds` - キャッシュ時間の秒数 _(最小値: 1800, 最大値: 86400)_
+- `cache_seconds` - キャッシュ時間の秒数 _(最小値: 14400, 最大値: 86400)_
- `locale` - カードに言語を設定する _(例えば cn, de, es, 等)_
##### bg_color の グラデーション指定
diff --git a/docs/readme_kr.md b/docs/readme_kr.md
index 1d64d50d2c0b7..4a1c57cc1e977 100644
--- a/docs/readme_kr.md
+++ b/docs/readme_kr.md
@@ -151,7 +151,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
- `bg_color` - 카드의 배경 색상 _(hex color)_ **혹은** 다음 양식으로 그라데이션 주기 _angle,start,end_
- `hide_border` - 카드의 테두리 표시 여부 _(boolean)_
- `theme` - 테마의 이름, [사용 가능한 모든 테마](../themes/README.md) 에서 선택
-- `cache_seconds` - 수동으로 캐시 헤더 설정 _(min: 1800, max: 86400)_
+- `cache_seconds` - 수동으로 캐시 헤더 설정 _(min: 14400, max: 86400)_
- `locale` - 카드에 표시할 언어 _(e.g. kr, cn, de, es, etc.)_
##### 배경에 그라데이션 주기
diff --git a/docs/readme_nl.md b/docs/readme_nl.md
index bab581762572c..b279c4f71fff4 100644
--- a/docs/readme_nl.md
+++ b/docs/readme_nl.md
@@ -144,7 +144,7 @@ Je kan het uiterlijk van je `Statistieken kaart` of `Repo kaart` aanpassen hoe j
- `bg_color` - Achtergrond kleur van de kaart _(hex kleur)_ **of** een verloop van kleuren in het formaat van _graden,start,einde_
- `hide_border` - Verbergt de rand van de kaart _(boolean)_
- `theme` - Naam van het thema, kies uit [alle beschikbare thema\'s](../themes/README.md)
-- `cache_seconds` - Stel de cache header handmatig in _(min: 1800, max: 86400)_
+- `cache_seconds` - Stel de cache header handmatig in _(min: 14400, max: 86400)_
- `locale` - Stel taal van de kaart in _(e.g. cn, de, es, etc.)_
##### Kleurenverloop in bg_color (achtergrond kleur):
diff --git a/docs/readme_np.md b/docs/readme_np.md
index 510e836f2d8b6..e90ee57bfe6b3 100644
--- a/docs/readme_np.md
+++ b/docs/readme_np.md
@@ -142,7 +142,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
- `bg_color` - Card's background color _(hex color)_ **or** a gradient in the form of _angle,start,end_
- `hide_border` - Hides the card's border _(boolean)_
- `theme` - name of the theme, choose from [all available themes](./themes/README.md)
-- `cache_seconds` - set the cache header manually _(min: 1800, max: 86400)_
+- `cache_seconds` - set the cache header manually _(min: 14400, max: 86400)_
- `locale` - set the language in the card _(e.g. cn, de, es, etc.)_
##### Gradient in bg_color
diff --git a/docs/readme_pt-BR.md b/docs/readme_pt-BR.md
index 62c23dc55c7e2..1ac57716009be 100644
--- a/docs/readme_pt-BR.md
+++ b/docs/readme_pt-BR.md
@@ -141,7 +141,7 @@ Personalize a aparência do seu `Stats Card` ou `Repo Card` da maneira que desej
- `bg_color` - Cor de fundo do cartão _(hex color)_
- `hide_border` - Esconde a borda do cartão _(boleano)_
- `theme` - Nome do tema, escolha em [todos os temas disponíveis](../themes/README.md)
-- `cache_seconds` - Defina o cabeçalho do cache manualmente _(min: 1800, max: 86400)_
+- `cache_seconds` - Defina o cabeçalho do cache manualmente _(min: 14400, max: 86400)_
- `locale` - defina o idioma no cartão _(por exemplo. cn, de, es, etc.)_
> Nota sobre o cache: Cartões de repositório tem um cache padrão de 30 minutos (1800 segundos), se o número a contagem de forks e contagem de estrelas é menor que 1 mil o padrão é 2 horas (7200 segundos). Note também que o cache é limitado a um mínimo de 30 minutos e um máximo de 24 horas.
diff --git a/docs/readme_tr.md b/docs/readme_tr.md
index 4e67c7ed00f13..d8ae9778fb50c 100644
--- a/docs/readme_tr.md
+++ b/docs/readme_tr.md
@@ -143,7 +143,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
- `bg_color` - Kartın arkaplan rengi _(hex color / hex rengi)_ **ya da** gradient şeklinde _açı,başlangıç,bitiş_
- `hide_border` - Kartın çerçevelerini gizler _(boolean)_
- `theme` - Temanın rengi [tüm temalar](./themes/README.md)
-- `cache_seconds` - Manuel olarak cache'i belirleyebilirsiniz _(en az: 1800, en fazla: 86400)_
+- `cache_seconds` - Manuel olarak cache'i belirleyebilirsiniz _(en az: 14400, en fazla: 86400)_
- `locale` - Karttaki dili seçebilirsiniz _(örneğin; tr, cn, de, es, vb.)_
##### bg_color'da Gradient
From 5577bbf07fae7f0e2fcbed24042a59e5442434dc Mon Sep 17 00:00:00 2001
From: kitswas <90329875+kitswas@users.noreply.github.com>
Date: Tue, 25 Apr 2023 11:49:05 +0530
Subject: [PATCH 190/905] New top language algorithm implementation (#1732)
* Reduced vercel maxDuration
* Implemented new algorithm for Top Langs
* Revert "Reduced vercel maxDuration"
This reverts commit b0bc626efe12c738cf5005e7f11c7d2a07b6387a.
* Added documentation
* Fixed broken implementation
* Update fetchTopLanguages.test.js
Changed tests
* Now uses the general formula
The parameters p and q can be set by the user.
* Updated tests and added new test
* Added new test
New test for order by repo count.
* Updated documentation
Added explanation and examples for new options.
* Updated documentation
This was overwritten in the merge commit.
* docs: improve docs and fix tests
* Renamed parameters
Renamed `p` and `q` to `size_weight` and `count_weight`, respectively.
* Updated the documentation
Changes introduced in f2516d60a442dfdbb9e24ddda8743664bcb8064d
---------
Co-authored-by: rickstaa
---
api/top-langs.js | 4 +++
readme.md | 40 +++++++++++++++------
src/fetchers/top-languages-fetcher.js | 24 +++++++++++--
tests/fetchTopLanguages.test.js | 52 ++++++++++++++++++++++++---
4 files changed, 104 insertions(+), 16 deletions(-)
diff --git a/api/top-langs.js b/api/top-langs.js
index e67d953323441..cde0a9af08a93 100644
--- a/api/top-langs.js
+++ b/api/top-langs.js
@@ -25,6 +25,8 @@ export default async (req, res) => {
layout,
langs_count,
exclude_repo,
+ size_weight,
+ count_weight,
custom_title,
locale,
border_radius,
@@ -46,6 +48,8 @@ export default async (req, res) => {
const topLangs = await fetchTopLanguages(
username,
parseArray(exclude_repo),
+ size_weight,
+ count_weight,
);
const cacheSeconds = clampValue(
diff --git a/readme.md b/readme.md
index fe04a88e81bba..76b46e0eaefb5 100644
--- a/readme.md
+++ b/readme.md
@@ -310,6 +310,8 @@ You can provide multiple comma-separated values in the bg_color option to render
- `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`.
- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
- `hide_progress` - It uses the compact layout option, hides percentages, and removes the bars. Default: `false`.
+- `size_weight` - Configures language stats algorithm _(number)_ (see [Language stats algorithm](#Language-stats-algorithm)), defaults to 1.
+- `count_weight` - Configures language stats algorithm _(number)_ (see [Language stats algorithm](#Language-stats-algorithm)), defaults to 0.
> **Warning**
> Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
@@ -359,7 +361,25 @@ Use [show_owner](#customization) variable to include the repo's owner username
The top languages card shows a GitHub user's most frequently used top language.
> **Note**
-> Top Languages does not indicate my skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats.
+> Top Languages does not indicate the user's skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats.
+
+### Language stats algorithm
+
+We use the following algorithm to calculate the languages percentages on the language card:
+
+```js
+ranking_index = (byte_count ^ size_weight) * (repo_count ^ count_weight)
+```
+
+By default, only the byte count is used for determining the languages percentages shown on the language card (i.e. `size_weight=1` and `count_weight=0`). You can, however, use the `&size_weight=` and `&count_weight=` options to weight the language usage calculation. The values must be positive real numbers. [More details about the algorithm can be found here](https://github.com/anuraghazra/github-readme-stats/issues/1600#issuecomment-1046056305).
+
+- `&size_weight=1&count_weight=0` - _(default)_ Orders by byte count.
+- `&size_weight=0.5&count_weight=0.5` - _(recommended)_ Uses both byte and repo count for ranking
+- `&size_weight=0&count_weight=1` - Orders by repo count
+
+```md
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&size_weight=0.5&count_weight=0.5)](https://github.com/anuraghazra/github-readme-stats)
+```
### Usage
@@ -419,7 +439,7 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
-- Hidden progress bars
+- Hidden progress bars
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
@@ -564,14 +584,14 @@ Since the GitHub API only allows 5k requests per hour, my `https://github-readme
:hammer_and_wrench: Step-by-step guide for deploying on other platforms
-1. Fork or clone this repo as per your needs
-2. Add `express` to the dependencies section of `package.json`
-https://github.com/anuraghazra/github-readme-stats/blob/ba7c2f8b55eac8452e479c8bd38b044d204d0424/package.json#L54-L61
-3. Run `npm i` if needed (initial setup)
-4. Run `node express.js` to start the server, or set the entry point to `express.js` in `package.json` if you're deploying on a managed service
-https://github.com/anuraghazra/github-readme-stats/blob/ba7c2f8b55eac8452e479c8bd38b044d204d0424/package.json#L11
-5. You're done 🎉
-
+1. Fork or clone this repo as per your needs
+2. Add `express` to the dependencies section of `package.json`
+
+3. Run `npm i` if needed (initial setup)
+4. Run `node express.js` to start the server, or set the entry point to `express.js` in `package.json` if you're deploying on a managed service
+
+5. You're done 🎉
+
### Keep your fork up to date
diff --git a/src/fetchers/top-languages-fetcher.js b/src/fetchers/top-languages-fetcher.js
index 86d794435be08..45b2ba7d85183 100644
--- a/src/fetchers/top-languages-fetcher.js
+++ b/src/fetchers/top-languages-fetcher.js
@@ -54,7 +54,12 @@ const fetcher = (variables, token) => {
* @param {string[]} exclude_repo List of repositories to exclude.
* @returns {Promise} Top languages data.
*/
-const fetchTopLanguages = async (username, exclude_repo = []) => {
+const fetchTopLanguages = async (
+ username,
+ exclude_repo = [],
+ size_weight = 1,
+ count_weight = 0,
+) => {
if (!username) throw new MissingParamError(["username"]);
const res = await retryer(fetcher, { login: username });
@@ -101,6 +106,8 @@ const fetchTopLanguages = async (username, exclude_repo = []) => {
.sort((a, b) => b.size - a.size)
.filter((name) => !repoToHide[name.name]);
+ let repoCount = 0;
+
repoNodes = repoNodes
.filter((node) => node.languages.edges.length > 0)
// flatten the list of language nodes
@@ -111,9 +118,14 @@ const fetchTopLanguages = async (username, exclude_repo = []) => {
// if we already have the language in the accumulator
// & the current language name is same as previous name
- // add the size to the language size.
+ // add the size to the language size and increase repoCount.
if (acc[prev.node.name] && prev.node.name === acc[prev.node.name].name) {
langSize = prev.size + acc[prev.node.name].size;
+ repoCount += 1;
+ } else {
+ // reset repoCount to 1
+ // language must exist in at least one repo to be detected
+ repoCount = 1;
}
return {
...acc,
@@ -121,10 +133,18 @@ const fetchTopLanguages = async (username, exclude_repo = []) => {
name: prev.node.name,
color: prev.node.color,
size: langSize,
+ count: repoCount,
},
};
}, {});
+ Object.keys(repoNodes).forEach((name) => {
+ // comparison index calculation
+ repoNodes[name].size =
+ Math.pow(repoNodes[name].size, size_weight) *
+ Math.pow(repoNodes[name].count, count_weight);
+ });
+
const topLangs = Object.keys(repoNodes)
.sort((a, b) => repoNodes[b].size - repoNodes[a].size)
.reduce((result, key) => {
diff --git a/tests/fetchTopLanguages.test.js b/tests/fetchTopLanguages.test.js
index 24416cd294525..c3f558bf4236f 100644
--- a/tests/fetchTopLanguages.test.js
+++ b/tests/fetchTopLanguages.test.js
@@ -60,20 +60,22 @@ const error = {
};
describe("FetchTopLanguages", () => {
- it("should fetch correct language data", async () => {
+ it("should fetch correct language data while using the new calculation", async () => {
mock.onPost("https://api.github.com/graphql").reply(200, data_langs);
- let repo = await fetchTopLanguages("anuraghazra");
+ let repo = await fetchTopLanguages("anuraghazra", [], 0.5, 0.5);
expect(repo).toStrictEqual({
HTML: {
color: "#0f0",
+ count: 2,
name: "HTML",
- size: 200,
+ size: 20.000000000000004,
},
javascript: {
color: "#0ff",
+ count: 2,
name: "javascript",
- size: 200,
+ size: 20.000000000000004,
},
});
});
@@ -85,17 +87,59 @@ describe("FetchTopLanguages", () => {
expect(repo).toStrictEqual({
HTML: {
color: "#0f0",
+ count: 1,
name: "HTML",
size: 100,
},
javascript: {
color: "#0ff",
+ count: 2,
+ name: "javascript",
+ size: 200,
+ },
+ });
+ });
+
+ it("should fetch correct language data while using the old calculation", async () => {
+ mock.onPost("https://api.github.com/graphql").reply(200, data_langs);
+
+ let repo = await fetchTopLanguages("anuraghazra", [], 1, 0);
+ expect(repo).toStrictEqual({
+ HTML: {
+ color: "#0f0",
+ count: 2,
+ name: "HTML",
+ size: 200,
+ },
+ javascript: {
+ color: "#0ff",
+ count: 2,
name: "javascript",
size: 200,
},
});
});
+ it("should rank languages by the number of repositories they appear in", async () => {
+ mock.onPost("https://api.github.com/graphql").reply(200, data_langs);
+
+ let repo = await fetchTopLanguages("anuraghazra", [], 0, 1);
+ expect(repo).toStrictEqual({
+ HTML: {
+ color: "#0f0",
+ count: 2,
+ name: "HTML",
+ size: 2,
+ },
+ javascript: {
+ color: "#0ff",
+ count: 2,
+ name: "javascript",
+ size: 2,
+ },
+ });
+ });
+
it("should throw error", async () => {
mock.onPost("https://api.github.com/graphql").reply(200, error);
From f5f0a79bc12a35c58609f3fa6ced2f6722bbfdf1 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Fri, 28 Apr 2023 04:00:13 +0200
Subject: [PATCH 191/905] feat: improve CONTRIBUTING.md (#2609)
---
CONTRIBUTING.md | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0d4b558abe6f1..7d450d6076d8e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,11 +2,11 @@
We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
-- Reporting an issue
-- Discussing the current state of the code
-- Submitting a fix
-- Proposing new features
-- Becoming a maintainer
+- Reporting [an issue](https://github.com/anuraghazra/github-readme-stats/issues/new?assignees=&labels=bug&template=bug_report.yml).
+- [Discussing](https://github.com/anuraghazra/github-readme-stats/discussions) the current state of the code.
+- Submitting [a fix](https://github.com/anuraghazra/github-readme-stats/compare).
+- Proposing [new features](https://github.com/anuraghazra/github-readme-stats/issues/new?assignees=&labels=enhancement&template=feature_request.yml).
+- Becoming a maintainer.
## All Changes Happen Through Pull Requests
@@ -33,11 +33,15 @@ _(make sure you already have a [Vercel](https://vercel.com/) account)_
1. Install [Vercel CLI](https://vercel.com/download).
2. Fork the repository and clone the code to your local machine.
3. Run `npm install` in the repository root.
-4. Run the command "vercel" in the root and follow the steps there.
+4. Run the command `vercel` in the root and follow the steps there.
5. Open `vercel.json` and set the maxDuration to 10.
6. Create a `.env` file in the root of the directory.
-7. In the .env file add a new variable named "PAT_1" with your [GitHub Personal Access Token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token).
-8. Run the command "vercel dev" to start a development server at .
+7. In the .env file add a new variable named `PAT_1` with your [GitHub Personal Access Token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token).
+8. Run the command `vercel dev` to start a development server at .
+9. The cards will then be available from this local endpoint (i.e. `https://localhost:3000/api?username=anuraghazra`).
+
+> **Note**
+> You can also debug any tests using the [VSCode Jest extension](https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest). For more information see https://github.com/jest-community/vscode-jest/issues/912.
## Themes Contribution
From fd64333211fa9f39f59028fcb3892d2cf2fbb57a Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Fri, 28 Apr 2023 04:00:33 +0200
Subject: [PATCH 192/905] docs: update give logo (#2605)
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index 76b46e0eaefb5..6b4cefdf84116 100644
--- a/readme.md
+++ b/readme.md
@@ -66,7 +66,7 @@
Love the project? Please consider donating to help it improve!
-
+
Are you considering supporting the project by donating? Please DO NOT!!
From 30a45d3c136033a0459d0c0423a4836d78e8b0e7 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Fri, 28 Apr 2023 10:50:57 +0300
Subject: [PATCH 193/905] Fixed typo in word color inside README (#2652)
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index 6b4cefdf84116..538b4e8840646 100644
--- a/readme.md
+++ b/readme.md
@@ -183,7 +183,7 @@ We have included a `transparent` theme that has a transparent background. This t
##### Add transparent alpha channel to a themes bg_color
-You can use the `bg_color` parameter to make any of [the available themes](./themes/README.md) transparent. This is done by setting the `bg_color` to a colour with a transparent alpha channel (i.e. `bg_color=00000000`):
+You can use the `bg_color` parameter to make any of [the available themes](./themes/README.md) transparent. This is done by setting the `bg_color` to a color with a transparent alpha channel (i.e. `bg_color=00000000`):
```md
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&bg_color=00000000)
From 6eebfe36e8406730ae13d088060eb5ea6503e1d5 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Fri, 28 Apr 2023 10:51:24 +0300
Subject: [PATCH 194/905] Fixed docs typo inside src/common/utils.js (#2651)
---
src/common/utils.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/common/utils.js b/src/common/utils.js
index c600c717ae3e5..f82544604cf9c 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -392,7 +392,7 @@ const lowercaseTrim = (name) => name.toLowerCase().trim();
/**
* Split array of languages in two columns.
*
- * @template T Langauge object.
+ * @template T Language object.
* @param {Array} arr Array of languages.
* @param {number} perChunk Number of languages per column.
* @returns {Array} Array of languages split in two columns.
From a82a617a37a986c9ee7f9285190c82d106034974 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Fri, 28 Apr 2023 10:51:54 +0300
Subject: [PATCH 195/905] Fixed several typos inside preview theme script
(#2650)
---
scripts/preview-theme.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index e18c01b8615af..57b792a369c95 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -26,9 +26,9 @@ const FAIL_TEXT = `
\rUnfortunately, your theme PR contains an error or does not adhere to our [theme guidelines](https://github.com/anuraghazra/github-readme-stats/blob/master/CONTRIBUTING.md#themes-contribution). Please fix the issues below, and we will review your\
\r PR again. This pull request will **automatically close in 20 days** if no changes are made. After this time, you must re-open the PR for it to be reviewed.
`;
-const THEME_CONTRIB_GUIDELINESS = `
+const THEME_CONTRIB_GUIDELINES = `
\rHi, thanks for the theme contribution. Please read our theme [contribution guidelines](https://github.com/anuraghazra/github-readme-stats/blob/master/CONTRIBUTING.md#themes-contribution).
- \rWe are currently only accepting color combinations from any VSCode theme or themes with good colour combinations to minimize bloating the themes collection.
+ \rWe are currently only accepting color combinations from any VSCode theme or themes with good color combinations to minimize bloating the themes collection.
\r> Also, note that if this theme is exclusively for your personal use, then instead of adding it to our theme collection, you can use card [customization options](https://github.com/anuraghazra/github-readme-stats#customization).
`;
@@ -363,7 +363,7 @@ export const run = async () => {
debug(`Context: ${inspect(github.context)}`);
let commentBody = `
\r# ${COMMENT_TITLE}
- \r${THEME_CONTRIB_GUIDELINESS}
+ \r${THEME_CONTRIB_GUIDELINES}
`;
const ccc = new ColorContrastChecker();
OCTOKIT = github.getOctokit(getGithubToken());
From 31d1ab43d0cae0ecbaba5748fb6a5ca9ae1c7609 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Fri, 28 Apr 2023 18:48:34 +0300
Subject: [PATCH 196/905] Fixed todo inside stats card data fetcher (#2649)
---
src/calculateRank.js | 15 ++++++++-------
src/fetchers/stats-fetcher.js | 1 -
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/calculateRank.js b/src/calculateRank.js
index 24845bc7d9944..215c24d848c34 100644
--- a/src/calculateRank.js
+++ b/src/calculateRank.js
@@ -29,13 +29,14 @@ const normalcdf = (mean, sigma, to) => {
/**
* Calculates the users rank.
*
- * @param {number} totalRepos Total number of repos.
- * @param {number} totalCommits Total number of commits.
- * @param {number} contributions The number of contributions.
- * @param {number} followers The number of followers.
- * @param {number} prs The number of pull requests.
- * @param {number} issues The number of issues.
- * @param {number} stargazers The number of stars.
+ * @param {object} params Parameters on which the user's rank depends.
+ * @param {number} params.totalRepos Total number of repos.
+ * @param {number} params.totalCommits Total number of commits.
+ * @param {number} params.contributions The number of contributions.
+ * @param {number} params.followers The number of followers.
+ * @param {number} params.prs The number of pull requests.
+ * @param {number} params.issues The number of issues.
+ * @param {number} params.stargazers The number of stars.
* @returns {{level: string, score: number}}} The users rank.
*/
const calculateRank = ({
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index fc06fce15fa86..8603e38bbf59d 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -259,7 +259,6 @@ const fetchStats = async (
return prev + curr.stargazers.totalCount;
}, 0);
- // @ts-ignore // TODO: Fix this.
stats.rank = calculateRank({
totalCommits: stats.totalCommits,
totalRepos: user.repositories.totalCount,
From 3bd6519d39cbd6b0a078af17c2756b2804d85fb3 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sat, 29 Apr 2023 04:55:37 +0200
Subject: [PATCH 197/905] docs: fix README language card usage order (#2659)
---
readme.md | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/readme.md b/readme.md
index 538b4e8840646..ae18c9e6002c6 100644
--- a/readme.md
+++ b/readme.md
@@ -363,6 +363,16 @@ The top languages card shows a GitHub user's most frequently used top language.
> **Note**
> Top Languages does not indicate the user's skill level or anything like that; it's a GitHub metric to determine which languages have the most code on GitHub. It is a new feature of github-readme-stats.
+### Usage
+
+Copy-paste this code into your readme and change the links.
+
+Endpoint: `api/top-langs?username=anuraghazra`
+
+```md
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats)
+```
+
### Language stats algorithm
We use the following algorithm to calculate the languages percentages on the language card:
@@ -381,16 +391,6 @@ By default, only the byte count is used for determining the languages percentage
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&size_weight=0.5&count_weight=0.5)](https://github.com/anuraghazra/github-readme-stats)
```
-### Usage
-
-Copy-paste this code into your readme and change the links.
-
-Endpoint: `api/top-langs?username=anuraghazra`
-
-```md
-[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats)
-```
-
### Exclude individual repositories
You can use the `&exclude_repo=repo1,repo2` parameter to exclude individual repositories.
From 2f4279e73883cb64712a5083a1577c602202b6a4 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Sun, 30 Apr 2023 09:20:26 +0300
Subject: [PATCH 198/905] Fixed vscode type error in get card colors function
(#2660)
---
src/common/utils.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/common/utils.js b/src/common/utils.js
index f82544604cf9c..47e106140b6d0 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -194,15 +194,15 @@ const flexLayout = ({ items, gap, direction, sizes = [] }) => {
/**
* Returns theme based colors with proper overrides and defaults.
*
- * @param {Object[]} args Function arguments.
+ * @param {Object} args Function arguments.
* @param {string} args.title_color Card title color.
* @param {string} args.text_color Card text color.
* @param {string} args.icon_color Card icon color.
* @param {string} args.bg_color Card background color.
* @param {string} args.border_color Card border color.
+ * @param {string} args.ring_color Card ring color.
* @param {string} args.theme Card theme.
* @param {string} args.fallbackTheme Fallback theme.
- *
*/
const getCardColors = ({
title_color,
From cb99414d3dc6027139bed09006deee0615847239 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Mon, 1 May 2023 09:21:29 +0300
Subject: [PATCH 199/905] Show no activity error in compact layout of wakatime
card (#2662)
---
src/cards/wakatime-card.js | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index 2c329558b8a35..77521966dcd2c 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -267,12 +267,20 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
${compactProgressBar}
- ${createLanguageTextNode({
- x: 0,
- y: 25,
- langs: filteredLanguages,
- totalSize: 100,
- }).join("")}
+ ${
+ filteredLanguages.length
+ ? createLanguageTextNode({
+ x: 0,
+ y: 25,
+ langs: filteredLanguages,
+ totalSize: 100,
+ }).join("")
+ : noCodingActivityNode({
+ // @ts-ignore
+ color: textColor,
+ text: i18n.t("wakatimecard.nocodingactivity"),
+ })
+ }
`;
} else {
finalLayout = flexLayout({
From a4d6fe104f8c7df2c3f0fc6619aa68306e458c5d Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Wed, 3 May 2023 08:04:33 +0300
Subject: [PATCH 200/905] Fixed card constructor docstring to resolve vscode
type errors (#2674)
---
src/common/Card.js | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/common/Card.js b/src/common/Card.js
index 2f1d9c29f274d..c61b17db73a2b 100644
--- a/src/common/Card.js
+++ b/src/common/Card.js
@@ -12,6 +12,12 @@ class Card {
* @param {string?=} args.customTitle Card custom title.
* @param {string?=} args.defaultTitle Card default title.
* @param {string?=} args.titlePrefixIcon Card title prefix icon.
+ * @param {object?=} args.colors Card colors arguments.
+ * @param {string} args.colors.titleColor Card title color.
+ * @param {string} args.colors.textColor Card text color.
+ * @param {string} args.colors.iconColor Card icon color.
+ * @param {string|Array} args.colors.bgColor Card background color.
+ * @param {string} args.colors.borderColor Card border color.
* @returns {Card} Card instance.
*/
constructor({
From 0dc35316669fffef34cf3a5339fd7f7d985a04f5 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Thu, 4 May 2023 10:13:47 +0300
Subject: [PATCH 201/905] Fixed wakatime create text node func docstring to
resolve vscode type errors (#2678)
---
src/cards/wakatime-card.js | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index 77521966dcd2c..4cf06f866fd8a 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -86,14 +86,15 @@ const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
/**
* Create WakaTime text item.
*
- * @param {Object[]} args The function arguments.
- * @param {string} id The id of the text node item.
- * @param {string} label The label of the text node item.
- * @param {string} value The value of the text node item.
- * @param {number} index The index of the text node item.
- * @param {percent} percent Percentage of the text node item.
- * @param {boolean} hideProgress Whether to hide the progress bar.
- * @param {string} progressBarBackgroundColor The color of the progress bar background.
+ * @param {Object} args The function arguments.
+ * @param {string} args.id The id of the text node item.
+ * @param {string} args.label The label of the text node item.
+ * @param {string} args.value The value of the text node item.
+ * @param {number} args.index The index of the text node item.
+ * @param {string} args.percent Percentage of the text node item.
+ * @param {boolean} args.hideProgress Whether to hide the progress bar.
+ * @param {string} args.progressBarColor The color of the progress bar.
+ * @param {string} args.progressBarBackgroundColor The color of the progress bar background.
*/
const createTextNode = ({
id,
From 311204f4f9712a5ab6fb94c616a1c4310dd28006 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Fri, 5 May 2023 17:06:52 +0300
Subject: [PATCH 202/905] Fixed docstring for several wakatime card gen
functions to resolve multiple type errors (#2690)
---
src/cards/wakatime-card.js | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index 4cf06f866fd8a..0b2366763d6ef 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -36,11 +36,11 @@ const noCodingActivityNode = ({ color, text }) => {
/**
* Create compact WakaTime layout.
*
- * @param {Object[]} args The function arguments.
- * @param {import("../fetchers/types").WakaTimeLang[]} languages The languages array.
- * @param {number} totalSize The total size of the languages.
- * @param {number} x The x position of the language node.
- * @param {number} y The y position of the language node.
+ * @param {Object} args The function arguments.
+ * @param {import("../fetchers/types").WakaTimeLang} args.lang The languages array.
+ * @param {number} args.totalSize The total size of the languages.
+ * @param {number} args.x The x position of the language node.
+ * @param {number} args.y The y position of the language node.
*/
const createCompactLangNode = ({ lang, totalSize, x, y }) => {
const color = languageColors[lang.name] || "#858585";
@@ -58,11 +58,11 @@ const createCompactLangNode = ({ lang, totalSize, x, y }) => {
/**
* Create WakaTime language text node item.
*
- * @param {Object[]} args The function arguments.
- * @param {import("../fetchers/types").WakaTimeLang} lang The language object.
- * @param {number} totalSize The total size of the languages.
- * @param {number} x The x position of the language node.
- * @param {number} y The y position of the language node.
+ * @param {Object} args The function arguments.
+ * @param {import("../fetchers/types").WakaTimeLang[]} args.langs The language objects.
+ * @param {number} args.totalSize The total size of the languages.
+ * @param {number} args.x The x position of the language node.
+ * @param {number} args.y The y position of the language node.
*/
const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
return langs.map((lang, index) => {
From c6dab8b0f2a0ecf66b1d7e797579a31c950897e5 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Fri, 5 May 2023 17:07:15 +0300
Subject: [PATCH 203/905] Fixed docstring for stats card create text node
function to resolve type errors (#2689)
---
src/cards/stats-card.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index 92701d8103c95..4761d023e4ab1 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -20,14 +20,16 @@ const RANK_CARD_DEFAULT_WIDTH = 450;
/**
* Create a stats card text item.
*
- * @param {object[]} createTextNodeParams Object that contains the createTextNode parameters.
+ * @param {object} createTextNodeParams Object that contains the createTextNode parameters.
+ * @param {string} createTextNodeParams.icon The icon to display.
* @param {string} createTextNodeParams.label The label to display.
- * @param {string} createTextNodeParams.value The value to display.
+ * @param {number} createTextNodeParams.value The value to display.
* @param {string} createTextNodeParams.id The id of the stat.
* @param {number} createTextNodeParams.index The index of the stat.
* @param {boolean} createTextNodeParams.showIcons Whether to show icons.
* @param {number} createTextNodeParams.shiftValuePos Number of pixels the value has to be shifted to the right.
* @param {boolean} createTextNodeParams.bold Whether to bold the label.
+ * @param {string} createTextNodeParams.number_format The format of numbers on card.
* @returns
*/
const createTextNode = ({
From c656f3df6bd26ebe9e244616618617099a84bfb0 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Fri, 5 May 2023 17:07:37 +0300
Subject: [PATCH 204/905] Update codecov action version to resolve github
action deprecation warning (#2677)
---
.github/workflows/test.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index fe34668d3e8d2..e8fc84a7df963 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -34,4 +34,4 @@ jobs:
npm run format:check
- name: Code Coverage
- uses: codecov/codecov-action@v1
+ uses: codecov/codecov-action@v3
From d306bec73e5325869b41592dfc1758119c2a4036 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Fri, 5 May 2023 17:09:23 +0300
Subject: [PATCH 205/905] Add PRs cache cleaning workflow (#2661)
---
.github/workflows/prs-cache-clean.yml | 33 +++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 .github/workflows/prs-cache-clean.yml
diff --git a/.github/workflows/prs-cache-clean.yml b/.github/workflows/prs-cache-clean.yml
new file mode 100644
index 0000000000000..8ee4670e01534
--- /dev/null
+++ b/.github/workflows/prs-cache-clean.yml
@@ -0,0 +1,33 @@
+name: prs cache clean
+on:
+ pull_request:
+ types:
+ - closed
+
+jobs:
+ cleanup:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Cleanup
+ run: |
+ gh extension install actions/gh-actions-cache
+
+ REPO=${{ github.repository }}
+ BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
+
+ echo "Fetching list of cache key"
+ cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
+
+ ## Setting this to not fail the workflow while deleting cache keys.
+ set +e
+ echo "Deleting caches..."
+ for cacheKey in $cacheKeysForPR
+ do
+ gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
+ done
+ echo "Done"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
From 2619c1263876b9ac6eef5fb11737efa7ad2603b0 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 5 May 2023 14:10:17 +0000
Subject: [PATCH 206/905] build(deps): bump yaml from 2.1.3 to 2.2.2 (#2644)
Bumps [yaml](https://github.com/eemeli/yaml) from 2.1.3 to 2.2.2.
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](https://github.com/eemeli/yaml/compare/v2.1.3...v2.2.2)
---
updated-dependencies:
- dependency-name: yaml
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package-lock.json | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index ebc7570a41923..a378d89ec88cf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5581,9 +5581,9 @@
"dev": true
},
"node_modules/yaml": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
- "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==",
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz",
+ "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==",
"dev": true,
"engines": {
"node": ">= 14"
@@ -9855,9 +9855,9 @@
"dev": true
},
"yaml": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
- "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==",
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz",
+ "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==",
"dev": true
},
"yargs": {
From a340900e8a1fac282d953fd4c7ac1ae9a459726e Mon Sep 17 00:00:00 2001
From: Fabiano Couto
Date: Fri, 5 May 2023 18:12:28 -0300
Subject: [PATCH 207/905] fix(wakatime-fetcher): add default range to prevent
user not found error (#2670)
* feat(theme): add github_dark_dimmed theme
* feat(theme): change github_dark_dimmed icon color
* contrast ratio adjustment
contrast ratio adjustment on github_dark_dimmed theme
* feat(theme): readme preview
* feat(theme): github themes next to each other
* github themes next to each other
* feat(RankIcon): add rank icon option
* feat(RankIcon): extract rankIcon to icons file
* feat(RankIcon): update readme
* feat(RankIcon): test coverage
* Update readme.md
Co-authored-by: Rick Staa
* add wakatime default range
* update wakatime demos in readme with most active user
* update wakatime demo in readme
* remove &range=all_time from wakatime demos in readme
---------
Co-authored-by: Rick Staa
---
readme.md | 8 ++++----
src/fetchers/wakatime-fetcher.js | 4 +++-
tests/fetchWakatime.test.js | 2 +-
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/readme.md b/readme.md
index ae18c9e6002c6..a95022be6bdf5 100644
--- a/readme.md
+++ b/readme.md
@@ -456,13 +456,13 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
### Demo
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
- Compact layout
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
* * *
@@ -520,7 +520,7 @@ Choose from any of the [default themes](#themes)
- WakaTime card
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
* * *
diff --git a/src/fetchers/wakatime-fetcher.js b/src/fetchers/wakatime-fetcher.js
index fa1f3d890920f..2af8fa9998fb1 100644
--- a/src/fetchers/wakatime-fetcher.js
+++ b/src/fetchers/wakatime-fetcher.js
@@ -14,7 +14,9 @@ const fetchWakatimeStats = async ({ username, api_domain, range }) => {
const { data } = await axios.get(
`https://${
api_domain ? api_domain.replace(/\/$/gi, "") : "wakatime.com"
- }/api/v1/users/${username}/stats/${range || ""}?is_including_today=true`,
+ }/api/v1/users/${username}/stats/${
+ range || "all_time"
+ }?is_including_today=true`,
);
return data.data;
diff --git a/tests/fetchWakatime.test.js b/tests/fetchWakatime.test.js
index 47ca25b7254a6..04c01ba42c6f0 100644
--- a/tests/fetchWakatime.test.js
+++ b/tests/fetchWakatime.test.js
@@ -105,7 +105,7 @@ describe("Wakatime fetcher", () => {
const username = "anuraghazra";
mock
.onGet(
- `https://wakatime.com/api/v1/users/${username}/stats/?is_including_today=true`,
+ `https://wakatime.com/api/v1/users/${username}/stats/all_time?is_including_today=true`,
)
.reply(200, wakaTimeData);
From 0c2fe4e07bab9c8fd8ec2477766cbf2b1fb11cdc Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Sat, 6 May 2023 10:43:37 +0300
Subject: [PATCH 208/905] Cover with test changes in #2662 pull request (#2673)
---
tests/renderWakatimeCard.test.js | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/tests/renderWakatimeCard.test.js b/tests/renderWakatimeCard.test.js
index 25e7ab4d802cd..630f259643c78 100644
--- a/tests/renderWakatimeCard.test.js
+++ b/tests/renderWakatimeCard.test.js
@@ -67,4 +67,19 @@ describe("Test Render Wakatime Card", () => {
"No coding activity this week",
);
});
+
+ it('should show "no coding activity this week" message when using compact layout and there has not been activity', () => {
+ document.body.innerHTML = renderWakatimeCard(
+ {
+ ...wakaTimeData.data,
+ languages: undefined,
+ },
+ {
+ layout: "compact",
+ },
+ );
+ expect(document.querySelector(".stat").textContent).toBe(
+ "No coding activity this week",
+ );
+ });
});
From 0caa4c5fd8788bb77406d298dc74fecc7bdc9eed Mon Sep 17 00:00:00 2001
From: Rongrong
Date: Sat, 6 May 2023 16:07:03 +0800
Subject: [PATCH 209/905] test: fix mistaken pageInfo.endCursor keys (#2657)
The previous mock logic was too simplistic and has been fixed in the
commit. If the mock logic had been properly implemented, then the
mistaken pageInfo.endCursor keys should have made the test case "should
fetch two pages of stars if 'FETCH_MULTI_PAGE_STARS' env variable is set
to `true`" stuck.
---
tests/api.test.js | 2 +-
tests/fetchStats.test.js | 17 +++++++++--------
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/tests/api.test.js b/tests/api.test.js
index 461f3e18abb6d..f11832ef9141c 100644
--- a/tests/api.test.js
+++ b/tests/api.test.js
@@ -43,7 +43,7 @@ const data_stats = {
nodes: [{ stargazers: { totalCount: 100 } }],
pageInfo: {
hasNextPage: false,
- cursor: "cursor",
+ endCursor: "cursor",
},
},
},
diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js
index 04e943a75b50a..08523f3362e0e 100644
--- a/tests/fetchStats.test.js
+++ b/tests/fetchStats.test.js
@@ -27,7 +27,7 @@ const data_stats = {
],
pageInfo: {
hasNextPage: true,
- cursor: "cursor",
+ endCursor: "cursor",
},
},
},
@@ -44,7 +44,7 @@ const data_repo = {
],
pageInfo: {
hasNextPage: false,
- cursor: "cursor",
+ endCursor: "cursor",
},
},
},
@@ -64,7 +64,7 @@ const data_repo_zero_stars = {
],
pageInfo: {
hasNextPage: true,
- cursor: "cursor",
+ endCursor: "cursor",
},
},
},
@@ -86,11 +86,12 @@ const mock = new MockAdapter(axios);
beforeEach(() => {
process.env.FETCH_MULTI_PAGE_STARS = "false"; // Set to `false` to fetch only one page of stars.
- mock
- .onPost("https://api.github.com/graphql")
- .replyOnce(200, data_stats)
- .onPost("https://api.github.com/graphql")
- .replyOnce(200, data_repo);
+ mock.onPost("https://api.github.com/graphql").reply((cfg) => {
+ return [
+ 200,
+ cfg.data.includes("contributionsCollection") ? data_stats : data_repo,
+ ];
+ });
});
afterEach(() => {
From 688f4e497593d22d813423248bd96aaf0f0e495f Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sat, 6 May 2023 11:59:11 +0200
Subject: [PATCH 210/905] docs: update wakatime user (#2697)
The old example user doesn't have a WakaTime account anymore.
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index a95022be6bdf5..58af2835d5fbe 100644
--- a/readme.md
+++ b/readme.md
@@ -448,7 +448,7 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
```md
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
```
> **Note**:
From 6f449a1f0b4cca5d19c16a5822f162921f5cf238 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Sun, 7 May 2023 23:03:00 +0300
Subject: [PATCH 211/905] Fixed docstring for get styles function to resolve
vscode type errors (#2700)
---
src/getStyles.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/getStyles.js b/src/getStyles.js
index f7b90f4adc7b4..7e6113921b60d 100644
--- a/src/getStyles.js
+++ b/src/getStyles.js
@@ -65,10 +65,11 @@ const getAnimations = () => {
/**
* Retrieves CSS styles for a card.
*
- * @param {Object[]} colors The colors to use for the card.
+ * @param {Object} colors The colors to use for the card.
* @param {string} colors.titleColor The title color.
* @param {string} colors.textColor The text color.
* @param {string} colors.iconColor The icon color.
+ * @param {string} colors.ringColor The ring color.
* @param {boolean} colors.show_icons Whether to show icons.
* @param {number} colors.progress The progress value to animate to.
* @returns {string} Card CSS styles.
From 15436e2aa19de52177409735f67da56f243e4431 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Sun, 7 May 2023 23:03:26 +0300
Subject: [PATCH 212/905] Fixed axios imports inside docstrings to resolve
vscode type errors (#2699)
---
src/fetchers/repo-fetcher.js | 4 ++--
src/fetchers/top-languages-fetcher.js | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/fetchers/repo-fetcher.js b/src/fetchers/repo-fetcher.js
index ff7a2be8164cc..412d1d4c28cf1 100644
--- a/src/fetchers/repo-fetcher.js
+++ b/src/fetchers/repo-fetcher.js
@@ -5,9 +5,9 @@ import { MissingParamError, request } from "../common/utils.js";
/**
* Repo data fetcher.
*
- * @param {import('Axios').AxiosRequestHeaders} variables Fetcher variables.
+ * @param {import('axios').AxiosRequestHeaders} variables Fetcher variables.
* @param {string} token GitHub token.
- * @returns {Promise} The response.
+ * @returns {Promise} The response.
*/
const fetcher = (variables, token) => {
return request(
diff --git a/src/fetchers/top-languages-fetcher.js b/src/fetchers/top-languages-fetcher.js
index 45b2ba7d85183..b57d901afb0a7 100644
--- a/src/fetchers/top-languages-fetcher.js
+++ b/src/fetchers/top-languages-fetcher.js
@@ -11,7 +11,7 @@ import {
/**
* Top languages fetcher object.
*
- * @param {import('Axios').AxiosRequestHeaders} variables Fetcher variables.
+ * @param {import('axios').AxiosRequestHeaders} variables Fetcher variables.
* @param {string} token GitHub token.
* @returns {Promise} Languages fetcher response.
*/
From ce116e2d2f42aad54f9fc8e54f208c6c9b1ff558 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Mon, 8 May 2023 10:31:47 +0300
Subject: [PATCH 213/905] Fixed typos inside bug report issue template (#2706)
---
.github/ISSUE_TEMPLATE/bug_report.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 198bc80ef0fe4..367ae4f302d8b 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -15,7 +15,7 @@ body:
required: true
- type: textarea
attributes:
- label: Expected behaviour
+ label: Expected behavior
description:
A clear and concise description of what you expected to happen.
- type: textarea
From 550b88ce878ea19d433b8167731db0a3c306d8a2 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Mon, 8 May 2023 10:32:50 +0300
Subject: [PATCH 214/905] Update wakatime user inside docs translations (#2705)
---
docs/readme_de.md | 8 ++++----
docs/readme_es.md | 10 +++++-----
docs/readme_kr.md | 10 +++++-----
docs/readme_nl.md | 8 ++++----
docs/readme_np.md | 8 ++++----
docs/readme_pt-BR.md | 6 +++---
docs/readme_tr.md | 10 +++++-----
7 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/docs/readme_de.md b/docs/readme_de.md
index 8756670eaf4b9..1ad0d26a390db 100644
--- a/docs/readme_de.md
+++ b/docs/readme_de.md
@@ -253,18 +253,18 @@ Du kannst die `&layout=compact` Option nutzen, um das Kartendesign zu ändern.
Ändere `?username=` in den eigenen [Wakatime](https://wakatime.com)-Benutzernamen.
```md
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
```
### Beispiel
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
- Kompaktes Layout
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_es.md b/docs/readme_es.md
index b477e5c729cab..5672027ae32d5 100644
--- a/docs/readme_es.md
+++ b/docs/readme_es.md
@@ -282,18 +282,18 @@ Puedes usar la opción `& layout = compact` para cambiar el diseño de la tarjet
cambia el valor del parámetro `?username=` a tu username en [Wakatime](https://wakatime.com).
```md
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
```
### Ejemplo
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
- Diseño compacto
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
---
@@ -343,7 +343,7 @@ Escoja cualquiera de los [temas por defecto](#themes)
- Tarjeta de Wakatime
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_kr.md b/docs/readme_kr.md
index 4a1c57cc1e977..0d7bced34ccde 100644
--- a/docs/readme_kr.md
+++ b/docs/readme_kr.md
@@ -298,18 +298,18 @@ _참고:
`?username=` 속성의 값을 [Wakatime](https://wakatime.com) 계정의 사용자 명(닉네임)으로 바꿔주세요.
```md
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
```
### 미리보기
-[![willianrod 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
-[![willianrod 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
- 컴팩트한 레이아웃
-[![willianrod 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
---
@@ -359,7 +359,7 @@ _참고:
- Wakatime 카드
-[![willianrod 님의 Wakatime 카드](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok 님의 Wakatime 카드](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_nl.md b/docs/readme_nl.md
index b279c4f71fff4..f70828f142a88 100644
--- a/docs/readme_nl.md
+++ b/docs/readme_nl.md
@@ -283,14 +283,14 @@ Je kan de `&layout=compact` optie gebruiken om het kaart ontwerp aan te passen.
Verander de `?username=` waarde naar je [Wakatime](https://wakatime.com) gebruikersnaam.
```md
-[![willianrod's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
```
### Demo
-[![willianrod's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
-[![willianrod's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
---
@@ -340,7 +340,7 @@ Kies uit de [standaard thema\'s](#themes)
- Wakatime kaart
-[![willianrod's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_np.md b/docs/readme_np.md
index e90ee57bfe6b3..b322545c0235e 100644
--- a/docs/readme_np.md
+++ b/docs/readme_np.md
@@ -279,14 +279,14 @@ You can use the `&langs_count=` option to increase or decrease the number of lan
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
```md
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
```
### डेमो
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
---
@@ -336,7 +336,7 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
- वक समय कार्ड
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_pt-BR.md b/docs/readme_pt-BR.md
index 1ac57716009be..cf6eeedc4ded6 100644
--- a/docs/readme_pt-BR.md
+++ b/docs/readme_pt-BR.md
@@ -242,14 +242,14 @@ Utilize a opção `&layout=compact` para mudar o layout do cartão.
Altere o valor de `?username=` para o seu username do Wakatime.
```md
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
```
### Demonstração
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_tr.md b/docs/readme_tr.md
index d8ae9778fb50c..fe5aff738c13a 100644
--- a/docs/readme_tr.md
+++ b/docs/readme_tr.md
@@ -282,18 +282,18 @@ Endpoint: `api/top-langs?username=mustafacagri`
`?username=` değerini [Wakatime](https://wakatime.com)'daki kullanıcı adınızla değiştirin.
```md
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
```
### Demo
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
- Kompakt Düzen
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
---
@@ -343,7 +343,7 @@ Endpoint: `api/top-langs?username=mustafacagri`
- Wakatime kart
-[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
---
From 8ff5a3ba45cb493f61444d2963e969b2b54d91e4 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Mon, 8 May 2023 10:33:08 +0300
Subject: [PATCH 215/905] Fixed docstring for create language text node
function (#2704)
---
src/cards/top-languages-card.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index ce8e12a839c77..816b651ea669e 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -98,7 +98,7 @@ const createCompactLangNode = ({ lang, totalSize, hideProgress, index }) => {
/**
* Creates compact layout of text only language nodes.
*
- * @param {object[]} props Function properties.
+ * @param {object} props Function properties.
* @param {Lang[]} props.langs Array of programming languages.
* @param {number} props.totalSize Total size of all languages.
* @param {boolean} props.hideProgress Whether to hide percentage.
From daa1977ba310f5dcb44f7945e7ecb5537e708c05 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Tue, 9 May 2023 10:04:02 +0300
Subject: [PATCH 216/905] Fixed docstring for wakatime card recalculate
percentages function (#2710)
---
src/cards/wakatime-card.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index 0b2366763d6ef..dacc4227dc2ad 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -140,7 +140,7 @@ const createTextNode = ({
* hiding languages.
*
* @param {import("../fetchers/types").WakaTimeLang[]} languages The languages array.
- * @return {import("../fetchers/types").WakaTimeLang[]} The recalculated languages array.
+ * @return {void} The recalculated languages array.
*/
const recalculatePercentages = (languages) => {
const totalSum = languages.reduce(
From c5e7f7b490f3c36857396e8c888d21d9e102c3ae Mon Sep 17 00:00:00 2001
From: Nabil Alamin
Date: Tue, 9 May 2023 19:54:34 +0100
Subject: [PATCH 217/905] add pie chart layout to language card (#2099)
* add pie chart layout to language card
* resolve failing top-lang card tests
* scale down pie chart
* update readme.md
* Update readme.md
Co-authored-by: Rick Staa
* style: format code
* update donut layout to be created without dependencies
* minor update
* style: format readme
* resolve failing tests
* refactor: clean up code and add extra tests
This commit cleans up the pie chart generation code and adds additional
tests.
* feat: improve pie chart positioning
* rename layout pie to donut
* add animation to donut layout
* refactor: rename pie and doughnut to donut
* feat: decrease donus animation delay
---------
Co-authored-by: rickstaa
---
package-lock.json | 145 ++++-----------
readme.md | 12 ++
src/cards/top-languages-card.js | 301 ++++++++++++++++++++++++++-----
src/cards/types.d.ts | 2 +-
tests/renderTopLanguages.test.js | 287 ++++++++++++++++++++++++++++-
5 files changed, 588 insertions(+), 159 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index a378d89ec88cf..a2156910681da 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1495,31 +1495,19 @@
}
},
"node_modules/acorn-globals": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz",
- "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==",
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz",
+ "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==",
"dev": true,
"dependencies": {
- "acorn": "^7.1.1",
- "acorn-walk": "^7.1.1"
- }
- },
- "node_modules/acorn-globals/node_modules/acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
- "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
+ "acorn": "^8.1.0",
+ "acorn-walk": "^8.0.2"
}
},
"node_modules/acorn-walk": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
- "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+ "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
"dev": true,
"engines": {
"node": ">=0.4.0"
@@ -1778,12 +1766,6 @@
"node": ">=8"
}
},
- "node_modules/browser-process-hrtime": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
- "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==",
- "dev": true
- },
"node_modules/browserslist": {
"version": "4.21.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
@@ -2509,20 +2491,6 @@
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
},
- "node_modules/fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -3865,18 +3833,18 @@
}
},
"node_modules/jsdom": {
- "version": "20.0.0",
- "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.0.tgz",
- "integrity": "sha512-x4a6CKCgx00uCmP+QakBDFXwjAJ69IkkIWHmtmjd3wvXPcdOS44hfX2vqkOQrVrq8l9DhNNADZRXaCEWvgXtVA==",
+ "version": "20.0.1",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz",
+ "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==",
"dev": true,
"dependencies": {
"abab": "^2.0.6",
- "acorn": "^8.7.1",
- "acorn-globals": "^6.0.0",
+ "acorn": "^8.8.0",
+ "acorn-globals": "^7.0.0",
"cssom": "^0.5.0",
"cssstyle": "^2.3.0",
"data-urls": "^3.0.2",
- "decimal.js": "^10.3.1",
+ "decimal.js": "^10.4.1",
"domexception": "^4.0.0",
"escodegen": "^2.0.0",
"form-data": "^4.0.0",
@@ -3884,18 +3852,17 @@
"http-proxy-agent": "^5.0.0",
"https-proxy-agent": "^5.0.1",
"is-potential-custom-element-name": "^1.0.1",
- "nwsapi": "^2.2.0",
- "parse5": "^7.0.0",
+ "nwsapi": "^2.2.2",
+ "parse5": "^7.1.1",
"saxes": "^6.0.0",
"symbol-tree": "^3.2.4",
- "tough-cookie": "^4.0.0",
- "w3c-hr-time": "^1.0.2",
+ "tough-cookie": "^4.1.2",
"w3c-xmlserializer": "^3.0.0",
"webidl-conversions": "^7.0.0",
"whatwg-encoding": "^2.0.0",
"whatwg-mimetype": "^3.0.0",
"whatwg-url": "^11.0.0",
- "ws": "^8.8.0",
+ "ws": "^8.9.0",
"xml-name-validator": "^4.0.0"
},
"engines": {
@@ -5397,15 +5364,6 @@
"node": ">=10.12.0"
}
},
- "node_modules/w3c-hr-time": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
- "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==",
- "dev": true,
- "dependencies": {
- "browser-process-hrtime": "^1.0.0"
- }
- },
"node_modules/w3c-xmlserializer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz",
@@ -6830,27 +6788,19 @@
"dev": true
},
"acorn-globals": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz",
- "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==",
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz",
+ "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==",
"dev": true,
"requires": {
- "acorn": "^7.1.1",
- "acorn-walk": "^7.1.1"
- },
- "dependencies": {
- "acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
- "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
- "dev": true
- }
+ "acorn": "^8.1.0",
+ "acorn-walk": "^8.0.2"
}
},
"acorn-walk": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
- "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+ "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
"dev": true
},
"agent-base": {
@@ -7049,12 +6999,6 @@
"fill-range": "^7.0.1"
}
},
- "browser-process-hrtime": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
- "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==",
- "dev": true
- },
"browserslist": {
"version": "4.21.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
@@ -7590,13 +7534,6 @@
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
},
- "fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
- "optional": true
- },
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -8609,18 +8546,18 @@
}
},
"jsdom": {
- "version": "20.0.0",
- "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.0.tgz",
- "integrity": "sha512-x4a6CKCgx00uCmP+QakBDFXwjAJ69IkkIWHmtmjd3wvXPcdOS44hfX2vqkOQrVrq8l9DhNNADZRXaCEWvgXtVA==",
+ "version": "20.0.1",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.1.tgz",
+ "integrity": "sha512-pksjj7Rqoa+wdpkKcLzQRHhJCEE42qQhl/xLMUKHgoSejaKOdaXEAnqs6uDNwMl/fciHTzKeR8Wm8cw7N+g98A==",
"dev": true,
"requires": {
"abab": "^2.0.6",
- "acorn": "^8.7.1",
- "acorn-globals": "^6.0.0",
+ "acorn": "^8.8.0",
+ "acorn-globals": "^7.0.0",
"cssom": "^0.5.0",
"cssstyle": "^2.3.0",
"data-urls": "^3.0.2",
- "decimal.js": "^10.3.1",
+ "decimal.js": "^10.4.1",
"domexception": "^4.0.0",
"escodegen": "^2.0.0",
"form-data": "^4.0.0",
@@ -8628,18 +8565,17 @@
"http-proxy-agent": "^5.0.0",
"https-proxy-agent": "^5.0.1",
"is-potential-custom-element-name": "^1.0.1",
- "nwsapi": "^2.2.0",
- "parse5": "^7.0.0",
+ "nwsapi": "^2.2.2",
+ "parse5": "^7.1.1",
"saxes": "^6.0.0",
"symbol-tree": "^3.2.4",
- "tough-cookie": "^4.0.0",
- "w3c-hr-time": "^1.0.2",
+ "tough-cookie": "^4.1.2",
"w3c-xmlserializer": "^3.0.0",
"webidl-conversions": "^7.0.0",
"whatwg-encoding": "^2.0.0",
"whatwg-mimetype": "^3.0.0",
"whatwg-url": "^11.0.0",
- "ws": "^8.8.0",
+ "ws": "^8.9.0",
"xml-name-validator": "^4.0.0"
}
},
@@ -9724,15 +9660,6 @@
"convert-source-map": "^1.6.0"
}
},
- "w3c-hr-time": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
- "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==",
- "dev": true,
- "requires": {
- "browser-process-hrtime": "^1.0.0"
- }
- },
"w3c-xmlserializer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz",
diff --git a/readme.md b/readme.md
index 58af2835d5fbe..5f3c125476343 100644
--- a/readme.md
+++ b/readme.md
@@ -423,6 +423,14 @@ You can use the `&layout=compact` option to change the card design.
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
```
+### Donut Chart Language Card Layout
+
+You can use the `&layout=donut` option to change the card design.
+
+```md
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut)](https://github.com/anuraghazra/github-readme-stats)
+```
+
### Hide Progress Bars
You can use the `&hide_progress=true` option to hide the percentages and the progress bars (layout will be automatically set to `compact`).
@@ -439,6 +447,10 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+- Donut Chart layout
+
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut)](https://github.com/anuraghazra/github-readme-stats)
+
- Hidden progress bars
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 816b651ea669e..262ae972a4002 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -36,13 +36,134 @@ const getLongestLang = (arr) =>
);
/**
- * Creates a node to display usage of a programming language in percentage
- * using text and a horizontal progress bar.
+ * Convert degrees to radians.
+ *
+ * @param {number} angleInDegrees Angle in degrees.
+ * @returns Angle in radians.
+ */
+const degreesToRadians = (angleInDegrees) => angleInDegrees * (Math.PI / 180.0);
+
+/**
+ * Convert radians to degrees.
+ *
+ * @param {number} angleInRadians Angle in radians.
+ * @returns Angle in degrees.
+ */
+const radiansToDegrees = (angleInRadians) => angleInRadians / (Math.PI / 180.0);
+
+/**
+ * Convert polar coordinates to cartesian coordinates.
+ *
+ * @param {number} centerX Center x coordinate.
+ * @param {number} centerY Center y coordinate.
+ * @param {number} radius Radius of the circle.
+ * @param {number} angleInDegrees Angle in degrees.
+ * @returns {{x: number, y: number}} Cartesian coordinates.
+ */
+const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
+ const rads = degreesToRadians(angleInDegrees);
+ return {
+ x: centerX + radius * Math.cos(rads),
+ y: centerY + radius * Math.sin(rads),
+ };
+};
+
+/**
+ * Convert cartesian coordinates to polar coordinates.
+ *
+ * @param {number} centerX Center x coordinate.
+ * @param {number} centerY Center y coordinate.
+ * @param {number} x Point x coordinate.
+ * @param {number} y Point y coordinate.
+ * @returns {{radius: number, angleInDegrees: number}} Polar coordinates.
+ */
+const cartesianToPolar = (centerX, centerY, x, y) => {
+ const radius = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
+ let angleInDegrees = radiansToDegrees(Math.atan2(y - centerY, x - centerX));
+ if (angleInDegrees < 0) angleInDegrees += 360;
+ return { radius, angleInDegrees };
+};
+
+/**
+ * Calculates height for the compact layout.
+ *
+ * @param {number} totalLangs Total number of languages.
+ * @returns {number} Card height.
+ */
+const calculateCompactLayoutHeight = (totalLangs) => {
+ return 90 + Math.round(totalLangs / 2) * 25;
+};
+
+/**
+ * Calculates height for the normal layout.
+ *
+ * @param {number} totalLangs Total number of languages.
+ * @returns {number} Card height.
+ */
+const calculateNormalLayoutHeight = (totalLangs) => {
+ return 45 + (totalLangs + 1) * 40;
+};
+
+/**
+ * Calculates height for the donut layout.
+ *
+ * @param {number} totalLangs Total number of languages.
+ * @returns {number} Card height.
+ */
+const calculateDonutLayoutHeight = (totalLangs) => {
+ return 215 + Math.max(totalLangs - 5, 0) * 32;
+};
+
+/**
+ * Calculates the center translation needed to keep the donut chart centred.
+ * @param {number} totalLangs Total number of languages.
+ * @returns {number} Donut center translation.
+ */
+const donutCenterTranslation = (totalLangs) => {
+ return -45 + Math.max(totalLangs - 5, 0) * 16;
+};
+
+/**
+ * Trim top languages to lang_count while also hiding certain languages.
+ *
+ * @param {Record} topLangs Top languages.
+ * @param {string[]} hide Languages to hide.
+ * @param {string} langs_count Number of languages to show.
+ * @returns {{topLangs: Record, totalSize: number}} Trimmed top languages and total size.
+ */
+const trimTopLanguages = (topLangs, hide, langs_count) => {
+ let langs = Object.values(topLangs);
+ let langsToHide = {};
+ let langsCount = clampValue(parseInt(langs_count), 1, 10);
+
+ // populate langsToHide map for quick lookup
+ // while filtering out
+ if (hide) {
+ hide.forEach((langName) => {
+ langsToHide[lowercaseTrim(langName)] = true;
+ });
+ }
+
+ // filter out languages to be hidden
+ langs = langs
+ .sort((a, b) => b.size - a.size)
+ .filter((lang) => {
+ return !langsToHide[lowercaseTrim(lang.name)];
+ })
+ .slice(0, langsCount);
+
+ const totalLanguageSize = langs.reduce((acc, curr) => acc + curr.size, 0);
+
+ return { langs, totalLanguageSize };
+};
+
+/**
+ * Create progress bar text item for a programming language.
*
* @param {object} props Function properties.
* @param {number} props.width The card width
- * @param {string} props.name Name of the programming language.
* @param {string} props.color Color of the programming language.
+ * @param {string} props.name Name of the programming language.
* @param {string} props.progress Usage of the programming language in percentage.
* @param {number} props.index Index of the programming language.
* @returns {string} Programming language SVG node.
@@ -71,7 +192,7 @@ const createProgressTextNode = ({ width, color, name, progress, index }) => {
};
/**
- * Creates a text only node to display usage of a programming language in percentage.
+ * Creates compact text item for a programming language.
*
* @param {object} props Function properties.
* @param {Lang} props.lang Programming language object.
@@ -96,7 +217,7 @@ const createCompactLangNode = ({ lang, totalSize, hideProgress, index }) => {
};
/**
- * Creates compact layout of text only language nodes.
+ * Create compact languages text items for all programming languages.
*
* @param {object} props Function properties.
* @param {Lang[]} props.langs Array of programming languages.
@@ -134,7 +255,29 @@ const createLanguageTextNode = ({ langs, totalSize, hideProgress }) => {
};
/**
- * Renders layout to display user's most frequently used programming languages.
+ * Create donut languages text items for all programming languages.
+ *
+ * @param {object[]} props Function properties.
+ * @param {Lang[]} props.langs Array of programming languages.
+ * @param {number} props.totalSize Total size of all languages.
+ * @returns {string} Donut layout programming language SVG node.
+ */
+const createDonutLanguagesNode = ({ langs, totalSize }) => {
+ return flexLayout({
+ items: langs.map((lang, index) => {
+ return createCompactLangNode({
+ lang,
+ totalSize,
+ index,
+ });
+ }),
+ gap: 32,
+ direction: "column",
+ }).join("");
+};
+
+/**
+ * Renders the default language card layout.
*
* @param {Lang[]} langs Array of programming languages.
* @param {number} width Card width.
@@ -158,7 +301,7 @@ const renderNormalLayout = (langs, width, totalLanguageSize) => {
};
/**
- * Renders compact layout to display user's most frequently used programming languages.
+ * Renders the compact language card layout.
*
* @param {Lang[]} langs Array of programming languages.
* @param {number} width Card width.
@@ -218,60 +361,105 @@ const renderCompactLayout = (langs, width, totalLanguageSize, hideProgress) => {
};
/**
- * Calculates height for the compact layout.
+ * Creates the SVG paths for the language donut chart.
*
- * @param {number} totalLangs Total number of languages.
- * @returns {number} Card height.
+ * @param {number} cx Donut center x-position.
+ * @param {number} cy Donut center y-position.
+ * @param {number} radius Donut arc Radius.
+ * @param {number[]} percentages Array with donut section percentages.
+ * @returns {{d: string, percent: number}[]} Array of svg path elements
*/
-const calculateCompactLayoutHeight = (totalLangs) => {
- return 90 + Math.round(totalLangs / 2) * 25;
-};
+const createDonutPaths = (cx, cy, radius, percentages) => {
+ const paths = [];
+ let startAngle = 0;
+ let endAngle = 0;
-/**
- * Calculates height for the normal layout.
- *
- * @param {number} totalLangs Total number of languages.
- * @returns {number} Card height.
- */
-const calculateNormalLayoutHeight = (totalLangs) => {
- return 45 + (totalLangs + 1) * 40;
+ const totalPercent = percentages.reduce((acc, curr) => acc + curr, 0);
+ for (let i = 0; i < percentages.length; i++) {
+ const tmpPath = {};
+
+ let percent = parseFloat(
+ ((percentages[i] / totalPercent) * 100).toFixed(2),
+ );
+
+ endAngle = 3.6 * percent + startAngle;
+ const startPoint = polarToCartesian(cx, cy, radius, endAngle - 90); // rotate donut 90 degrees counter-clockwise.
+ const endPoint = polarToCartesian(cx, cy, radius, startAngle - 90); // rotate donut 90 degrees counter-clockwise.
+ const largeArc = endAngle - startAngle <= 180 ? 0 : 1;
+
+ tmpPath.percent = percent;
+ tmpPath.d = `M ${startPoint.x} ${startPoint.y} A ${radius} ${radius} 0 ${largeArc} 0 ${endPoint.x} ${endPoint.y}`;
+
+ paths.push(tmpPath);
+ startAngle = endAngle;
+ }
+
+ return paths;
};
/**
- * Hides languages and trims the list to show only the top N languages.
+ * Renders the donut language card layout.
*
- * @param {Record} topLangs Top languages.
- * @param {string[]} hide Languages to hide.
- * @param {string} langs_count Number of languages to show.
+ * @param {Lang[]} langs Array of programming languages.
+ * @param {number} width Card width.
+ * @param {number} totalLanguageSize Total size of all languages.
+ * @returns {string} Donut layout card SVG object.
*/
-const useLanguages = (topLangs, hide, langs_count) => {
- let langs = Object.values(topLangs);
- let langsToHide = {};
- let langsCount = clampValue(parseInt(langs_count), 1, 10);
+const renderDonutLayout = (langs, width, totalLanguageSize) => {
+ const centerX = width / 3;
+ const centerY = width / 3;
+ const radius = centerX - 60;
+ const strokeWidth = 12;
+
+ const colors = langs.map((lang) => lang.color);
+ const langsPercents = langs.map((lang) =>
+ parseFloat(((lang.size / totalLanguageSize) * 100).toFixed(2)),
+ );
- // populate langsToHide map for quick lookup
- // while filtering out
- if (hide) {
- hide.forEach((langName) => {
- langsToHide[lowercaseTrim(langName)] = true;
- });
- }
+ const langPaths = createDonutPaths(centerX, centerY, radius, langsPercents);
+
+ const donutPaths =
+ langs.length === 1
+ ? ``
+ : langPaths
+ .map((section, index) => {
+ const staggerDelay = (index + 3) * 100;
+ const delay = staggerDelay + 300;
+
+ const output = `
+
+
+
+
+ `;
- // filter out languages to be hidden
- langs = langs
- .sort((a, b) => b.size - a.size)
- .filter((lang) => {
- return !langsToHide[lowercaseTrim(lang.name)];
- })
- .slice(0, langsCount);
+ return output;
+ })
+ .join("");
- const totalLanguageSize = langs.reduce((acc, curr) => acc + curr.size, 0);
+ const donut = `${donutPaths}`;
- return { langs, totalLanguageSize };
+ return `
+
+
+ ${createDonutLanguagesNode({ langs, totalSize: totalLanguageSize })}
+
+
+
+ ${donut}
+
+
+ `;
};
/**
- * Renders card to display user's most frequently used programming languages.
+ * Renders card that display user's most frequently used programming languages.
*
* @param {import('../fetchers/types').TopLangData} topLangs User's most frequently used programming languages.
* @param {Partial} options Card options.
@@ -302,7 +490,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
translations: langCardLocales,
});
- const { langs, totalLanguageSize } = useLanguages(
+ const { langs, totalLanguageSize } = trimTopLanguages(
topLangs,
hide,
String(langs_count),
@@ -326,6 +514,10 @@ const renderTopLanguages = (topLangs, options = {}) => {
totalLanguageSize,
hide_progress,
);
+ } else if (layout?.toLowerCase() === "donut") {
+ height = calculateDonutLayoutHeight(langs.length);
+ width = width + 50; // padding
+ finalLayout = renderDonutLayout(langs, width, totalLanguageSize);
} else {
finalLayout = renderNormalLayout(langs, width, totalLanguageSize);
}
@@ -394,4 +586,17 @@ const renderTopLanguages = (topLangs, options = {}) => {
`);
};
-export { renderTopLanguages, MIN_CARD_WIDTH };
+export {
+ getLongestLang,
+ degreesToRadians,
+ radiansToDegrees,
+ polarToCartesian,
+ cartesianToPolar,
+ calculateCompactLayoutHeight,
+ calculateNormalLayoutHeight,
+ calculateDonutLayoutHeight,
+ donutCenterTranslation,
+ trimTopLanguages,
+ renderTopLanguages,
+ MIN_CARD_WIDTH,
+};
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index 02a41b5769387..fea5aa954222c 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -39,7 +39,7 @@ export type TopLangOptions = CommonOptions & {
hide_border: boolean;
card_width: number;
hide: string[];
- layout: "compact" | "normal";
+ layout: "compact" | "normal" | "donut";
custom_title: string;
langs_count: number;
disable_animations: boolean;
diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js
index de9e21f129bdf..e4f47c396b80b 100644
--- a/tests/renderTopLanguages.test.js
+++ b/tests/renderTopLanguages.test.js
@@ -1,9 +1,20 @@
import { queryAllByTestId, queryByTestId } from "@testing-library/dom";
import { cssToObject } from "@uppercod/css-to-object";
import {
- MIN_CARD_WIDTH,
+ getLongestLang,
+ degreesToRadians,
+ radiansToDegrees,
+ polarToCartesian,
+ cartesianToPolar,
+ calculateCompactLayoutHeight,
+ calculateNormalLayoutHeight,
+ calculateDonutLayoutHeight,
+ donutCenterTranslation,
+ trimTopLanguages,
renderTopLanguages,
+ MIN_CARD_WIDTH,
} from "../src/cards/top-languages-card.js";
+
// adds special assertions like toHaveTextContent
import "@testing-library/jest-dom";
@@ -27,6 +38,205 @@ const langs = {
},
};
+/**
+ * Retrieve the language percentage from the donut chart SVG.
+ * @param {string} d The SVG path element.
+ * @param {number} centerX The center X coordinate of the donut chart.
+ * @param {number} centerY The center Y coordinate of the donut chart.
+ * @returns {number} The percentage of the language.
+ */
+const langPercentFromSvg = (d, centerX, centerY) => {
+ const dTmp = d
+ .split(" ")
+ .filter((x) => !isNaN(x))
+ .map((x) => parseFloat(x));
+ const endAngle =
+ cartesianToPolar(centerX, centerY, dTmp[0], dTmp[1]).angleInDegrees + 90;
+ let startAngle =
+ cartesianToPolar(centerX, centerY, dTmp[7], dTmp[8]).angleInDegrees + 90;
+ if (startAngle > endAngle) startAngle -= 360;
+ return (endAngle - startAngle) / 3.6;
+};
+
+describe("Test renderTopLanguages helper functions", () => {
+ it("getLongestLang", () => {
+ const langArray = Object.values(langs);
+ expect(getLongestLang(langArray)).toBe(langs.javascript);
+ });
+
+ it("degreesToRadians", () => {
+ expect(degreesToRadians(0)).toBe(0);
+ expect(degreesToRadians(90)).toBe(Math.PI / 2);
+ expect(degreesToRadians(180)).toBe(Math.PI);
+ expect(degreesToRadians(270)).toBe((3 * Math.PI) / 2);
+ expect(degreesToRadians(360)).toBe(2 * Math.PI);
+ });
+
+ it("radiansToDegrees", () => {
+ expect(radiansToDegrees(0)).toBe(0);
+ expect(radiansToDegrees(Math.PI / 2)).toBe(90);
+ expect(radiansToDegrees(Math.PI)).toBe(180);
+ expect(radiansToDegrees((3 * Math.PI) / 2)).toBe(270);
+ expect(radiansToDegrees(2 * Math.PI)).toBe(360);
+ });
+
+ it("polarToCartesian", () => {
+ expect(polarToCartesian(100, 100, 60, 0)).toStrictEqual({ x: 160, y: 100 });
+ expect(polarToCartesian(100, 100, 60, 45)).toStrictEqual({
+ x: 142.42640687119285,
+ y: 142.42640687119285,
+ });
+ expect(polarToCartesian(100, 100, 60, 90)).toStrictEqual({
+ x: 100,
+ y: 160,
+ });
+ expect(polarToCartesian(100, 100, 60, 135)).toStrictEqual({
+ x: 57.573593128807154,
+ y: 142.42640687119285,
+ });
+ expect(polarToCartesian(100, 100, 60, 180)).toStrictEqual({
+ x: 40,
+ y: 100.00000000000001,
+ });
+ expect(polarToCartesian(100, 100, 60, 225)).toStrictEqual({
+ x: 57.57359312880714,
+ y: 57.573593128807154,
+ });
+ expect(polarToCartesian(100, 100, 60, 270)).toStrictEqual({
+ x: 99.99999999999999,
+ y: 40,
+ });
+ expect(polarToCartesian(100, 100, 60, 315)).toStrictEqual({
+ x: 142.42640687119285,
+ y: 57.57359312880714,
+ });
+ expect(polarToCartesian(100, 100, 60, 360)).toStrictEqual({
+ x: 160,
+ y: 99.99999999999999,
+ });
+ });
+
+ it("cartesianToPolar", () => {
+ expect(cartesianToPolar(100, 100, 160, 100)).toStrictEqual({
+ radius: 60,
+ angleInDegrees: 0,
+ });
+ expect(
+ cartesianToPolar(100, 100, 142.42640687119285, 142.42640687119285),
+ ).toStrictEqual({ radius: 60.00000000000001, angleInDegrees: 45 });
+ expect(cartesianToPolar(100, 100, 100, 160)).toStrictEqual({
+ radius: 60,
+ angleInDegrees: 90,
+ });
+ expect(
+ cartesianToPolar(100, 100, 57.573593128807154, 142.42640687119285),
+ ).toStrictEqual({ radius: 60, angleInDegrees: 135 });
+ expect(cartesianToPolar(100, 100, 40, 100.00000000000001)).toStrictEqual({
+ radius: 60,
+ angleInDegrees: 180,
+ });
+ expect(
+ cartesianToPolar(100, 100, 57.57359312880714, 57.573593128807154),
+ ).toStrictEqual({ radius: 60, angleInDegrees: 225 });
+ expect(cartesianToPolar(100, 100, 99.99999999999999, 40)).toStrictEqual({
+ radius: 60,
+ angleInDegrees: 270,
+ });
+ expect(
+ cartesianToPolar(100, 100, 142.42640687119285, 57.57359312880714),
+ ).toStrictEqual({ radius: 60.00000000000001, angleInDegrees: 315 });
+ expect(cartesianToPolar(100, 100, 160, 99.99999999999999)).toStrictEqual({
+ radius: 60,
+ angleInDegrees: 360,
+ });
+ });
+
+ it("calculateCompactLayoutHeight", () => {
+ expect(calculateCompactLayoutHeight(0)).toBe(90);
+ expect(calculateCompactLayoutHeight(1)).toBe(115);
+ expect(calculateCompactLayoutHeight(2)).toBe(115);
+ expect(calculateCompactLayoutHeight(3)).toBe(140);
+ expect(calculateCompactLayoutHeight(4)).toBe(140);
+ expect(calculateCompactLayoutHeight(5)).toBe(165);
+ expect(calculateCompactLayoutHeight(6)).toBe(165);
+ expect(calculateCompactLayoutHeight(7)).toBe(190);
+ expect(calculateCompactLayoutHeight(8)).toBe(190);
+ expect(calculateCompactLayoutHeight(9)).toBe(215);
+ expect(calculateCompactLayoutHeight(10)).toBe(215);
+ });
+
+ it("calculateNormalLayoutHeight", () => {
+ expect(calculateNormalLayoutHeight(0)).toBe(85);
+ expect(calculateNormalLayoutHeight(1)).toBe(125);
+ expect(calculateNormalLayoutHeight(2)).toBe(165);
+ expect(calculateNormalLayoutHeight(3)).toBe(205);
+ expect(calculateNormalLayoutHeight(4)).toBe(245);
+ expect(calculateNormalLayoutHeight(5)).toBe(285);
+ expect(calculateNormalLayoutHeight(6)).toBe(325);
+ expect(calculateNormalLayoutHeight(7)).toBe(365);
+ expect(calculateNormalLayoutHeight(8)).toBe(405);
+ expect(calculateNormalLayoutHeight(9)).toBe(445);
+ expect(calculateNormalLayoutHeight(10)).toBe(485);
+ });
+
+ it("calculateDonutLayoutHeight", () => {
+ expect(calculateDonutLayoutHeight(0)).toBe(215);
+ expect(calculateDonutLayoutHeight(1)).toBe(215);
+ expect(calculateDonutLayoutHeight(2)).toBe(215);
+ expect(calculateDonutLayoutHeight(3)).toBe(215);
+ expect(calculateDonutLayoutHeight(4)).toBe(215);
+ expect(calculateDonutLayoutHeight(5)).toBe(215);
+ expect(calculateDonutLayoutHeight(6)).toBe(247);
+ expect(calculateDonutLayoutHeight(7)).toBe(279);
+ expect(calculateDonutLayoutHeight(8)).toBe(311);
+ expect(calculateDonutLayoutHeight(9)).toBe(343);
+ expect(calculateDonutLayoutHeight(10)).toBe(375);
+ });
+
+ it("donutCenterTranslation", () => {
+ expect(donutCenterTranslation(0)).toBe(-45);
+ expect(donutCenterTranslation(1)).toBe(-45);
+ expect(donutCenterTranslation(2)).toBe(-45);
+ expect(donutCenterTranslation(3)).toBe(-45);
+ expect(donutCenterTranslation(4)).toBe(-45);
+ expect(donutCenterTranslation(5)).toBe(-45);
+ expect(donutCenterTranslation(6)).toBe(-29);
+ expect(donutCenterTranslation(7)).toBe(-13);
+ expect(donutCenterTranslation(8)).toBe(3);
+ expect(donutCenterTranslation(9)).toBe(19);
+ expect(donutCenterTranslation(10)).toBe(35);
+ });
+
+ it("trimTopLanguages", () => {
+ expect(trimTopLanguages([])).toStrictEqual({
+ langs: [],
+ totalLanguageSize: 0,
+ });
+ expect(trimTopLanguages([langs.javascript])).toStrictEqual({
+ langs: [langs.javascript],
+ totalLanguageSize: 200,
+ });
+ expect(
+ trimTopLanguages([langs.javascript, langs.HTML], [], 5),
+ ).toStrictEqual({
+ langs: [langs.javascript, langs.HTML],
+ totalLanguageSize: 400,
+ });
+ expect(trimTopLanguages(langs, [], 5)).toStrictEqual({
+ langs: Object.values(langs),
+ totalLanguageSize: 500,
+ });
+ expect(trimTopLanguages(langs, [], 2)).toStrictEqual({
+ langs: Object.values(langs).slice(0, 2),
+ totalLanguageSize: 400,
+ });
+ expect(trimTopLanguages(langs, ["javascript"], 5)).toStrictEqual({
+ langs: [langs.HTML, langs.css],
+ totalLanguageSize: 300,
+ });
+ });
+});
+
describe("Test renderTopLanguages", () => {
it("should render correctly", () => {
document.body.innerHTML = renderTopLanguages(langs);
@@ -236,6 +446,81 @@ describe("Test renderTopLanguages", () => {
);
});
+ it("should render with layout donut", () => {
+ document.body.innerHTML = renderTopLanguages(langs, { layout: "donut" });
+
+ expect(queryByTestId(document.body, "header")).toHaveTextContent(
+ "Most Used Languages",
+ );
+
+ expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
+ "HTML 40.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-donut")[0]).toHaveAttribute(
+ "size",
+ "40",
+ );
+ const d = queryAllByTestId(document.body, "lang-donut")[0]
+ .getAttribute("d")
+ .split(" ")
+ .filter((x) => !isNaN(x))
+ .map((x) => parseFloat(x));
+ const center = { x: d[7], y: d[7] };
+ const HTMLLangPercent = langPercentFromSvg(
+ queryAllByTestId(document.body, "lang-donut")[0].getAttribute("d"),
+ center.x,
+ center.y,
+ );
+ expect(HTMLLangPercent).toBeCloseTo(40);
+
+ expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent(
+ "javascript 40.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-donut")[1]).toHaveAttribute(
+ "size",
+ "40",
+ );
+ const javascriptLangPercent = langPercentFromSvg(
+ queryAllByTestId(document.body, "lang-donut")[1].getAttribute("d"),
+ center.x,
+ center.y,
+ );
+ expect(javascriptLangPercent).toBeCloseTo(40);
+
+ expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent(
+ "css 20.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-donut")[2]).toHaveAttribute(
+ "size",
+ "20",
+ );
+ const cssLangPercent = langPercentFromSvg(
+ queryAllByTestId(document.body, "lang-donut")[2].getAttribute("d"),
+ center.x,
+ center.y,
+ );
+ expect(cssLangPercent).toBeCloseTo(20);
+
+ expect(HTMLLangPercent + javascriptLangPercent + cssLangPercent).toBe(100);
+
+ // Should render full donut (circle) if one language is 100%.
+ document.body.innerHTML = renderTopLanguages(
+ { HTML: langs.HTML },
+ { layout: "donut" },
+ );
+ expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
+ "HTML 100.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-donut")[0]).toHaveAttribute(
+ "size",
+ "100",
+ );
+ expect(queryAllByTestId(document.body, "lang-donut")).toHaveLength(1);
+ expect(queryAllByTestId(document.body, "lang-donut")[0].tagName).toBe(
+ "circle",
+ );
+ });
+
it("should render a translated title", () => {
document.body.innerHTML = renderTopLanguages(langs, { locale: "cn" });
expect(document.getElementsByClassName("header")[0].textContent).toBe(
From 4b19453c1ae1ab0ff7292206fae8db85b427369f Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Wed, 10 May 2023 23:59:00 +0300
Subject: [PATCH 218/905] Fixed docstring for create donut language node
function (#2713)
---
src/cards/top-languages-card.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 262ae972a4002..5523c93060bb0 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -257,7 +257,7 @@ const createLanguageTextNode = ({ langs, totalSize, hideProgress }) => {
/**
* Create donut languages text items for all programming languages.
*
- * @param {object[]} props Function properties.
+ * @param {object} props Function properties.
* @param {Lang[]} props.langs Array of programming languages.
* @param {number} props.totalSize Total size of all languages.
* @returns {string} Donut layout programming language SVG node.
From 1f4a2c4d827533813faedf2b40172fe1c221037d Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Thu, 11 May 2023 09:36:21 +0300
Subject: [PATCH 219/905] Add missing argument to create compact lang node
function to resolve vscode type error (#2714)
---
src/cards/top-languages-card.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 5523c93060bb0..ed51f1c9ddbfe 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -268,6 +268,7 @@ const createDonutLanguagesNode = ({ langs, totalSize }) => {
return createCompactLangNode({
lang,
totalSize,
+ hideProgress: false,
index,
});
}),
From ff9839b73caefcfb0185e61f529c7def7398fc1c Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov <53787217+qwerty541@users.noreply.github.com>
Date: Thu, 11 May 2023 09:49:57 +0300
Subject: [PATCH 220/905] Top languages card pie layout (#2709)
* Top languages card donut layout
* Top languages card pie layout
* renames
* dev
* docs
* dev
* dev
* animations
* dev
* handle one language
---
readme.md | 12 +++
src/cards/top-languages-card.js | 115 +++++++++++++++++++++++++++-
src/cards/types.d.ts | 2 +-
tests/renderTopLanguages.test.js | 127 ++++++++++++++++++++++++++++++-
4 files changed, 250 insertions(+), 6 deletions(-)
diff --git a/readme.md b/readme.md
index 5f3c125476343..d1e56775f91a4 100644
--- a/readme.md
+++ b/readme.md
@@ -431,6 +431,14 @@ You can use the `&layout=donut` option to change the card design.
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut)](https://github.com/anuraghazra/github-readme-stats)
```
+### Pie Chart Language Card Layout
+
+You can use the `&layout=pie` option to change the card design.
+
+```md
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=pie)](https://github.com/anuraghazra/github-readme-stats)
+```
+
### Hide Progress Bars
You can use the `&hide_progress=true` option to hide the percentages and the progress bars (layout will be automatically set to `compact`).
@@ -451,6 +459,10 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut)](https://github.com/anuraghazra/github-readme-stats)
+- Pie Chart layout
+
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=pie)](https://github.com/anuraghazra/github-readme-stats)
+
- Hidden progress bars
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index ed51f1c9ddbfe..e03e8bcb00a35 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -114,6 +114,16 @@ const calculateDonutLayoutHeight = (totalLangs) => {
return 215 + Math.max(totalLangs - 5, 0) * 32;
};
+/**
+ * Calculates height for the pie layout.
+ *
+ * @param {number} totalLangs Total number of languages.
+ * @returns {number} Card height.
+ */
+const calculatePieLayoutHeight = (totalLangs) => {
+ return 300 + Math.round(totalLangs / 2) * 25;
+};
+
/**
* Calculates the center translation needed to keep the donut chart centred.
* @param {number} totalLangs Total number of languages.
@@ -361,6 +371,101 @@ const renderCompactLayout = (langs, width, totalLanguageSize, hideProgress) => {
`;
};
+/**
+ * Renders pie layout to display user's most frequently used programming languages.
+ *
+ * @param {Lang[]} langs Array of programming languages.
+ * @param {number} totalLanguageSize Total size of all languages.
+ * @returns {string} Compact layout card SVG object.
+ */
+const renderPieLayout = (langs, totalLanguageSize) => {
+ // Pie chart radius and center coordinates
+ const radius = 90;
+ const centerX = 150;
+ const centerY = 100;
+
+ // Start angle for the pie chart parts
+ let startAngle = 0;
+
+ // Start delay coefficient for the pie chart parts
+ let startDelayCoefficient = 1;
+
+ // SVG paths
+ const paths = [];
+
+ // Generate each pie chart part
+ for (const lang of langs) {
+ if (langs.length === 1) {
+ paths.push(`
+
+ `);
+ break;
+ }
+
+ const langSizePart = lang.size / totalLanguageSize;
+ const percentage = langSizePart * 100;
+ // Calculate the angle for the current part
+ const angle = langSizePart * 360;
+
+ // Calculate the end angle
+ const endAngle = startAngle + angle;
+
+ // Calculate the coordinates of the start and end points of the arc
+ const startPoint = polarToCartesian(centerX, centerY, radius, startAngle);
+ const endPoint = polarToCartesian(centerX, centerY, radius, endAngle);
+
+ // Determine the large arc flag based on the angle
+ const largeArcFlag = angle > 180 ? 1 : 0;
+
+ // Calculate delay
+ const delay = startDelayCoefficient * 100;
+
+ // SVG arc markup
+ paths.push(`
+
+
+
+ `);
+
+ // Update the start angle for the next part
+ startAngle = endAngle;
+ // Update the start delay coefficient for the next part
+ startDelayCoefficient += 1;
+ }
+
+ return `
+
+
+
+ ${paths.join("")}
+
+
+
+
+ ${createLanguageTextNode({
+ langs,
+ totalSize: totalLanguageSize,
+ hideProgress: false,
+ })}
+
+
+
+ `;
+};
+
/**
* Creates the SVG paths for the language donut chart.
*
@@ -505,7 +610,10 @@ const renderTopLanguages = (topLangs, options = {}) => {
let height = calculateNormalLayoutHeight(langs.length);
let finalLayout = "";
- if (layout === "compact" || hide_progress == true) {
+ if (layout === "pie") {
+ height = calculatePieLayoutHeight(langs.length);
+ finalLayout = renderPieLayout(langs, totalLanguageSize);
+ } else if (layout === "compact" || hide_progress == true) {
height =
calculateCompactLayoutHeight(langs.length) + (hide_progress ? -25 : 0);
@@ -580,6 +688,10 @@ const renderTopLanguages = (topLangs, options = {}) => {
`,
);
+ if (layout === "pie") {
+ return card.render(finalLayout);
+ }
+
return card.render(`
${finalLayout}
@@ -596,6 +708,7 @@ export {
calculateCompactLayoutHeight,
calculateNormalLayoutHeight,
calculateDonutLayoutHeight,
+ calculatePieLayoutHeight,
donutCenterTranslation,
trimTopLanguages,
renderTopLanguages,
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index fea5aa954222c..7945118cbe384 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -39,7 +39,7 @@ export type TopLangOptions = CommonOptions & {
hide_border: boolean;
card_width: number;
hide: string[];
- layout: "compact" | "normal" | "donut";
+ layout: "compact" | "normal" | "donut" | "pie";
custom_title: string;
langs_count: number;
disable_animations: boolean;
diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js
index e4f47c396b80b..e4bc56de8dc95 100644
--- a/tests/renderTopLanguages.test.js
+++ b/tests/renderTopLanguages.test.js
@@ -9,6 +9,7 @@ import {
calculateCompactLayoutHeight,
calculateNormalLayoutHeight,
calculateDonutLayoutHeight,
+ calculatePieLayoutHeight,
donutCenterTranslation,
trimTopLanguages,
renderTopLanguages,
@@ -40,12 +41,13 @@ const langs = {
/**
* Retrieve the language percentage from the donut chart SVG.
+ *
* @param {string} d The SVG path element.
* @param {number} centerX The center X coordinate of the donut chart.
* @param {number} centerY The center Y coordinate of the donut chart.
* @returns {number} The percentage of the language.
*/
-const langPercentFromSvg = (d, centerX, centerY) => {
+const langPercentFromDonutLayoutSvg = (d, centerX, centerY) => {
const dTmp = d
.split(" ")
.filter((x) => !isNaN(x))
@@ -58,6 +60,34 @@ const langPercentFromSvg = (d, centerX, centerY) => {
return (endAngle - startAngle) / 3.6;
};
+/**
+ * Retrieve the language percentage from the pie chart SVG.
+ *
+ * @param {string} d The SVG path element.
+ * @param {number} centerX The center X coordinate of the pie chart.
+ * @param {number} centerY The center Y coordinate of the pie chart.
+ * @returns {number} The percentage of the language.
+ */
+const langPercentFromPieLayoutSvg = (d, centerX, centerY) => {
+ const dTmp = d
+ .split(" ")
+ .filter((x) => !isNaN(x))
+ .map((x) => parseFloat(x));
+ const startAngle = cartesianToPolar(
+ centerX,
+ centerY,
+ dTmp[2],
+ dTmp[3],
+ ).angleInDegrees;
+ let endAngle = cartesianToPolar(
+ centerX,
+ centerY,
+ dTmp[9],
+ dTmp[10],
+ ).angleInDegrees;
+ return ((endAngle - startAngle) / 360) * 100;
+};
+
describe("Test renderTopLanguages helper functions", () => {
it("getLongestLang", () => {
const langArray = Object.values(langs);
@@ -193,6 +223,20 @@ describe("Test renderTopLanguages helper functions", () => {
expect(calculateDonutLayoutHeight(10)).toBe(375);
});
+ it("calculatePieLayoutHeight", () => {
+ expect(calculatePieLayoutHeight(0)).toBe(300);
+ expect(calculatePieLayoutHeight(1)).toBe(325);
+ expect(calculatePieLayoutHeight(2)).toBe(325);
+ expect(calculatePieLayoutHeight(3)).toBe(350);
+ expect(calculatePieLayoutHeight(4)).toBe(350);
+ expect(calculatePieLayoutHeight(5)).toBe(375);
+ expect(calculatePieLayoutHeight(6)).toBe(375);
+ expect(calculatePieLayoutHeight(7)).toBe(400);
+ expect(calculatePieLayoutHeight(8)).toBe(400);
+ expect(calculatePieLayoutHeight(9)).toBe(425);
+ expect(calculatePieLayoutHeight(10)).toBe(425);
+ });
+
it("donutCenterTranslation", () => {
expect(donutCenterTranslation(0)).toBe(-45);
expect(donutCenterTranslation(1)).toBe(-45);
@@ -466,7 +510,7 @@ describe("Test renderTopLanguages", () => {
.filter((x) => !isNaN(x))
.map((x) => parseFloat(x));
const center = { x: d[7], y: d[7] };
- const HTMLLangPercent = langPercentFromSvg(
+ const HTMLLangPercent = langPercentFromDonutLayoutSvg(
queryAllByTestId(document.body, "lang-donut")[0].getAttribute("d"),
center.x,
center.y,
@@ -480,7 +524,7 @@ describe("Test renderTopLanguages", () => {
"size",
"40",
);
- const javascriptLangPercent = langPercentFromSvg(
+ const javascriptLangPercent = langPercentFromDonutLayoutSvg(
queryAllByTestId(document.body, "lang-donut")[1].getAttribute("d"),
center.x,
center.y,
@@ -494,7 +538,7 @@ describe("Test renderTopLanguages", () => {
"size",
"20",
);
- const cssLangPercent = langPercentFromSvg(
+ const cssLangPercent = langPercentFromDonutLayoutSvg(
queryAllByTestId(document.body, "lang-donut")[2].getAttribute("d"),
center.x,
center.y,
@@ -520,6 +564,81 @@ describe("Test renderTopLanguages", () => {
"circle",
);
});
+ it("should render with layout pie", () => {
+ document.body.innerHTML = renderTopLanguages(langs, { layout: "pie" });
+
+ expect(queryByTestId(document.body, "header")).toHaveTextContent(
+ "Most Used Languages",
+ );
+
+ expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
+ "HTML 40.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-pie")[0]).toHaveAttribute(
+ "size",
+ "40",
+ );
+
+ const d = queryAllByTestId(document.body, "lang-pie")[0]
+ .getAttribute("d")
+ .split(" ")
+ .filter((x) => !isNaN(x))
+ .map((x) => parseFloat(x));
+ const center = { x: d[0], y: d[1] };
+ const HTMLLangPercent = langPercentFromPieLayoutSvg(
+ queryAllByTestId(document.body, "lang-pie")[0].getAttribute("d"),
+ center.x,
+ center.y,
+ );
+ expect(HTMLLangPercent).toBeCloseTo(40);
+
+ expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent(
+ "javascript 40.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-pie")[1]).toHaveAttribute(
+ "size",
+ "40",
+ );
+ const javascriptLangPercent = langPercentFromPieLayoutSvg(
+ queryAllByTestId(document.body, "lang-pie")[1].getAttribute("d"),
+ center.x,
+ center.y,
+ );
+ expect(javascriptLangPercent).toBeCloseTo(40);
+
+ expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent(
+ "css 20.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-pie")[2]).toHaveAttribute(
+ "size",
+ "20",
+ );
+ const cssLangPercent = langPercentFromPieLayoutSvg(
+ queryAllByTestId(document.body, "lang-pie")[2].getAttribute("d"),
+ center.x,
+ center.y,
+ );
+ expect(cssLangPercent).toBeCloseTo(20);
+
+ expect(HTMLLangPercent + javascriptLangPercent + cssLangPercent).toBe(100);
+
+ // Should render full pie (circle) if one language is 100%.
+ document.body.innerHTML = renderTopLanguages(
+ { HTML: langs.HTML },
+ { layout: "pie" },
+ );
+ expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
+ "HTML 100.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-pie")[0]).toHaveAttribute(
+ "size",
+ "100",
+ );
+ expect(queryAllByTestId(document.body, "lang-pie")).toHaveLength(1);
+ expect(queryAllByTestId(document.body, "lang-pie")[0].tagName).toBe(
+ "circle",
+ );
+ });
it("should render a translated title", () => {
document.body.innerHTML = renderTopLanguages(langs, { locale: "cn" });
From d59a80599f781fd9af4731236519a2e551e97590 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sat, 13 May 2023 14:20:18 +0300
Subject: [PATCH 221/905] Docs: add missing top languages card layouts. (#2717)
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index d1e56775f91a4..f59342f3ab9f4 100644
--- a/readme.md
+++ b/readme.md
@@ -303,7 +303,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `hide` - Hide the languages specified from the card _(Comma-separated values)_. Default: `[] (blank array)`.
- `hide_title` - _(boolean)_. Default: `false`.
-- `layout` - Switch between two available layouts `default` & `compact`. Default: `default`.
+- `layout` - Switch between four available layouts `normal` & `compact` & `donut` & `pie`. Default: `normal`.
- `card_width` - Set the card's width manually _(number)_. Default `300`.
- `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`.
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
From 6d45f89c9efcccc995a1912695cbe269f0e5c289 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sat, 13 May 2023 14:21:06 +0300
Subject: [PATCH 222/905] Top languages card render test: move repeated code
into helper function (#2718)
---
tests/renderTopLanguages.test.js | 39 +++++++++++++++++---------------
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js
index e4bc56de8dc95..a8bc873a79ef1 100644
--- a/tests/renderTopLanguages.test.js
+++ b/tests/renderTopLanguages.test.js
@@ -39,6 +39,19 @@ const langs = {
},
};
+/**
+ * Retrieve number array from SVG path definition string.
+ *
+ * @param {string} d SVG path definition string.
+ * @return {number[]} Resulting numbers array.
+ */
+const getNumbersFromSvgPathDefinitionAttribute = (d) => {
+ return d
+ .split(" ")
+ .filter((x) => !isNaN(x))
+ .map((x) => parseFloat(x));
+};
+
/**
* Retrieve the language percentage from the donut chart SVG.
*
@@ -48,10 +61,7 @@ const langs = {
* @returns {number} The percentage of the language.
*/
const langPercentFromDonutLayoutSvg = (d, centerX, centerY) => {
- const dTmp = d
- .split(" ")
- .filter((x) => !isNaN(x))
- .map((x) => parseFloat(x));
+ const dTmp = getNumbersFromSvgPathDefinitionAttribute(d);
const endAngle =
cartesianToPolar(centerX, centerY, dTmp[0], dTmp[1]).angleInDegrees + 90;
let startAngle =
@@ -69,10 +79,7 @@ const langPercentFromDonutLayoutSvg = (d, centerX, centerY) => {
* @returns {number} The percentage of the language.
*/
const langPercentFromPieLayoutSvg = (d, centerX, centerY) => {
- const dTmp = d
- .split(" ")
- .filter((x) => !isNaN(x))
- .map((x) => parseFloat(x));
+ const dTmp = getNumbersFromSvgPathDefinitionAttribute(d);
const startAngle = cartesianToPolar(
centerX,
centerY,
@@ -504,11 +511,9 @@ describe("Test renderTopLanguages", () => {
"size",
"40",
);
- const d = queryAllByTestId(document.body, "lang-donut")[0]
- .getAttribute("d")
- .split(" ")
- .filter((x) => !isNaN(x))
- .map((x) => parseFloat(x));
+ const d = getNumbersFromSvgPathDefinitionAttribute(
+ queryAllByTestId(document.body, "lang-donut")[0].getAttribute("d"),
+ );
const center = { x: d[7], y: d[7] };
const HTMLLangPercent = langPercentFromDonutLayoutSvg(
queryAllByTestId(document.body, "lang-donut")[0].getAttribute("d"),
@@ -579,11 +584,9 @@ describe("Test renderTopLanguages", () => {
"40",
);
- const d = queryAllByTestId(document.body, "lang-pie")[0]
- .getAttribute("d")
- .split(" ")
- .filter((x) => !isNaN(x))
- .map((x) => parseFloat(x));
+ const d = getNumbersFromSvgPathDefinitionAttribute(
+ queryAllByTestId(document.body, "lang-pie")[0].getAttribute("d"),
+ );
const center = { x: d[0], y: d[1] };
const HTMLLangPercent = langPercentFromPieLayoutSvg(
queryAllByTestId(document.body, "lang-pie")[0].getAttribute("d"),
From 7ec1a76c6590a8c9682aa71d81ca6bef0405a078 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Wed, 17 May 2023 09:37:25 +0300
Subject: [PATCH 223/905] Docs (translations): add missing top languages card
layouts. (#2728)
---
docs/readme_cn.md | 2 +-
docs/readme_de.md | 2 +-
docs/readme_es.md | 2 +-
docs/readme_fr.md | 2 +-
docs/readme_it.md | 2 +-
docs/readme_ja.md | 2 +-
docs/readme_kr.md | 2 +-
docs/readme_nl.md | 2 +-
docs/readme_np.md | 2 +-
docs/readme_pt-BR.md | 2 +-
docs/readme_tr.md | 2 +-
11 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/docs/readme_cn.md b/docs/readme_cn.md
index d6487b6618264..3bd2c149c8b91 100644
--- a/docs/readme_cn.md
+++ b/docs/readme_cn.md
@@ -171,7 +171,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
- `hide` - 从卡片中隐藏指定语言 _(Comma seperated values)_
- `hide_title` - _(boolean)_
-- `layout` - 在两个可用布局 `default` & `compact` 间切换
+- `layout` - 提供四種佈局 `normal` & `compact` & `donut` & `pie` 间切换
- `card_width` - 手动设置卡片的宽度 _(number)_
> :warning: **重要:**
diff --git a/docs/readme_de.md b/docs/readme_de.md
index 1ad0d26a390db..a94e8c2c8613c 100644
--- a/docs/readme_de.md
+++ b/docs/readme_de.md
@@ -161,7 +161,7 @@ Du kannst mehrere, mit Kommas separierte, Werte in der bg_color Option angeben,
- `hide` - Verbirgt die angegebenen Sprachen von der Karte _(Komma separierte Werte)_
- `hide_title` - _(Boolean)_
-- `layout` - Wechsel zwischen den zwei verfügbaren Layouts `default` & `compact`
+- `layout` - Wechseln Sie zwischen den vier verfügbaren Layouts `normal` & `compact` & `donut` & `pie`
- `card_width` - Lege die Breite der Karte manuell fest _(Zahl)_
> :warning: **Wichtig:**
diff --git a/docs/readme_es.md b/docs/readme_es.md
index 5672027ae32d5..a353502ca5697 100644
--- a/docs/readme_es.md
+++ b/docs/readme_es.md
@@ -175,7 +175,7 @@ Puedes pasar mútliples valores separados por coma en la opción `bg_color` para
- `hide` - Oculta de la tarjeta los lenguajes especificados _(valores separados por comas)_
- `hide_title` - _(booleano)_
-- `layout` - Cambia entre los dos diseños disponibles `default` & `compact`
+- `layout` - Cambiar entre los cuatro diseños disponibles `normal` & `compact` & `donut` & `pie`
- `card_width` - Establece el ancho de la tarjeta manualmente _(número)_
- `langs_count` - Muestra más lenguajes en la tarjeta, entre 1-10, por defecto 5 _(número)_
- `exclude_repo` - Excluye los repositorios especificados _(valores separados por comas)_
diff --git a/docs/readme_fr.md b/docs/readme_fr.md
index ce0d3d495cc10..427f2971451c8 100644
--- a/docs/readme_fr.md
+++ b/docs/readme_fr.md
@@ -171,7 +171,7 @@ Vous pouvez fournir plusieurs valeurs (suivie d'une virgule) dans l'option bg_co
- `hide` - Masquer les langages spécifiés sur la carte _(Comma seperated values)_
- `hide_title` - Masquer le titre _(boolean)_
-- `layout` - Alterner entre 2 mise en page `default` & `compact`
+- `layout` - Alterner entre 4 mise en page `normal` & `compact` & `donut` & `pie`
- `card_width` - Fixer la largeur de la carte manuellement _(number)_
> :warning: **Important:**
diff --git a/docs/readme_it.md b/docs/readme_it.md
index e54af7dc488ad..4418c333b4be4 100644
--- a/docs/readme_it.md
+++ b/docs/readme_it.md
@@ -171,7 +171,7 @@ Puoi fornire valori separati da virgola nel parametro bg_color per creare un gra
- `hide` - Nasconde un linguaggio specifico _(valori separati da virgola)_
- `hide_title` - Nasconde il titolo _(booleano)_
-- `layout` - Specifica il tipo di layout, `default` (esteso) o `compact` (compatto)
+- `layout` - Specificare il tipo di layout, `normal` (esteso), `compact` (compatto), `donut` (ciambella) e `pie` (torta)
- `card_width` - Specifica il valore della larghezza _(numero)_
> :warning: **Importante:**
diff --git a/docs/readme_ja.md b/docs/readme_ja.md
index 2c2def7fca1a6..e6629ae2c97ea 100644
--- a/docs/readme_ja.md
+++ b/docs/readme_ja.md
@@ -174,7 +174,7 @@ bg_color オプションで複数のカンマ区切りの値を指定してグ
- `hide` - 特定の言語を隠す _(カンマ区切りで指定)_
- `hide_title` - _(boolean)_
-- `layout` - `default` か `compact` のいずれかのレイアウトに切り替える
+- `layout` - `normal` & `compact` & `donut` & `pie` のいずれかのレイアウトに切り替える
- `card_width` - カードの横幅 _(number)_
- `langs_count` - 表示される言語の数 _(1 ~ 10, 初期値 5)_
- `exclude_repo` - 指定されたリポジトリを除外する _(カンマ区切りで指定)_
diff --git a/docs/readme_kr.md b/docs/readme_kr.md
index 0d7bced34ccde..28207af5ed7a6 100644
--- a/docs/readme_kr.md
+++ b/docs/readme_kr.md
@@ -189,7 +189,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
- `hide` - 카드에서 특정 언어 제외 _(Comma-separated values)_
- `hide_title` - 타이틀 제외 _(boolean)_
-- `layout` - 사용 가능한 두 가지 값, `default` & `compact` 중 표시 형태 선택
+- `layout` - 4가지 값 사용 가능, `normal` & `compact` & `donut` & `pie` 중 표시 형태 선택
- `card_width` - 카드 너비 직접 설정 _(number)_
- `langs_count` - 카드에 표시할 언어의 수 (1-10 사이, 기본 값 : 5) _(number)_
- `exclude_repo` - 통계에 제외할 저장소 지정 _(Comma-separated values)_
diff --git a/docs/readme_nl.md b/docs/readme_nl.md
index f70828f142a88..04ba9cf4bb516 100644
--- a/docs/readme_nl.md
+++ b/docs/readme_nl.md
@@ -176,7 +176,7 @@ Je kan meerdere komma verdeelde waarden in de bg_color optie geven om een kleure
- `hide` - Verbergt specifieke talen van de kaart _(komma gescheiden waardes)_
- `hide_title` - _(boolean)_
-- `layout` - Keuze voor de twee beschikbare layouts `default` & `compact`
+- `layout` - Keuze uit de vier beschikbare indelingen `normal` & `compact` & `donut` & `pie`
- `card_width` - Stelt de breedte van de kaart handmatig in. _(nummer)_
- `langs_count` - Laat meer talen op de kaart zien, waarde tussen 1-10, staat standaard op to 5 _(nummer)_
- `exclude_repo` - Verbergt specifieke repositories _(komma gescheiden waardes)_
diff --git a/docs/readme_np.md b/docs/readme_np.md
index b322545c0235e..088039dd3bc66 100644
--- a/docs/readme_np.md
+++ b/docs/readme_np.md
@@ -174,7 +174,7 @@ You can provide multiple comma-separated values in bg_color option to render a g
- `hide` - Hide the languages specified from the card _(Comma-separated values)_
- `hide_title` - _(boolean)_
-- `layout` - Switch between two available layouts `default` & `compact`
+- `layout` - Switch between four available layouts `normal` & `compact` & `donut` & `pie`. Default: `normal`.
- `card_width` - Set the card's width manually _(number)_
- `langs_count` - Show more languages on the card, between 1-10, defaults to 5 _(number)_
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_
diff --git a/docs/readme_pt-BR.md b/docs/readme_pt-BR.md
index cf6eeedc4ded6..bcb58f2b3625b 100644
--- a/docs/readme_pt-BR.md
+++ b/docs/readme_pt-BR.md
@@ -164,7 +164,7 @@ Personalize a aparência do seu `Stats Card` ou `Repo Card` da maneira que desej
- `hide` - Oculta linguagens específicas _(Valores separados por vírgulas)_
- `hide_title` - Oculta o título _(boolean)_
-- `layout` - Alterna entre os dois layouts disponíveis `default` & `compact`
+- `layout` - Alterna entre os quatro layouts disponíveis `normal` & `compact` & `donut` & `pie`
- `card_width` - Define a largura do cartão manualmente _(number)_
> :warning: **Importante:**
diff --git a/docs/readme_tr.md b/docs/readme_tr.md
index fe5aff738c13a..d08a00cb45721 100644
--- a/docs/readme_tr.md
+++ b/docs/readme_tr.md
@@ -176,7 +176,7 @@ bg_color içerisinde birden fazla rengi gradient olarak göstermek için virgül
- `hide` - Belirli bir dili listede gizler _(Virgül ile ayırılmış değerlerle)_
- `hide_title` - _(boolean)_
-- `layout` - Uygun olan iki tasarım / layout arasında değişiklik yapar `default` & `compact`
+- `layout` - Dört uygun tasarım / düzen arasında geçiş `normal` & `compact` & `donut` & `pie`
- `card_width` - Kartın genişliğini manuel olarak belirler _(number)_
- `langs_count` - 1-10 arasında istediğiniz kadar dil gösterebilirsiniz. Varsayılan: 5 _(number)_
- `exclude_repo` - Belirli repoları listeden çıkartır _(Virgül ile ayırılmış değerlerle)_
From f9427b2a54bbab31aa7874da25a2e3227dbb4e77 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Fri, 19 May 2023 11:45:29 +0300
Subject: [PATCH 224/905] Top languages card donut vertical layout (#2701)
* Top languages card donut layout
* dev
* dev
* dev
* dev
---
readme.md | 14 +++-
src/cards/top-languages-card.js | 97 ++++++++++++++++++++-
src/cards/types.d.ts | 2 +-
tests/renderTopLanguages.test.js | 140 +++++++++++++++++++++++++++++++
4 files changed, 250 insertions(+), 3 deletions(-)
diff --git a/readme.md b/readme.md
index f59342f3ab9f4..0de7caa4756d5 100644
--- a/readme.md
+++ b/readme.md
@@ -303,7 +303,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `hide` - Hide the languages specified from the card _(Comma-separated values)_. Default: `[] (blank array)`.
- `hide_title` - _(boolean)_. Default: `false`.
-- `layout` - Switch between four available layouts `normal` & `compact` & `donut` & `pie`. Default: `normal`.
+- `layout` - Switch between four available layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`. Default: `normal`.
- `card_width` - Set the card's width manually _(number)_. Default `300`.
- `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`.
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
@@ -431,6 +431,14 @@ You can use the `&layout=donut` option to change the card design.
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut)](https://github.com/anuraghazra/github-readme-stats)
```
+### Donut Vertical Chart Language Card Layout
+
+You can use the `&layout=donut-vertical` option to change the card design.
+
+```md
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut-vertical)](https://github.com/anuraghazra/github-readme-stats)
+```
+
### Pie Chart Language Card Layout
You can use the `&layout=pie` option to change the card design.
@@ -459,6 +467,10 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut)](https://github.com/anuraghazra/github-readme-stats)
+- Donut Vertical Chart layout
+
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut-vertical)](https://github.com/anuraghazra/github-readme-stats)
+
- Pie Chart layout
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=pie)](https://github.com/anuraghazra/github-readme-stats)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index e03e8bcb00a35..c6cedb1fb077c 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -84,6 +84,16 @@ const cartesianToPolar = (centerX, centerY, x, y) => {
return { radius, angleInDegrees };
};
+/**
+ * Calculates length of circle.
+ *
+ * @param {number} radius Radius of the circle.
+ * @returns {number} The length of the circle.
+ */
+const getCircleLength = (radius) => {
+ return 2 * Math.PI * radius;
+};
+
/**
* Calculates height for the compact layout.
*
@@ -114,6 +124,16 @@ const calculateDonutLayoutHeight = (totalLangs) => {
return 215 + Math.max(totalLangs - 5, 0) * 32;
};
+/**
+ * Calculates height for the donut vertical layout.
+ *
+ * @param {number} totalLangs Total number of languages.
+ * @returns {number} Card height.
+ */
+const calculateDonutVerticalLayoutHeight = (totalLangs) => {
+ return 300 + Math.round(totalLangs / 2) * 25;
+};
+
/**
* Calculates height for the pie layout.
*
@@ -371,6 +391,76 @@ const renderCompactLayout = (langs, width, totalLanguageSize, hideProgress) => {
`;
};
+/**
+ * Renders donut vertical layout to display user's most frequently used programming languages.
+ *
+ * @param {Lang[]} langs Array of programming languages.
+ * @param {number} totalLanguageSize Total size of all languages.
+ * @returns {string} Compact layout card SVG object.
+ */
+const renderDonutVerticalLayout = (langs, totalLanguageSize) => {
+ // Donut vertical chart radius and total length
+ const radius = 80;
+ const totalCircleLength = getCircleLength(radius);
+
+ // SVG circles
+ let circles = [];
+
+ // Start indent for donut vertical chart parts
+ let indent = 0;
+
+ // Start delay coefficient for donut vertical chart parts
+ let startDelayCoefficient = 1;
+
+ // Generate each donut vertical chart part
+ for (const lang of langs) {
+ const percentage = (lang.size / totalLanguageSize) * 100;
+ const circleLength = totalCircleLength * (percentage / 100);
+ const delay = startDelayCoefficient * 100;
+
+ circles.push(`
+
+
+
+ `);
+
+ // Update the indent for the next part
+ indent += circleLength;
+ // Update the start delay coefficient for the next part
+ startDelayCoefficient += 1;
+ }
+
+ return `
+
+
+
+ ${circles.join("")}
+
+
+
+
+ ${createLanguageTextNode({
+ langs,
+ totalSize: totalLanguageSize,
+ hideProgress: false,
+ })}
+
+
+
+ `;
+};
+
/**
* Renders pie layout to display user's most frequently used programming languages.
*
@@ -613,6 +703,9 @@ const renderTopLanguages = (topLangs, options = {}) => {
if (layout === "pie") {
height = calculatePieLayoutHeight(langs.length);
finalLayout = renderPieLayout(langs, totalLanguageSize);
+ } else if (layout === "donut-vertical") {
+ height = calculateDonutVerticalLayoutHeight(langs.length);
+ finalLayout = renderDonutVerticalLayout(langs, totalLanguageSize);
} else if (layout === "compact" || hide_progress == true) {
height =
calculateCompactLayoutHeight(langs.length) + (hide_progress ? -25 : 0);
@@ -688,7 +781,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
`,
);
- if (layout === "pie") {
+ if (layout === "pie" || layout === "donut-vertical") {
return card.render(finalLayout);
}
@@ -705,9 +798,11 @@ export {
radiansToDegrees,
polarToCartesian,
cartesianToPolar,
+ getCircleLength,
calculateCompactLayoutHeight,
calculateNormalLayoutHeight,
calculateDonutLayoutHeight,
+ calculateDonutVerticalLayoutHeight,
calculatePieLayoutHeight,
donutCenterTranslation,
trimTopLanguages,
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index 7945118cbe384..d6a1de05d176f 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -39,7 +39,7 @@ export type TopLangOptions = CommonOptions & {
hide_border: boolean;
card_width: number;
hide: string[];
- layout: "compact" | "normal" | "donut" | "pie";
+ layout: "compact" | "normal" | "donut" | "donut-vertical" | "pie";
custom_title: string;
langs_count: number;
disable_animations: boolean;
diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js
index a8bc873a79ef1..ed3bd3d76973c 100644
--- a/tests/renderTopLanguages.test.js
+++ b/tests/renderTopLanguages.test.js
@@ -6,9 +6,11 @@ import {
radiansToDegrees,
polarToCartesian,
cartesianToPolar,
+ getCircleLength,
calculateCompactLayoutHeight,
calculateNormalLayoutHeight,
calculateDonutLayoutHeight,
+ calculateDonutVerticalLayoutHeight,
calculatePieLayoutHeight,
donutCenterTranslation,
trimTopLanguages,
@@ -70,6 +72,20 @@ const langPercentFromDonutLayoutSvg = (d, centerX, centerY) => {
return (endAngle - startAngle) / 3.6;
};
+/**
+ * Calculate language percentage for donut vertical chart SVG.
+ *
+ * @param {number} partLength Length of current chart part..
+ * @param {number} totalCircleLength Total length of circle.
+ * @return {number} Chart part percentage.
+ */
+const langPercentFromDonutVerticalLayoutSvg = (
+ partLength,
+ totalCircleLength,
+) => {
+ return (partLength / totalCircleLength) * 100;
+};
+
/**
* Retrieve the language percentage from the pie chart SVG.
*
@@ -230,6 +246,20 @@ describe("Test renderTopLanguages helper functions", () => {
expect(calculateDonutLayoutHeight(10)).toBe(375);
});
+ it("calculateDonutVerticalLayoutHeight", () => {
+ expect(calculateDonutVerticalLayoutHeight(0)).toBe(300);
+ expect(calculateDonutVerticalLayoutHeight(1)).toBe(325);
+ expect(calculateDonutVerticalLayoutHeight(2)).toBe(325);
+ expect(calculateDonutVerticalLayoutHeight(3)).toBe(350);
+ expect(calculateDonutVerticalLayoutHeight(4)).toBe(350);
+ expect(calculateDonutVerticalLayoutHeight(5)).toBe(375);
+ expect(calculateDonutVerticalLayoutHeight(6)).toBe(375);
+ expect(calculateDonutVerticalLayoutHeight(7)).toBe(400);
+ expect(calculateDonutVerticalLayoutHeight(8)).toBe(400);
+ expect(calculateDonutVerticalLayoutHeight(9)).toBe(425);
+ expect(calculateDonutVerticalLayoutHeight(10)).toBe(425);
+ });
+
it("calculatePieLayoutHeight", () => {
expect(calculatePieLayoutHeight(0)).toBe(300);
expect(calculatePieLayoutHeight(1)).toBe(325);
@@ -258,6 +288,18 @@ describe("Test renderTopLanguages helper functions", () => {
expect(donutCenterTranslation(10)).toBe(35);
});
+ it("getCircleLength", () => {
+ expect(getCircleLength(20)).toBeCloseTo(125.663);
+ expect(getCircleLength(30)).toBeCloseTo(188.495);
+ expect(getCircleLength(40)).toBeCloseTo(251.327);
+ expect(getCircleLength(50)).toBeCloseTo(314.159);
+ expect(getCircleLength(60)).toBeCloseTo(376.991);
+ expect(getCircleLength(70)).toBeCloseTo(439.822);
+ expect(getCircleLength(80)).toBeCloseTo(502.654);
+ expect(getCircleLength(90)).toBeCloseTo(565.486);
+ expect(getCircleLength(100)).toBeCloseTo(628.318);
+ });
+
it("trimTopLanguages", () => {
expect(trimTopLanguages([])).toStrictEqual({
langs: [],
@@ -569,6 +611,104 @@ describe("Test renderTopLanguages", () => {
"circle",
);
});
+
+ it("should render with layout donut vertical", () => {
+ document.body.innerHTML = renderTopLanguages(langs, {
+ layout: "donut-vertical",
+ });
+
+ expect(queryByTestId(document.body, "header")).toHaveTextContent(
+ "Most Used Languages",
+ );
+
+ expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
+ "HTML 40.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-donut")[0]).toHaveAttribute(
+ "size",
+ "40",
+ );
+
+ const totalCircleLength = queryAllByTestId(
+ document.body,
+ "lang-donut",
+ )[0].getAttribute("stroke-dasharray");
+
+ const HTMLLangPercent = langPercentFromDonutVerticalLayoutSvg(
+ queryAllByTestId(document.body, "lang-donut")[1].getAttribute(
+ "stroke-dashoffset",
+ ) -
+ queryAllByTestId(document.body, "lang-donut")[0].getAttribute(
+ "stroke-dashoffset",
+ ),
+ totalCircleLength,
+ );
+ expect(HTMLLangPercent).toBeCloseTo(40);
+
+ expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent(
+ "javascript 40.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-donut")[1]).toHaveAttribute(
+ "size",
+ "40",
+ );
+ const javascriptLangPercent = langPercentFromDonutVerticalLayoutSvg(
+ queryAllByTestId(document.body, "lang-donut")[2].getAttribute(
+ "stroke-dashoffset",
+ ) -
+ queryAllByTestId(document.body, "lang-donut")[1].getAttribute(
+ "stroke-dashoffset",
+ ),
+ totalCircleLength,
+ );
+ expect(javascriptLangPercent).toBeCloseTo(40);
+
+ expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent(
+ "css 20.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-donut")[2]).toHaveAttribute(
+ "size",
+ "20",
+ );
+ const cssLangPercent = langPercentFromDonutVerticalLayoutSvg(
+ totalCircleLength -
+ queryAllByTestId(document.body, "lang-donut")[2].getAttribute(
+ "stroke-dashoffset",
+ ),
+ totalCircleLength,
+ );
+ expect(cssLangPercent).toBeCloseTo(20);
+
+ expect(HTMLLangPercent + javascriptLangPercent + cssLangPercent).toBe(100);
+ });
+
+ it("should render with layout donut vertical full donut circle of one language is 100%", () => {
+ document.body.innerHTML = renderTopLanguages(
+ { HTML: langs.HTML },
+ { layout: "donut-vertical" },
+ );
+ expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
+ "HTML 100.00%",
+ );
+ expect(queryAllByTestId(document.body, "lang-donut")[0]).toHaveAttribute(
+ "size",
+ "100",
+ );
+ const totalCircleLength = queryAllByTestId(
+ document.body,
+ "lang-donut",
+ )[0].getAttribute("stroke-dasharray");
+
+ const HTMLLangPercent = langPercentFromDonutVerticalLayoutSvg(
+ totalCircleLength -
+ queryAllByTestId(document.body, "lang-donut")[0].getAttribute(
+ "stroke-dashoffset",
+ ),
+ totalCircleLength,
+ );
+ expect(HTMLLangPercent).toBeCloseTo(100);
+ });
+
it("should render with layout pie", () => {
document.body.innerHTML = renderTopLanguages(langs, { layout: "pie" });
From c8d5eda27cc30adf3c73ad01545546b7f5fddbf1 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 22 May 2023 23:39:43 +0300
Subject: [PATCH 225/905] Docs (translations): add top languages card donut
vertical layout (#2739)
---
docs/readme_cn.md | 2 +-
docs/readme_de.md | 2 +-
docs/readme_es.md | 2 +-
docs/readme_fr.md | 2 +-
docs/readme_it.md | 2 +-
docs/readme_ja.md | 2 +-
docs/readme_kr.md | 2 +-
docs/readme_nl.md | 2 +-
docs/readme_np.md | 2 +-
docs/readme_pt-BR.md | 2 +-
docs/readme_tr.md | 2 +-
11 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/docs/readme_cn.md b/docs/readme_cn.md
index 3bd2c149c8b91..8fda35b348140 100644
--- a/docs/readme_cn.md
+++ b/docs/readme_cn.md
@@ -171,7 +171,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
- `hide` - 从卡片中隐藏指定语言 _(Comma seperated values)_
- `hide_title` - _(boolean)_
-- `layout` - 提供四種佈局 `normal` & `compact` & `donut` & `pie` 间切换
+- `layout` - 提供五種佈局 `normal` & `compact` & `donut` & `donut-vertical` & `pie` 间切换
- `card_width` - 手动设置卡片的宽度 _(number)_
> :warning: **重要:**
diff --git a/docs/readme_de.md b/docs/readme_de.md
index a94e8c2c8613c..bb3e312909f3a 100644
--- a/docs/readme_de.md
+++ b/docs/readme_de.md
@@ -161,7 +161,7 @@ Du kannst mehrere, mit Kommas separierte, Werte in der bg_color Option angeben,
- `hide` - Verbirgt die angegebenen Sprachen von der Karte _(Komma separierte Werte)_
- `hide_title` - _(Boolean)_
-- `layout` - Wechseln Sie zwischen den vier verfügbaren Layouts `normal` & `compact` & `donut` & `pie`
+- `layout` - Wechseln Sie zwischen den fünf verfügbaren Layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`
- `card_width` - Lege die Breite der Karte manuell fest _(Zahl)_
> :warning: **Wichtig:**
diff --git a/docs/readme_es.md b/docs/readme_es.md
index a353502ca5697..5815e9089a90c 100644
--- a/docs/readme_es.md
+++ b/docs/readme_es.md
@@ -175,7 +175,7 @@ Puedes pasar mútliples valores separados por coma en la opción `bg_color` para
- `hide` - Oculta de la tarjeta los lenguajes especificados _(valores separados por comas)_
- `hide_title` - _(booleano)_
-- `layout` - Cambiar entre los cuatro diseños disponibles `normal` & `compact` & `donut` & `pie`
+- `layout` - Cambiar entre los cinco diseños disponibles `normal` & `compact` & `donut` & `donut-vertical` & `pie`
- `card_width` - Establece el ancho de la tarjeta manualmente _(número)_
- `langs_count` - Muestra más lenguajes en la tarjeta, entre 1-10, por defecto 5 _(número)_
- `exclude_repo` - Excluye los repositorios especificados _(valores separados por comas)_
diff --git a/docs/readme_fr.md b/docs/readme_fr.md
index 427f2971451c8..2a67ef2cd5e02 100644
--- a/docs/readme_fr.md
+++ b/docs/readme_fr.md
@@ -171,7 +171,7 @@ Vous pouvez fournir plusieurs valeurs (suivie d'une virgule) dans l'option bg_co
- `hide` - Masquer les langages spécifiés sur la carte _(Comma seperated values)_
- `hide_title` - Masquer le titre _(boolean)_
-- `layout` - Alterner entre 4 mise en page `normal` & `compact` & `donut` & `pie`
+- `layout` - Alterner entre 5 mise en page `normal` & `compact` & `donut` & `donut-vertical` & `pie`
- `card_width` - Fixer la largeur de la carte manuellement _(number)_
> :warning: **Important:**
diff --git a/docs/readme_it.md b/docs/readme_it.md
index 4418c333b4be4..f1c20d1a48d16 100644
--- a/docs/readme_it.md
+++ b/docs/readme_it.md
@@ -171,7 +171,7 @@ Puoi fornire valori separati da virgola nel parametro bg_color per creare un gra
- `hide` - Nasconde un linguaggio specifico _(valori separati da virgola)_
- `hide_title` - Nasconde il titolo _(booleano)_
-- `layout` - Specificare il tipo di layout, `normal` (esteso), `compact` (compatto), `donut` (ciambella) e `pie` (torta)
+- `layout` - Specificare il tipo di layout, `normal` (esteso), `compact` (compatto), `donut` (ciambella), `donut-vertical` (ciambella verticale) e `pie` (torta)
- `card_width` - Specifica il valore della larghezza _(numero)_
> :warning: **Importante:**
diff --git a/docs/readme_ja.md b/docs/readme_ja.md
index e6629ae2c97ea..4b1dcd2bcf314 100644
--- a/docs/readme_ja.md
+++ b/docs/readme_ja.md
@@ -174,7 +174,7 @@ bg_color オプションで複数のカンマ区切りの値を指定してグ
- `hide` - 特定の言語を隠す _(カンマ区切りで指定)_
- `hide_title` - _(boolean)_
-- `layout` - `normal` & `compact` & `donut` & `pie` のいずれかのレイアウトに切り替える
+- `layout` - `normal` & `compact` & `donut` & `donut-vertical` & `pie` のいずれかのレイアウトに切り替える
- `card_width` - カードの横幅 _(number)_
- `langs_count` - 表示される言語の数 _(1 ~ 10, 初期値 5)_
- `exclude_repo` - 指定されたリポジトリを除外する _(カンマ区切りで指定)_
diff --git a/docs/readme_kr.md b/docs/readme_kr.md
index 28207af5ed7a6..6113eedc00d10 100644
--- a/docs/readme_kr.md
+++ b/docs/readme_kr.md
@@ -189,7 +189,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
- `hide` - 카드에서 특정 언어 제외 _(Comma-separated values)_
- `hide_title` - 타이틀 제외 _(boolean)_
-- `layout` - 4가지 값 사용 가능, `normal` & `compact` & `donut` & `pie` 중 표시 형태 선택
+- `layout` - 5가지 값 사용 가능, `normal` & `compact` & `donut` & `donut-vertical` & `pie` 중 표시 형태 선택
- `card_width` - 카드 너비 직접 설정 _(number)_
- `langs_count` - 카드에 표시할 언어의 수 (1-10 사이, 기본 값 : 5) _(number)_
- `exclude_repo` - 통계에 제외할 저장소 지정 _(Comma-separated values)_
diff --git a/docs/readme_nl.md b/docs/readme_nl.md
index 04ba9cf4bb516..8d38d06adbcd1 100644
--- a/docs/readme_nl.md
+++ b/docs/readme_nl.md
@@ -176,7 +176,7 @@ Je kan meerdere komma verdeelde waarden in de bg_color optie geven om een kleure
- `hide` - Verbergt specifieke talen van de kaart _(komma gescheiden waardes)_
- `hide_title` - _(boolean)_
-- `layout` - Keuze uit de vier beschikbare indelingen `normal` & `compact` & `donut` & `pie`
+- `layout` - Kies uit de vijf beschikbare lay-outs `normal` & `compact` & `donut` & `donut-vertical` & `pie`
- `card_width` - Stelt de breedte van de kaart handmatig in. _(nummer)_
- `langs_count` - Laat meer talen op de kaart zien, waarde tussen 1-10, staat standaard op to 5 _(nummer)_
- `exclude_repo` - Verbergt specifieke repositories _(komma gescheiden waardes)_
diff --git a/docs/readme_np.md b/docs/readme_np.md
index 088039dd3bc66..e491426301903 100644
--- a/docs/readme_np.md
+++ b/docs/readme_np.md
@@ -174,7 +174,7 @@ You can provide multiple comma-separated values in bg_color option to render a g
- `hide` - Hide the languages specified from the card _(Comma-separated values)_
- `hide_title` - _(boolean)_
-- `layout` - Switch between four available layouts `normal` & `compact` & `donut` & `pie`. Default: `normal`.
+- `layout` - Switch between five available layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`. Default: `normal`.
- `card_width` - Set the card's width manually _(number)_
- `langs_count` - Show more languages on the card, between 1-10, defaults to 5 _(number)_
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_
diff --git a/docs/readme_pt-BR.md b/docs/readme_pt-BR.md
index bcb58f2b3625b..a590440ef69ec 100644
--- a/docs/readme_pt-BR.md
+++ b/docs/readme_pt-BR.md
@@ -164,7 +164,7 @@ Personalize a aparência do seu `Stats Card` ou `Repo Card` da maneira que desej
- `hide` - Oculta linguagens específicas _(Valores separados por vírgulas)_
- `hide_title` - Oculta o título _(boolean)_
-- `layout` - Alterna entre os quatro layouts disponíveis `normal` & `compact` & `donut` & `pie`
+- `layout` - Alternar entre os cinco layouts disponíveis `normal` & `compact` & `donut` & `donut-vertical` & `pie`
- `card_width` - Define a largura do cartão manualmente _(number)_
> :warning: **Importante:**
diff --git a/docs/readme_tr.md b/docs/readme_tr.md
index d08a00cb45721..9ee358b97bdec 100644
--- a/docs/readme_tr.md
+++ b/docs/readme_tr.md
@@ -176,7 +176,7 @@ bg_color içerisinde birden fazla rengi gradient olarak göstermek için virgül
- `hide` - Belirli bir dili listede gizler _(Virgül ile ayırılmış değerlerle)_
- `hide_title` - _(boolean)_
-- `layout` - Dört uygun tasarım / düzen arasında geçiş `normal` & `compact` & `donut` & `pie`
+- `layout` - Beş uygun tasarım / düzen arasında geçiş yapın `normal` & `compact` & `donut` & `donut-vertical` & `pie`
- `card_width` - Kartın genişliğini manuel olarak belirler _(number)_
- `langs_count` - 1-10 arasında istediğiniz kadar dil gösterebilirsiniz. Varsayılan: 5 _(number)_
- `exclude_repo` - Belirli repoları listeden çıkartır _(Virgül ile ayırılmış değerlerle)_
From ff2e02ba6841a263b6dc26807c0ea350fafac03b Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 22 May 2023 23:40:21 +0300
Subject: [PATCH 226/905] Docs: fix top languages card available layouts number
(#2738)
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index 0de7caa4756d5..58b8509c09c52 100644
--- a/readme.md
+++ b/readme.md
@@ -303,7 +303,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `hide` - Hide the languages specified from the card _(Comma-separated values)_. Default: `[] (blank array)`.
- `hide_title` - _(boolean)_. Default: `false`.
-- `layout` - Switch between four available layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`. Default: `normal`.
+- `layout` - Switch between five available layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`. Default: `normal`.
- `card_width` - Set the card's width manually _(number)_. Default `300`.
- `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`.
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
From c96e84a9ae9a095d3787324f84a04f0024145aff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Rozet?=
Date: Fri, 26 May 2023 15:39:35 +0200
Subject: [PATCH 227/905] Ranking System v2 (#1186)
* Revise rank calculation
* Replace contributions by commits
* Lower average stats and S+ threshold
* Fix calculateRank.test.js
Missing key in dictionary constructor
Co-authored-by: Rick Staa
* refactor: run prettier
* feat: change star weight to 0.75
* Separate PRs and issues
* Tweak weights
* Add count_private back
* fix: enable 'count_private' again
* test: fix tests
* refactor: improve code formatting
* Higher targets
---------
Co-authored-by: Rick Staa
---
docs/readme_fr.md | 14 +---
readme.md | 15 +---
src/calculateRank.js | 135 +++++++++++++---------------------
src/fetchers/stats-fetcher.js | 39 ++++------
tests/api.test.js | 45 ++----------
tests/calculateRank.test.js | 86 ++++++++++++++++++++--
tests/fetchStats.test.js | 101 ++++++++++---------------
7 files changed, 192 insertions(+), 243 deletions(-)
diff --git a/docs/readme_fr.md b/docs/readme_fr.md
index 2a67ef2cd5e02..1a597dd19c4ba 100644
--- a/docs/readme_fr.md
+++ b/docs/readme_fr.md
@@ -90,18 +90,6 @@ Pour masquer des statistiques spécifiques, vous pouvez passer un paramètre de
![Les Stats GitHub de Anurag](https://github-readme-stats.vercel.app/api?username=anuraghazra&hide=contribs,prs)
```
-### Ajouter le compte des contributions privées au compte des commits totaux
-
-Vous pouvez ajouter le compte de toutes vos contributions privées au compte total des engagements en utilisant le paramètre de requête `?count_private=true`.
-
-_Note: Si vous déployez vous-même ce projet, les contributions privées seront comptées par défaut ; sinon, vous devez choisir de partager les comptes de vos contributions privées._
-
-> Options: `&count_private=true`
-
-```md
-![Les Stats GitHub de Anurag](https://github-readme-stats.vercel.app/api?username=anuraghazra&count_private=true)
-```
-
### Afficher les icônes
Pour activer les icônes, vous pouvez passer `show_icons=true` dans le paramètre de requête, comme ceci :
@@ -160,7 +148,7 @@ Vous pouvez fournir plusieurs valeurs (suivie d'une virgule) dans l'option bg_co
- `hide_rank` - Masquer le rang _(boolean)_
- `show_icons` - Afficher les icônes _(boolean)_
- `include_all_commits` - Compter le total de commits au lieu de ne compter que les commits de l'année en cours _(boolean)_
-- `count_private` - Compter les commits privés _(boolean)_
+- `count_private` - Compter les contributions privées _(boolean)_
- `line_height` - Fixer la hauteur de la ligne entre les textes _(number)_
#### Repo Card Exclusive Options:
diff --git a/readme.md b/readme.md
index 58b8509c09c52..dc60369751a27 100644
--- a/readme.md
+++ b/readme.md
@@ -120,19 +120,6 @@ You can pass a query parameter `&hide=` to hide any specific stats with comma-se
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&hide=contribs,prs)
```
-### Adding private contributions count to total commits count
-
-You can add the count of all your private contributions to the total commits count by using the query parameter `&count_private=true`.
-
-> **Note**
-> If you are deploying this project yourself, the private contributions will be counted by default. If you are using the public Vercel instance, you need to choose to [share your private contributions](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/managing-contribution-settings-on-your-profile/showing-your-private-contributions-and-achievements-on-your-profile).
-
-> Options: `&count_private=true`
-
-```md
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&count_private=true)
-```
-
### Showing icons
To enable icons, you can pass `&show_icons=true` in the query param, like so:
@@ -283,7 +270,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `rank_icon` - Shows alternative rank icon (i.e. `github` or `default`). Default: `default`.
- `show_icons` - _(boolean)_. Default: `false`.
- `include_all_commits` - Count total commits instead of just the current year commits _(boolean)_. Default: `false`.
-- `count_private` - Count private commits _(boolean)_. Default: `false`.
+- `count_private` - Count private contributions _(boolean)_. Default: `false`.
- `line_height` - Sets the line height between text _(number)_. Default: `25`.
- `exclude_repo` - Exclude stars from specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
- `custom_title` - Sets a custom title for the card. Default: ` GitHub Stats`.
diff --git a/src/calculateRank.js b/src/calculateRank.js
index 215c24d848c34..7648ad412ed67 100644
--- a/src/calculateRank.js
+++ b/src/calculateRank.js
@@ -1,105 +1,72 @@
-/**
- * Calculates the probability of x taking on x or a value less than x in a normal distribution
- * with mean and standard deviation.
- *
- * @see https://stackoverflow.com/a/5263759/10629172
- *
- * @param {string} mean The mean of the normal distribution.
- * @param {number} sigma The standard deviation of the normal distribution.
- * @param {number} to The value to calculate the probability for.
- * @returns {number} Probability.
- */
-const normalcdf = (mean, sigma, to) => {
- var z = (to - mean) / Math.sqrt(2 * sigma * sigma);
- var t = 1 / (1 + 0.3275911 * Math.abs(z));
- var a1 = 0.254829592;
- var a2 = -0.284496736;
- var a3 = 1.421413741;
- var a4 = -1.453152027;
- var a5 = 1.061405429;
- var erf =
- 1 - ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * Math.exp(-z * z);
- var sign = 1;
- if (z < 0) {
- sign = -1;
- }
- return (1 / 2) * (1 + sign * erf);
-};
+function expsf(x, lambda = 1) {
+ return 2 ** (-lambda * x);
+}
/**
* Calculates the users rank.
*
* @param {object} params Parameters on which the user's rank depends.
- * @param {number} params.totalRepos Total number of repos.
- * @param {number} params.totalCommits Total number of commits.
- * @param {number} params.contributions The number of contributions.
- * @param {number} params.followers The number of followers.
+ * @param {boolean} params.all_commits Whether `include_all_commits` was used.
+ * @param {number} params.commits Number of commits.
* @param {number} params.prs The number of pull requests.
* @param {number} params.issues The number of issues.
- * @param {number} params.stargazers The number of stars.
+ * @param {number} params.repos Total number of repos.
+ * @param {number} params.stars The number of stars.
+ * @param {number} params.followers The number of followers.
* @returns {{level: string, score: number}}} The users rank.
*/
-const calculateRank = ({
- totalRepos,
- totalCommits,
- contributions,
- followers,
+function calculateRank({
+ all_commits,
+ commits,
prs,
issues,
- stargazers,
-}) => {
- const COMMITS_OFFSET = 1.65;
- const CONTRIBS_OFFSET = 1.65;
- const ISSUES_OFFSET = 1;
- const STARS_OFFSET = 0.75;
- const PRS_OFFSET = 0.5;
- const FOLLOWERS_OFFSET = 0.45;
- const REPO_OFFSET = 1;
-
- const ALL_OFFSETS =
- CONTRIBS_OFFSET +
- ISSUES_OFFSET +
- STARS_OFFSET +
- PRS_OFFSET +
- FOLLOWERS_OFFSET +
- REPO_OFFSET;
-
- const RANK_S_VALUE = 1;
- const RANK_DOUBLE_A_VALUE = 25;
- const RANK_A2_VALUE = 45;
- const RANK_A3_VALUE = 60;
- const RANK_B_VALUE = 100;
+ repos, // unused
+ stars,
+ followers,
+}) {
+ const COMMITS_MEAN = all_commits ? 1000 : 250,
+ COMMITS_WEIGHT = 2;
+ const PRS_MEAN = 50,
+ PRS_WEIGHT = 3;
+ const ISSUES_MEAN = 25,
+ ISSUES_WEIGHT = 1;
+ const STARS_MEAN = 250,
+ STARS_WEIGHT = 4;
+ const FOLLOWERS_MEAN = 25,
+ FOLLOWERS_WEIGHT = 1;
- const TOTAL_VALUES =
- RANK_S_VALUE +
- RANK_DOUBLE_A_VALUE +
- RANK_A2_VALUE +
- RANK_A3_VALUE +
- RANK_B_VALUE;
+ const TOTAL_WEIGHT =
+ COMMITS_WEIGHT +
+ PRS_WEIGHT +
+ ISSUES_WEIGHT +
+ STARS_WEIGHT +
+ FOLLOWERS_WEIGHT;
- // prettier-ignore
- const score = (
- totalCommits * COMMITS_OFFSET +
- contributions * CONTRIBS_OFFSET +
- issues * ISSUES_OFFSET +
- stargazers * STARS_OFFSET +
- prs * PRS_OFFSET +
- followers * FOLLOWERS_OFFSET +
- totalRepos * REPO_OFFSET
- ) / 100;
+ const rank =
+ (COMMITS_WEIGHT * expsf(commits, 1 / COMMITS_MEAN) +
+ PRS_WEIGHT * expsf(prs, 1 / PRS_MEAN) +
+ ISSUES_WEIGHT * expsf(issues, 1 / ISSUES_MEAN) +
+ STARS_WEIGHT * expsf(stars, 1 / STARS_MEAN) +
+ FOLLOWERS_WEIGHT * expsf(followers, 1 / FOLLOWERS_MEAN)) /
+ TOTAL_WEIGHT;
- const normalizedScore = normalcdf(score, TOTAL_VALUES, ALL_OFFSETS) * 100;
+ const RANK_S_PLUS = 0.025;
+ const RANK_S = 0.1;
+ const RANK_A_PLUS = 0.25;
+ const RANK_A = 0.5;
+ const RANK_B_PLUS = 0.75;
const level = (() => {
- if (normalizedScore < RANK_S_VALUE) return "S+";
- if (normalizedScore < RANK_DOUBLE_A_VALUE) return "S";
- if (normalizedScore < RANK_A2_VALUE) return "A++";
- if (normalizedScore < RANK_A3_VALUE) return "A+";
- return "B+";
+ if (rank <= RANK_S_PLUS) return "S+";
+ if (rank <= RANK_S) return "S";
+ if (rank <= RANK_A_PLUS) return "A+";
+ if (rank <= RANK_A) return "A";
+ if (rank <= RANK_B_PLUS) return "B+";
+ return "B";
})();
- return { level, score: normalizedScore };
-};
+ return { level, score: rank * 100 };
+}
export { calculateRank };
export default calculateRank;
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index 8603e38bbf59d..8fecffa466f8d 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -192,7 +192,7 @@ const fetchStats = async (
totalIssues: 0,
totalStars: 0,
contributedTo: 0,
- rank: { level: "C", score: 0 },
+ rank: { level: "B", score: 0 },
};
let res = await statsFetcher(username);
@@ -220,53 +220,44 @@ const fetchStats = async (
const user = res.data.data.user;
- // populate repoToHide map for quick lookup
- // while filtering out
- let repoToHide = {};
- if (exclude_repo) {
- exclude_repo.forEach((repoName) => {
- repoToHide[repoName] = true;
- });
- }
-
stats.name = user.name || user.login;
- stats.totalIssues = user.openIssues.totalCount + user.closedIssues.totalCount;
-
- // normal commits
- stats.totalCommits = user.contributionsCollection.totalCommitContributions;
- // if include_all_commits then just get that,
- // since totalCommitsFetcher already sends totalCommits no need to +=
+ // if include_all_commits, fetch all commits using the REST API.
if (include_all_commits) {
stats.totalCommits = await totalCommitsFetcher(username);
+ } else {
+ stats.totalCommits = user.contributionsCollection.totalCommitContributions;
}
- // if count_private then add private commits to totalCommits so far.
+ // if count_private, add private contributions to totalCommits.
if (count_private) {
stats.totalCommits +=
user.contributionsCollection.restrictedContributionsCount;
}
stats.totalPRs = user.pullRequests.totalCount;
+ stats.totalIssues = user.openIssues.totalCount + user.closedIssues.totalCount;
stats.contributedTo = user.repositoriesContributedTo.totalCount;
- // Retrieve stars while filtering out repositories to be hidden
+ // Retrieve stars while filtering out repositories to be hidden.
+ let repoToHide = new Set(exclude_repo);
+
stats.totalStars = user.repositories.nodes
.filter((data) => {
- return !repoToHide[data.name];
+ return !repoToHide.has(data.name);
})
.reduce((prev, curr) => {
return prev + curr.stargazers.totalCount;
}, 0);
stats.rank = calculateRank({
- totalCommits: stats.totalCommits,
- totalRepos: user.repositories.totalCount,
- followers: user.followers.totalCount,
- contributions: stats.contributedTo,
- stargazers: stats.totalStars,
+ all_commits: include_all_commits,
+ commits: stats.totalCommits,
prs: stats.totalPRs,
issues: stats.totalIssues,
+ repos: user.repositories.totalCount,
+ stars: stats.totalStars,
+ followers: user.followers.totalCount,
});
return stats;
diff --git a/tests/api.test.js b/tests/api.test.js
index f11832ef9141c..0f14378312435 100644
--- a/tests/api.test.js
+++ b/tests/api.test.js
@@ -12,17 +12,18 @@ const stats = {
totalCommits: 200,
totalIssues: 300,
totalPRs: 400,
- contributedTo: 500,
+ contributedTo: 50,
rank: null,
};
+
stats.rank = calculateRank({
- totalCommits: stats.totalCommits,
- totalRepos: 1,
- followers: 0,
- contributions: stats.contributedTo,
- stargazers: stats.totalStars,
+ all_commits: false,
+ commits: stats.totalCommits,
prs: stats.totalPRs,
issues: stats.totalIssues,
+ repos: 1,
+ stars: stats.totalStars,
+ followers: 0,
});
const data_stats = {
@@ -229,38 +230,6 @@ describe("Test /api/", () => {
}
});
- it("should add private contributions", async () => {
- const { req, res } = faker(
- {
- username: "anuraghazra",
- count_private: true,
- },
- data_stats,
- );
-
- await api(req, res);
-
- expect(res.setHeader).toBeCalledWith("Content-Type", "image/svg+xml");
- expect(res.send).toBeCalledWith(
- renderStatsCard(
- {
- ...stats,
- totalCommits: stats.totalCommits + 100,
- rank: calculateRank({
- totalCommits: stats.totalCommits + 100,
- totalRepos: 1,
- followers: 0,
- contributions: stats.contributedTo,
- stargazers: stats.totalStars,
- prs: stats.totalPRs,
- issues: stats.totalIssues,
- }),
- },
- {},
- ),
- );
- });
-
it("should allow changing ring_color", async () => {
const { req, res } = faker(
{
diff --git a/tests/calculateRank.test.js b/tests/calculateRank.test.js
index 235b1b5f20b04..3bfd7f4376248 100644
--- a/tests/calculateRank.test.js
+++ b/tests/calculateRank.test.js
@@ -2,17 +2,87 @@ import "@testing-library/jest-dom";
import { calculateRank } from "../src/calculateRank.js";
describe("Test calculateRank", () => {
- it("should calculate rank correctly", () => {
+ it("new user gets B rank", () => {
expect(
calculateRank({
- totalCommits: 100,
- totalRepos: 5,
+ all_commits: false,
+ commits: 0,
+ prs: 0,
+ issues: 0,
+ repos: 0,
+ stars: 0,
+ followers: 0,
+ }),
+ ).toStrictEqual({ level: "B", score: 100 });
+ });
+
+ it("average user gets A rank", () => {
+ expect(
+ calculateRank({
+ all_commits: false,
+ commits: 250,
+ prs: 50,
+ issues: 25,
+ repos: 0,
+ stars: 250,
+ followers: 25,
+ }),
+ ).toStrictEqual({ level: "A", score: 50 });
+ });
+
+ it("average user gets A rank (include_all_commits)", () => {
+ expect(
+ calculateRank({
+ all_commits: true,
+ commits: 1000,
+ prs: 50,
+ issues: 25,
+ repos: 0,
+ stars: 250,
+ followers: 25,
+ }),
+ ).toStrictEqual({ level: "A", score: 50 });
+ });
+
+ it("more than average user gets A+ rank", () => {
+ expect(
+ calculateRank({
+ all_commits: false,
+ commits: 500,
+ prs: 100,
+ issues: 50,
+ repos: 0,
+ stars: 500,
+ followers: 50,
+ }),
+ ).toStrictEqual({ level: "A+", score: 25 });
+ });
+
+ it("expert user gets S rank", () => {
+ expect(
+ calculateRank({
+ all_commits: false,
+ commits: 1000,
+ prs: 200,
+ issues: 100,
+ repos: 0,
+ stars: 1000,
followers: 100,
- contributions: 61,
- stargazers: 400,
- prs: 300,
- issues: 200,
}),
- ).toStrictEqual({ level: "A+", score: 49.25629684876535 });
+ ).toStrictEqual({ level: "S", score: 6.25 });
+ });
+
+ it("ezyang gets S+ rank", () => {
+ expect(
+ calculateRank({
+ all_commits: false,
+ commits: 1000,
+ prs: 4000,
+ issues: 2000,
+ repos: 0,
+ stars: 5000,
+ followers: 2000,
+ }),
+ ).toStrictEqual({ level: "S+", score: 1.1363983154296875 });
});
});
diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js
index 08523f3362e0e..3b27e8a6bc356 100644
--- a/tests/fetchStats.test.js
+++ b/tests/fetchStats.test.js
@@ -102,13 +102,13 @@ describe("Test fetchStats", () => {
it("should fetch correct stats", async () => {
let stats = await fetchStats("anuraghazra");
const rank = calculateRank({
- totalCommits: 100,
- totalRepos: 5,
- followers: 100,
- contributions: 61,
- stargazers: 300,
+ all_commits: false,
+ commits: 100,
prs: 300,
issues: 200,
+ repos: 5,
+ stars: 300,
+ followers: 100,
});
expect(stats).toStrictEqual({
@@ -132,13 +132,13 @@ describe("Test fetchStats", () => {
let stats = await fetchStats("anuraghazra");
const rank = calculateRank({
- totalCommits: 100,
- totalRepos: 5,
- followers: 100,
- contributions: 61,
- stargazers: 300,
+ all_commits: false,
+ commits: 100,
prs: 300,
issues: 200,
+ repos: 5,
+ stars: 300,
+ followers: 100,
});
expect(stats).toStrictEqual({
@@ -161,49 +161,26 @@ describe("Test fetchStats", () => {
);
});
- it("should fetch and add private contributions", async () => {
- let stats = await fetchStats("anuraghazra", true);
- const rank = calculateRank({
- totalCommits: 150,
- totalRepos: 5,
- followers: 100,
- contributions: 61,
- stargazers: 300,
- prs: 300,
- issues: 200,
- });
-
- expect(stats).toStrictEqual({
- contributedTo: 61,
- name: "Anurag Hazra",
- totalCommits: 150,
- totalIssues: 200,
- totalPRs: 300,
- totalStars: 300,
- rank,
- });
- });
-
it("should fetch total commits", async () => {
mock
.onGet("https://api.github.com/search/commits?q=author:anuraghazra")
.reply(200, { total_count: 1000 });
- let stats = await fetchStats("anuraghazra", true, true);
+ let stats = await fetchStats("anuraghazra", false, true);
const rank = calculateRank({
- totalCommits: 1050,
- totalRepos: 5,
- followers: 100,
- contributions: 61,
- stargazers: 300,
+ all_commits: true,
+ commits: 1000,
prs: 300,
issues: 200,
+ repos: 5,
+ stars: 300,
+ followers: 100,
});
expect(stats).toStrictEqual({
contributedTo: 61,
name: "Anurag Hazra",
- totalCommits: 1050,
+ totalCommits: 1000,
totalIssues: 200,
totalPRs: 300,
totalStars: 300,
@@ -216,21 +193,21 @@ describe("Test fetchStats", () => {
.onGet("https://api.github.com/search/commits?q=author:anuraghazra")
.reply(200, { total_count: 1000 });
- let stats = await fetchStats("anuraghazra", true, true, ["test-repo-1"]);
+ let stats = await fetchStats("anuraghazra", false, true, ["test-repo-1"]);
const rank = calculateRank({
- totalCommits: 1050,
- totalRepos: 5,
- followers: 100,
- contributions: 61,
- stargazers: 200,
+ all_commits: true,
+ commits: 1000,
prs: 300,
issues: 200,
+ repos: 5,
+ stars: 200,
+ followers: 100,
});
expect(stats).toStrictEqual({
contributedTo: 61,
name: "Anurag Hazra",
- totalCommits: 1050,
+ totalCommits: 1000,
totalIssues: 200,
totalPRs: 300,
totalStars: 200,
@@ -243,13 +220,13 @@ describe("Test fetchStats", () => {
let stats = await fetchStats("anuraghazra");
const rank = calculateRank({
- totalCommits: 100,
- totalRepos: 5,
- followers: 100,
- contributions: 61,
- stargazers: 400,
+ all_commits: false,
+ commits: 100,
prs: 300,
issues: 200,
+ repos: 5,
+ stars: 400,
+ followers: 100,
});
expect(stats).toStrictEqual({
@@ -268,13 +245,13 @@ describe("Test fetchStats", () => {
let stats = await fetchStats("anuraghazra");
const rank = calculateRank({
- totalCommits: 100,
- totalRepos: 5,
- followers: 100,
- contributions: 61,
- stargazers: 300,
+ all_commits: false,
+ commits: 100,
prs: 300,
issues: 200,
+ repos: 5,
+ stars: 300,
+ followers: 100,
});
expect(stats).toStrictEqual({
@@ -293,13 +270,13 @@ describe("Test fetchStats", () => {
let stats = await fetchStats("anuraghazra");
const rank = calculateRank({
- totalCommits: 100,
- totalRepos: 5,
- followers: 100,
- contributions: 61,
- stargazers: 300,
+ all_commits: false,
+ commits: 100,
prs: 300,
issues: 200,
+ repos: 5,
+ stars: 300,
+ followers: 100,
});
expect(stats).toStrictEqual({
From 73b0a91b7b07d10f8a28c569a10f80fc949114af Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 29 May 2023 09:43:37 +0300
Subject: [PATCH 228/905] Improve ukrainian translation of langcard.title
(#2756)
---
src/translations.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/translations.js b/src/translations.js
index 45c8295e024de..92a6fc5b90cb9 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -283,7 +283,7 @@ const langCardLocales = {
np: "अधिक प्रयोग गरिएको भाषाहरू",
el: "Οι περισσότερο χρησιμοποιούμενες γλώσσες",
ru: "Наиболее часто используемые языки",
- "uk-ua": "Найбільш часто використовувані мови",
+ "uk-ua": "Найчастіше використовувані мови",
id: "Bahasa Yang Paling Banyak Digunakan",
ml: "കൂടുതൽ ഉപയോഗിച്ച ഭാഷകൾ",
my: "Bahasa Paling Digunakan",
From 275c1fc1c7dbb78f0d4201a3034c18d62a04b5d7 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 29 May 2023 09:45:19 +0300
Subject: [PATCH 229/905] Show notice about no languages data instead of empty
card (#2755)
* Show message about no languages data instead of empty card
* dev
* dev
* dev
* dev
* dev
* dev
---
src/cards/top-languages-card.js | 51 ++++++++++++++++++++++++++-------
src/translations.js | 30 +++++++++++++++++++
2 files changed, 70 insertions(+), 11 deletions(-)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index c6cedb1fb077c..92f5b9d92d9e1 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -17,6 +17,7 @@ const MIN_CARD_WIDTH = 280;
const DEFAULT_LANGS_COUNT = 5;
const DEFAULT_LANG_COLOR = "#858585";
const CARD_PADDING = 25;
+const COMPACT_LAYOUT_BASE_HEIGHT = 90;
/**
* @typedef {import("../fetchers/types").Lang} Lang
@@ -101,7 +102,7 @@ const getCircleLength = (radius) => {
* @returns {number} Card height.
*/
const calculateCompactLayoutHeight = (totalLangs) => {
- return 90 + Math.round(totalLangs / 2) * 25;
+ return COMPACT_LAYOUT_BASE_HEIGHT + Math.round(totalLangs / 2) * 25;
};
/**
@@ -654,6 +655,19 @@ const renderDonutLayout = (langs, width, totalLanguageSize) => {
`;
};
+/**
+ * Creates the no coding activity SVG node.
+ *
+ * @param {{color: string, text: string, layout: import("./types").TopLangOptions["layout"]}} The function prop
+ */
+const noLanguagesDataNode = ({ color, text, layout }) => {
+ return `
+ ${text}
+ `;
+};
+
/**
* Renders card that display user's most frequently used programming languages.
*
@@ -699,8 +713,24 @@ const renderTopLanguages = (topLangs, options = {}) => {
: card_width;
let height = calculateNormalLayoutHeight(langs.length);
+ // returns theme based colors with proper overrides and defaults
+ const colors = getCardColors({
+ title_color,
+ text_color,
+ bg_color,
+ border_color,
+ theme,
+ });
+
let finalLayout = "";
- if (layout === "pie") {
+ if (langs.length === 0) {
+ height = COMPACT_LAYOUT_BASE_HEIGHT;
+ finalLayout = noLanguagesDataNode({
+ color: colors.textColor,
+ text: i18n.t("langcard.nodata"),
+ layout,
+ });
+ } else if (layout === "pie") {
height = calculatePieLayoutHeight(langs.length);
finalLayout = renderPieLayout(langs, totalLanguageSize);
} else if (layout === "donut-vertical") {
@@ -724,15 +754,6 @@ const renderTopLanguages = (topLangs, options = {}) => {
finalLayout = renderNormalLayout(langs, width, totalLanguageSize);
}
- // returns theme based colors with proper overrides and defaults
- const colors = getCardColors({
- title_color,
- text_color,
- bg_color,
- border_color,
- theme,
- });
-
const card = new Card({
customTitle: custom_title,
defaultTitle: i18n.t("langcard.title"),
@@ -764,6 +785,14 @@ const renderTopLanguages = (topLangs, options = {}) => {
width: 100%;
}
}
+ .stat {
+ font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${colors.textColor};
+ }
+ @supports(-moz-appearance: auto) {
+ /* Selector detects Firefox */
+ .stat { font-size:12px; }
+ }
+ .bold { font-weight: 700 }
.lang-name {
font: 400 11px "Segoe UI", Ubuntu, Sans-Serif;
fill: ${colors.textColor};
diff --git a/src/translations.js b/src/translations.js
index 92a6fc5b90cb9..51fc6aaa4cb92 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -293,6 +293,36 @@ const langCardLocales = {
vi: "Ngôn Ngữ Thường Sử Dụng",
se: "Mest använda språken",
},
+ "langcard.nodata": {
+ ar: "لا توجد بيانات لغات.",
+ cn: "沒有語言數據。",
+ "zh-tw": "沒有語言數據。",
+ cs: "Žádné jazykové údaje.",
+ de: "Keine Sprachdaten.",
+ bn: "কোন ভাষার ডেটা নেই।",
+ en: "No languages data.",
+ es: "Sin datos de idiomas.",
+ fr: "Aucune donnée sur les langues.",
+ hu: "Nincsenek nyelvi adatok.",
+ it: "Nessun dato sulle lingue.",
+ ja: "言語データがありません。",
+ kr: "언어 데이터가 없습니다.",
+ nl: "Ingen sprogdata.",
+ "pt-pt": "Sem dados de idiomas.",
+ "pt-br": "Sem dados de idiomas.",
+ np: "कुनै भाषा डाटा छैन।",
+ el: "Δεν υπάρχουν δεδομένα γλωσσών.",
+ ru: "Нет данных о языках.",
+ "uk-ua": "Немає даних про мови.",
+ id: "Tidak ada data bahasa.",
+ ml: "ഭാഷാ ഡാറ്റയില്ല.",
+ my: "Tiada data bahasa.",
+ sk: "Žiadne údaje o jazykoch.",
+ tr: "Dil verisi yok.",
+ pl: "Brak danych dotyczących języków.",
+ vi: "Không có dữ liệu ngôn ngữ.",
+ se: "Inga språkdata.",
+ },
};
const wakatimeCardLocales = {
From e0b3d833b04ae434a825d60a1f6f328bfdbdacdd Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 31 May 2023 13:24:11 +0200
Subject: [PATCH 230/905] refactor: update languages JSON (#2760)
Co-authored-by: rickstaa
---
src/common/languageColors.json | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/common/languageColors.json b/src/common/languageColors.json
index 3937eec5a2bf5..b670823cfd863 100644
--- a/src/common/languageColors.json
+++ b/src/common/languageColors.json
@@ -106,6 +106,7 @@
"Cypher": "#34c0eb",
"Cython": "#fedf5b",
"D": "#ba595e",
+ "D2": "#526ee8",
"DM": "#447265",
"Dafny": "#FFEC25",
"Darcs Patch": "#8eff23",
@@ -185,6 +186,7 @@
"Go": "#00ADD8",
"Go Checksums": "#00ADD8",
"Go Module": "#00ADD8",
+ "Go Workspace": "#00ADD8",
"Godot Resource": "#355570",
"Golo": "#88562A",
"Gosu": "#82937f",
@@ -284,6 +286,7 @@
"Lua": "#000080",
"MATLAB": "#e16737",
"MAXScript": "#00a6a6",
+ "MDX": "#fcb32c",
"MLIR": "#5EC8DB",
"MQL4": "#62A8D6",
"MQL5": "#4A76B8",
@@ -330,11 +333,12 @@
"Nu": "#c9df40",
"NumPy": "#9C8AF9",
"Nunjucks": "#3d8137",
+ "Nushell": "#4E9906",
"OASv2-json": "#85ea2d",
"OASv2-yaml": "#85ea2d",
"OASv3-json": "#85ea2d",
"OASv3-yaml": "#85ea2d",
- "OCaml": "#3be133",
+ "OCaml": "#ef7a08",
"ObjectScript": "#424893",
"Objective-C": "#438eff",
"Objective-C++": "#6866fb",
@@ -360,6 +364,7 @@
"PLSQL": "#dad8d8",
"PLpgSQL": "#336790",
"POV-Ray SDL": "#6bac65",
+ "Pact": "#F7A8B8",
"Pan": "#cc0000",
"Papyrus": "#6600cc",
"Parrot": "#f3ca0a",
@@ -398,6 +403,7 @@
"Quake": "#882233",
"R": "#198CE7",
"RAML": "#77d9fb",
+ "RBS": "#701516",
"RDoc": "#701516",
"REXX": "#d90e09",
"RMarkdown": "#198ce7",
@@ -472,6 +478,7 @@
"Swift": "#F05138",
"SystemVerilog": "#DAE1C2",
"TI Program": "#A0AA87",
+ "TL-Verilog": "#C40023",
"TLA": "#4b0079",
"TOML": "#9c4221",
"TSQL": "#e38c00",
@@ -512,6 +519,7 @@
"Vyper": "#2980b9",
"Web Ontology Language": "#5b70bd",
"WebAssembly": "#04133b",
+ "WebAssembly Interface Type": "#6250e7",
"Whiley": "#d5c397",
"Wikitext": "#fc5757",
"Windows Registry Entries": "#52d5ff",
From c301289f7deba0aa804da2e72e8b33029ffaa0b4 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Fri, 2 Jun 2023 11:07:59 +0200
Subject: [PATCH 231/905] fix: Make WakaTime card compatible with new API
(#2707)
* fix: Make WakaTime card compatible with new API
This commit makes sure that the WakaTime card works with the new
WakaTime API. See https://github.com/anuraghazra/github-readme-stats/issues/2698
for more information.
* fix: fix chinese simplified translations
* fix: improve WakaTime range order
* test: fix WakaTime tests
* refactor: remove WakaTime range loop
* refactor: remove redundant WakaTime call
* test: fix e2e tests
Co-authored-by: Hakula Chen
---------
Co-authored-by: Hakula Chen
---
api/wakatime.js | 3 +--
readme.md | 7 +++---
src/cards/wakatime-card.js | 25 ++++++++++++++++---
src/common/utils.js | 2 ++
src/fetchers/wakatime-fetcher.js | 16 ++++++------
src/translations.js | 16 ++++++++++++
.../renderWakatimeCard.test.js.snap | 4 +--
tests/e2e/e2e.test.js | 2 +-
tests/fetchWakatime.test.js | 2 +-
tests/renderWakatimeCard.test.js | 2 +-
10 files changed, 57 insertions(+), 22 deletions(-)
diff --git a/api/wakatime.js b/api/wakatime.js
index d439c5b7ac8c6..7ae93b5799321 100644
--- a/api/wakatime.js
+++ b/api/wakatime.js
@@ -28,7 +28,6 @@ export default async (req, res) => {
langs_count,
hide,
api_domain,
- range,
border_radius,
border_color,
} = req.query;
@@ -40,7 +39,7 @@ export default async (req, res) => {
}
try {
- const stats = await fetchWakatimeStats({ username, api_domain, range });
+ const stats = await fetchWakatimeStats({ username, api_domain });
let cacheSeconds = clampValue(
parseInt(cache_seconds || CONSTANTS.FOUR_HOURS, 10),
diff --git a/readme.md b/readme.md
index dc60369751a27..e7ef2b7096b5c 100644
--- a/readme.md
+++ b/readme.md
@@ -315,7 +315,6 @@ You can provide multiple comma-separated values in the bg_color option to render
- `layout` - Switch between two available layouts `default` & `compact`. Default `default`.
- `langs_count` - Limit the number of languages on the card, defaults to all reported languages _(number)_.
- `api_domain` - Set a custom API domain for the card, e.g. to use services like [Hakatime](https://github.com/mujx/hakatime) or [Wakapi](https://github.com/muety/wakapi) _(string)_. Default `Waka API`.
-- `range` – Request a range different from your WakaTime default, e.g. `last_7_days`. See [WakaTime API docs](https://wakatime.com/developers#stats) for a list of available options. _(YYYY-MM, last_7_days, last_30_days, last_6_months, last_year, or all_time)_. Default `all_time`.
* * *
@@ -468,15 +467,15 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
# Wakatime Week Stats
+> **Warning**
+> Please be aware that we currently only show data from Wakatime profiles that are public. You therefore have to make sure that **BOTH** `Display code time publicly` and `Display languages, editors, os, categories publicly` are enabled.
+
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
```md
[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
```
-> **Note**:
-> Please be aware that we currently only show data from Wakatime profiles that are public.
-
### Demo
[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index dacc4227dc2ad..9c17a4c063db7 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -279,7 +279,11 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
: noCodingActivityNode({
// @ts-ignore
color: textColor,
- text: i18n.t("wakatimecard.nocodingactivity"),
+ text: !stats.is_coding_activity_visible
+ ? i18n.t("wakatimecard.notpublic")
+ : stats.is_other_usage_visible
+ ? i18n.t("wakatimecard.nocodingactivity")
+ : i18n.t("wakatimecard.nocodedetails"),
})
}
`;
@@ -304,7 +308,11 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
noCodingActivityNode({
// @ts-ignore
color: textColor,
- text: i18n.t("wakatimecard.nocodingactivity"),
+ text: !stats.is_coding_activity_visible
+ ? i18n.t("wakatimecard.notpublic")
+ : stats.is_other_usage_visible
+ ? i18n.t("wakatimecard.nocodingactivity")
+ : i18n.t("wakatimecard.nocodedetails"),
}),
],
gap: lheight,
@@ -312,9 +320,20 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
}).join("");
}
+ // Get title range text
+ let titleText = i18n.t("wakatimecard.title");
+ switch (stats.range) {
+ case "last_7_days":
+ titleText += ` (${i18n.t("wakatimecard.last7days")})`;
+ break;
+ case "last_year":
+ titleText += ` (${i18n.t("wakatimecard.lastyear")})`;
+ break;
+ }
+
const card = new Card({
customTitle: custom_title,
- defaultTitle: i18n.t("wakatimecard.title"),
+ defaultTitle: titleText,
width: 495,
height,
border_radius,
diff --git a/src/common/utils.js b/src/common/utils.js
index 47e106140b6d0..d58203be69508 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -305,6 +305,7 @@ const SECONDARY_ERROR_MESSAGES = {
"Please add an env variable called PAT_1 with your github token in vercel",
USER_NOT_FOUND: "Make sure the provided username is not an organization",
GRAPHQL_ERROR: "Please try again later",
+ WAKATIME_USER_NOT_FOUND: "Make sure you have a public WakaTime profile",
};
/**
@@ -324,6 +325,7 @@ class CustomError extends Error {
static MAX_RETRY = "MAX_RETRY";
static USER_NOT_FOUND = "USER_NOT_FOUND";
static GRAPHQL_ERROR = "GRAPHQL_ERROR";
+ static WAKATIME_ERROR = "WAKATIME_ERROR";
}
/**
diff --git a/src/fetchers/wakatime-fetcher.js b/src/fetchers/wakatime-fetcher.js
index 2af8fa9998fb1..4578b9eb0ddda 100644
--- a/src/fetchers/wakatime-fetcher.js
+++ b/src/fetchers/wakatime-fetcher.js
@@ -1,29 +1,29 @@
import axios from "axios";
-import { MissingParamError } from "../common/utils.js";
+import { CustomError, MissingParamError } from "../common/utils.js";
+import { I18n } from "../common/I18n.js";
/**
* WakaTime data fetcher.
*
- * @param {{username: string, api_domain: string, range: string}} props Fetcher props.
+ * @param {{username: string, api_domain: string }} props Fetcher props.
* @returns {Promise} WakaTime data response.
*/
-const fetchWakatimeStats = async ({ username, api_domain, range }) => {
+const fetchWakatimeStats = async ({ username, api_domain }) => {
if (!username) throw new MissingParamError(["username"]);
try {
const { data } = await axios.get(
`https://${
api_domain ? api_domain.replace(/\/$/gi, "") : "wakatime.com"
- }/api/v1/users/${username}/stats/${
- range || "all_time"
- }?is_including_today=true`,
+ }/api/v1/users/${username}/stats?is_including_today=true`,
);
return data.data;
} catch (err) {
if (err.response.status < 200 || err.response.status > 299) {
- throw new Error(
- "Wakatime user not found, make sure you have a wakatime profile",
+ throw new CustomError(
+ `Could not resolve to a User with the login of '${username}'`,
+ "WAKATIME_USER_NOT_FOUND",
);
}
throw err;
diff --git a/src/translations.js b/src/translations.js
index 51fc6aaa4cb92..c123eb346f0bd 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -356,6 +356,22 @@ const wakatimeCardLocales = {
vi: "Thống Kê Wakatime",
se: "Wakatime statistik",
},
+ "wakatimecard.lastyear": {
+ en: "last year",
+ cn: "去年",
+ },
+ "wakatimecard.last7days": {
+ en: "last 7 days",
+ cn: "最近 7 天",
+ },
+ "wakatimecard.notpublic": {
+ en: "Wakatime user profile not public",
+ cn: "Wakatime 用户个人资料未公开",
+ },
+ "wakatimecard.nocodedetails": {
+ en: "User doesn't publicly share detailed code statistics",
+ cn: "用户不公开分享详细的代码统计信息",
+ },
"wakatimecard.nocodingactivity": {
ar: "لا يوجد نشاط برمجي لهذا الأسبوع",
cn: "本周没有编程活动",
diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap
index 6dfaf98e9742a..055c0f6642a7a 100644
--- a/tests/__snapshots__/renderWakatimeCard.test.js.snap
+++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap
@@ -123,7 +123,7 @@ exports[`Test Render Wakatime Card should render correctly with compact layout 1
y="0"
class="header"
data-testid="header"
- >Wakatime Stats
+ >Wakatime Stats (last 7 days)
From 9105c74af44383e29793800fc0db98a44396691c Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sun, 11 Jun 2023 02:39:33 +0200
Subject: [PATCH 262/905] docs: add PAT permission to docs (#2805)
This commit changes the README so that users are aware that they also
need to set the `user` permission when creating the PAT when they want
their private commits to show up.
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index abd9e8fece8cf..0387a2339c851 100644
--- a/readme.md
+++ b/readme.md
@@ -624,7 +624,7 @@ Since the GitHub API only allows 5k requests per hour, my `https://github-readme
![](https://files.catbox.moe/3n76fh.png)
8. Click the `Continue with GitHub` button, search for the required Git Repository and import it by clicking the `Import` button. Alternatively, you can import a Third-Party Git Repository using the `Import Third-Party Git Repository ->` link at the bottom of the page.
![](https://files.catbox.moe/mg5p04.png)
-9. Create a personal access token (PAT) [here](https://github.com/settings/tokens/new) and enable the `repo` permissions (this allows access to see private repo stats).
+9. Create a personal access token (PAT) [here](https://github.com/settings/tokens/new) and enable the `repo` and `user` permissions (this allows access to see private repo and user stats).
10. Add the PAT as an environment variable named `PAT_1` (as shown).
![](https://files.catbox.moe/0yclio.png)
11. Click deploy, and you're good to go. See your domains to use the API!
From 9520baac1fe61292a52ff51abada66bcdc7cd4f1 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sun, 11 Jun 2023 13:10:04 +0300
Subject: [PATCH 263/905] Docs: rename wakatime stats card section (#2807)
---
readme.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/readme.md b/readme.md
index 0387a2339c851..bc517684f5d9e 100644
--- a/readme.md
+++ b/readme.md
@@ -106,7 +106,7 @@ Please visit [this link](https://give.do/fundraisers/stand-beside-the-victims-of
- [Pie Chart Language Card Layout](#pie-chart-language-card-layout)
- [Hide Progress Bars](#hide-progress-bars)
- [Demo](#demo-1)
-- [Wakatime Week Stats](#wakatime-week-stats)
+- [Wakatime Stats Card](#wakatime-stats-card)
- [Demo](#demo-2)
- [All Demos](#all-demos)
- [Quick Tip (Align The Repo Cards)](#quick-tip-align-the-repo-cards)
@@ -499,7 +499,7 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide_progress=true)
-# Wakatime Week Stats
+# Wakatime Stats Card
> **Warning**
> Please be aware that we currently only show data from Wakatime profiles that are public. You therefore have to make sure that **BOTH** `Display code time publicly` and `Display languages, editors, os, categories publicly` are enabled.
From dc60ea9b30143c066c51843b57e6dff7f1fb2cf3 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sun, 11 Jun 2023 13:11:17 +0300
Subject: [PATCH 264/905] Docs: set correct separation symbol between
translations links (#2806)
---
readme.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/readme.md b/readme.md
index bc517684f5d9e..df8d768d18472 100644
--- a/readme.md
+++ b/readme.md
@@ -56,11 +56,11 @@
Italiano
·
한국어
- .
+ ·
Nederlands
- .
+ ·
नेपाली
- .
+ ·
Türkçe
From 041ef07ea46a99a90e8f1ff31fd382b8e5359156 Mon Sep 17 00:00:00 2001
From: Anirban Das <72315775+anirban12d@users.noreply.github.com>
Date: Sun, 11 Jun 2023 16:04:54 +0530
Subject: [PATCH 265/905] Added neon theme (#2579)
Added neon themes with bright colors that goes well with dark backgrounds.
---
themes/index.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/themes/index.js b/themes/index.js
index ab8eab6a0d0e9..aa7a24c23b216 100644
--- a/themes/index.js
+++ b/themes/index.js
@@ -423,6 +423,13 @@ export const themes = {
border_color: "85A4C0",
bg_color: "030314",
},
+ neon: {
+ title_color: "00EAD3",
+ text_color: "FF449F",
+ icon_color: "00EAD3",
+ border_color: "ffffff",
+ bg_color: "000000",
+ },
};
export default themes;
From 2704e25d5d9a3914befe50c32e7a8fce22a48e36 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sun, 11 Jun 2023 15:30:04 +0300
Subject: [PATCH 266/905] Add yzhang.markdown-all-in-one to recommended
workspace extensions (#2809)
* Add yzhang.markdown-all-in-one to recommended workspace extensions
* refactor: update .gitignore
---------
Co-authored-by: rickstaa
---
.gitignore | 7 ++++---
.vscode/extensions.json | 5 +++++
2 files changed, 9 insertions(+), 3 deletions(-)
create mode 100644 .vscode/extensions.json
diff --git a/.gitignore b/.gitignore
index 25017502d486a..d90afc81611cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,7 +8,8 @@ coverage
vercel_token
# IDE
-.vscode
+.vscode/*
+!.vscode/extensions.json
*.code-workspace
-
-.vercel
+
+.vercel
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000000000..408cb64f1d45b
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,5 @@
+{
+ "recommendations": [
+ "yzhang.markdown-all-in-one"
+ ]
+}
From 92a9d85c4a60d9c4e1f7543b430ce449df4176ad Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Sun, 11 Jun 2023 14:34:34 +0200
Subject: [PATCH 267/905] docs(theme): Auto update theme readme (#2810)
Co-authored-by: GitHub Readme Stats Bot
---
themes/README.md | 46 ++++++++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 12 deletions(-)
diff --git a/themes/README.md b/themes/README.md
index 5993b6a07a9b8..edd0788394f53 100644
--- a/themes/README.md
+++ b/themes/README.md
@@ -16,7 +16,8 @@ Use `?theme=THEME_NAME` parameter like so :-
| | | |
| :--: | :--: | :--: |
-| `default` ![default][default] | `transparent` ![transparent][transparent] | `dark` ![dark][dark] |
+| `default` ![default][default] | `transparent` ![transparent][transparent] | `shadow_red` ![shadow_red][shadow_red] |
+| `shadow_green` ![shadow_green][shadow_green] | `shadow_blue` ![shadow_blue][shadow_blue] | `dark` ![dark][dark] |
| `radical` ![radical][radical] | `merko` ![merko][merko] | `gruvbox` ![gruvbox][gruvbox] |
| `gruvbox_light` ![gruvbox_light][gruvbox_light] | `tokyonight` ![tokyonight][tokyonight] | `onedark` ![onedark][onedark] |
| `cobalt` ![cobalt][cobalt] | `synthwave` ![synthwave][synthwave] | `highcontrast` ![highcontrast][highcontrast] |
@@ -33,10 +34,11 @@ Use `?theme=THEME_NAME` parameter like so :-
| `blueberry` ![blueberry][blueberry] | `slateorange` ![slateorange][slateorange] | `kacho_ga` ![kacho_ga][kacho_ga] |
| `outrun` ![outrun][outrun] | `ocean_dark` ![ocean_dark][ocean_dark] | `city_lights` ![city_lights][city_lights] |
| `github_dark` ![github_dark][github_dark] | `github_dark_dimmed` ![github_dark_dimmed][github_dark_dimmed] | `discord_old_blurple` ![discord_old_blurple][discord_old_blurple] |
-| `panda` ![panda][panda] | `noctis_minimus` ![noctis_minimus][noctis_minimus] | `cobalt2` ![cobalt2][cobalt2] |
-| `swift` ![swift][swift] | `aura` ![aura][aura] | `apprentice` ![apprentice][apprentice] |
-| `moltack` ![moltack][moltack] | `codeSTACKr` ![codeSTACKr][codeSTACKr] | `rose_pine` ![rose_pine][rose_pine] |
-| `aura_dark` ![aura_dark][aura_dark] | | |
+| `aura_dark` ![aura_dark][aura_dark] | `panda` ![panda][panda] | `noctis_minimus` ![noctis_minimus][noctis_minimus] |
+| `cobalt2` ![cobalt2][cobalt2] | `swift` ![swift][swift] | `aura` ![aura][aura] |
+| `apprentice` ![apprentice][apprentice] | `moltack` ![moltack][moltack] | `codeSTACKr` ![codeSTACKr][codeSTACKr] |
+| `rose_pine` ![rose_pine][rose_pine] | `date_night` ![date_night][date_night] | `one_dark_pro` ![one_dark_pro][one_dark_pro] |
+| `rose` ![rose][rose] | `holi` ![holi][holi] | `neon` ![neon][neon] |
| [Add your theme][add-theme] | | |
## Repo Card
@@ -45,7 +47,8 @@ Use `?theme=THEME_NAME` parameter like so :-
| | | |
| :--: | :--: | :--: |
-| `default_repocard` ![default_repocard][default_repocard_repo] | `transparent` ![transparent][transparent_repo] | `dark` ![dark][dark_repo] |
+| `default_repocard` ![default_repocard][default_repocard_repo] | `transparent` ![transparent][transparent_repo] | `shadow_red` ![shadow_red][shadow_red_repo] |
+| `shadow_green` ![shadow_green][shadow_green_repo] | `shadow_blue` ![shadow_blue][shadow_blue_repo] | `dark` ![dark][dark_repo] |
| `radical` ![radical][radical_repo] | `merko` ![merko][merko_repo] | `gruvbox` ![gruvbox][gruvbox_repo] |
| `gruvbox_light` ![gruvbox_light][gruvbox_light_repo] | `tokyonight` ![tokyonight][tokyonight_repo] | `onedark` ![onedark][onedark_repo] |
| `cobalt` ![cobalt][cobalt_repo] | `synthwave` ![synthwave][synthwave_repo] | `highcontrast` ![highcontrast][highcontrast_repo] |
@@ -62,16 +65,20 @@ Use `?theme=THEME_NAME` parameter like so :-
| `blueberry` ![blueberry][blueberry_repo] | `slateorange` ![slateorange][slateorange_repo] | `kacho_ga` ![kacho_ga][kacho_ga_repo] |
| `outrun` ![outrun][outrun_repo] | `ocean_dark` ![ocean_dark][ocean_dark_repo] | `city_lights` ![city_lights][city_lights_repo] |
| `github_dark` ![github_dark][github_dark_repo] | `github_dark_dimmed` ![github_dark_dimmed][github_dark_dimmed_repo] | `discord_old_blurple` ![discord_old_blurple][discord_old_blurple_repo] |
-| `panda` ![panda][panda_repo] | `noctis_minimus` ![noctis_minimus][noctis_minimus_repo] | `cobalt2` ![cobalt2][cobalt2_repo] |
-| `swift` ![swift][swift_repo] | `aura` ![aura][aura_repo] | `apprentice` ![apprentice][apprentice_repo] |
-| `moltack` ![moltack][moltack_repo] | `codeSTACKr` ![codeSTACKr][codeSTACKr_repo] | `rose_pine` ![rose_pine][rose_pine_repo] |
-| `aura_dark` ![aura_dark][aura_dark_repo] | | |
+| `aura_dark` ![aura_dark][aura_dark_repo] | `panda` ![panda][panda_repo] | `noctis_minimus` ![noctis_minimus][noctis_minimus_repo] |
+| `cobalt2` ![cobalt2][cobalt2_repo] | `swift` ![swift][swift_repo] | `aura` ![aura][aura_repo] |
+| `apprentice` ![apprentice][apprentice_repo] | `moltack` ![moltack][moltack_repo] | `codeSTACKr` ![codeSTACKr][codeSTACKr_repo] |
+| `rose_pine` ![rose_pine][rose_pine_repo] | `date_night` ![date_night][date_night_repo] | `one_dark_pro` ![one_dark_pro][one_dark_pro_repo] |
+| `rose` ![rose][rose_repo] | `holi` ![holi][holi_repo] | `neon` ![neon][neon_repo] |
| [Add your theme][add-theme] | | |
[default]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=default
[default_repocard]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=default_repocard
[transparent]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=transparent
+[shadow_red]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=shadow_red
+[shadow_green]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=shadow_green
+[shadow_blue]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=shadow_blue
[dark]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=dark
[radical]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=radical
[merko]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=merko
@@ -121,6 +128,7 @@ Use `?theme=THEME_NAME` parameter like so :-
[github_dark]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=github_dark
[github_dark_dimmed]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=github_dark_dimmed
[discord_old_blurple]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=discord_old_blurple
+[aura_dark]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=aura_dark
[panda]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=panda
[noctis_minimus]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=noctis_minimus
[cobalt2]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=cobalt2
@@ -130,11 +138,19 @@ Use `?theme=THEME_NAME` parameter like so :-
[moltack]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=moltack
[codeSTACKr]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=codeSTACKr
[rose_pine]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=rose_pine
-[aura_dark]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=aura_dark
+[date_night]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=date_night
+[one_dark_pro]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=one_dark_pro
+[rose]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=rose
+[holi]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=holi
+[neon]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=neon
+
[default_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=default
[default_repocard_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=default_repocard
[transparent_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=transparent
+[shadow_red_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=shadow_red
+[shadow_green_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=shadow_green
+[shadow_blue_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=shadow_blue
[dark_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=dark
[radical_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=radical
[merko_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=merko
@@ -184,6 +200,7 @@ Use `?theme=THEME_NAME` parameter like so :-
[github_dark_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=github_dark
[github_dark_dimmed_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=github_dark_dimmed
[discord_old_blurple_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=discord_old_blurple
+[aura_dark_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=aura_dark
[panda_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=panda
[noctis_minimus_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=noctis_minimus
[cobalt2_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=cobalt2
@@ -193,7 +210,12 @@ Use `?theme=THEME_NAME` parameter like so :-
[moltack_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=moltack
[codeSTACKr_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=codeSTACKr
[rose_pine_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=rose_pine
-[aura_dark_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=aura_dark
+[date_night_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=date_night
+[one_dark_pro_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=one_dark_pro
+[rose_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=rose
+[holi_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=holi
+[neon_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=neon
+
[add-theme]: https://github.com/anuraghazra/github-readme-stats/edit/master/themes/index.js
From faf0c25b90cf3b7b2f8ce0ec4ed0a73b28cf7bfa Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sun, 11 Jun 2023 16:21:58 +0300
Subject: [PATCH 268/905] Update automated themes preview workflow
contributions guideline (#2808)
* Update automated themes preview workflow contributions guideline
* docs: link to top-issues dashboard
---------
Co-authored-by: rickstaa
---
CONTRIBUTING.md | 2 +-
scripts/preview-theme.js | 5 ++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4873bdbcf5f69..e2091c0baf850 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -53,7 +53,7 @@ All you need to do is edit the [themes/index.js](./themes/index.js) file and add
> If you are contributing your theme just because you are using it personally, then you can [customize the looks](./readme.md#customization) of your card with URL params instead.
> **Note**
-> Keep in mind that we already have a wide collection of different themes, in order not to inflate their number, we began to add only themes that were supported by the community. It means that your pull request with theme addition will not be merged until we get enough positive feedback from the community in the form of comments, thumb up and heart emojis. Remember that you are also able to support themes of other contributors that you liked to speed up their merge.
+> Keep in mind that we already have a vast collection of different themes. To keep their number manageable, we began to add only themes supported by the community. Your pull request with theme addition will be merged once we get enough positive feedback from the community in the form of thumbs up (see [#1935](https://github.com/anuraghazra/github-readme-stats/issues/1935#top-themes-prs). Remember that you can also support themes of other contributors that you liked to speed up their merge.
## Any contributions you make will be under the MIT Software License
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index 57b792a369c95..44a05d77f62e4 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -28,8 +28,11 @@ const FAIL_TEXT = `
`;
const THEME_CONTRIB_GUIDELINES = `
\rHi, thanks for the theme contribution. Please read our theme [contribution guidelines](https://github.com/anuraghazra/github-readme-stats/blob/master/CONTRIBUTING.md#themes-contribution).
- \rWe are currently only accepting color combinations from any VSCode theme or themes with good color combinations to minimize bloating the themes collection.
+ \r> **Warning**
+ \r> Keep in mind that we already have a vast collection of different themes. To keep their number manageable, we began to add only themes supported by the community. Your pull request with theme addition will be merged once we get enough positive feedback from the community in the form of thumbs up (see [#1935](https://github.com/anuraghazra/github-readme-stats/issues/1935#top-themes-prs). Remember that you can also support themes of other contributors that you liked to speed up their merge.
+
+ \r> **Note**
\r> Also, note that if this theme is exclusively for your personal use, then instead of adding it to our theme collection, you can use card [customization options](https://github.com/anuraghazra/github-readme-stats#customization).
`;
const COLOR_PROPS = {
From a9675816036142fb7e2744578adbada0b3c06983 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 12 Jun 2023 09:28:16 +0300
Subject: [PATCH 269/905] Docs (translations): Regenerated tables of contents
using yzhang.markdown-all-in-one extension (#2811)
---
docs/readme_cn.md | 26 +++++++++++++++++++-------
docs/readme_de.md | 22 +++++++++++++++++-----
docs/readme_es.md | 27 +++++++++++++++++++++------
docs/readme_fr.md | 23 +++++++++++++++++------
docs/readme_it.md | 29 +++++++++++++++++++++--------
docs/readme_ja.md | 20 ++++++++++++++++----
docs/readme_kr.md | 23 +++++++++++++++++++----
docs/readme_nl.md | 25 ++++++++++++++++++++-----
docs/readme_np.md | 25 ++++++++++++++++++++-----
docs/readme_pt-BR.md | 21 +++++++++++++++++----
docs/readme_tr.md | 29 ++++++++++++++++++++++-------
11 files changed, 209 insertions(+), 61 deletions(-)
diff --git a/docs/readme_cn.md b/docs/readme_cn.md
index 8fda35b348140..8990006b6a308 100644
--- a/docs/readme_cn.md
+++ b/docs/readme_cn.md
@@ -59,14 +59,26 @@
Gostou do projeto? Por favor considere fazer uma doação para ajudar a melhorá-lo!
-# Características
+# Características
- [Cartão de estatísticas do GitHub](#cartão-de-estatísticas-do-github)
+ - [Ocultando estatísticas específicas](#ocultando-estatísticas-específicas)
+ - [Adicionando contagem de contribuições privadas à contagem total de commits](#adicionando-contagem-de-contribuições-privadas-à-contagem-total-de-commits)
+ - [Exibindo ícones](#exibindo-ícones)
+ - [Temas](#temas)
+ - [Personalização](#personalização)
- [Pins extras do GitHub](#pins-extras-do-github)
+ - [Utilização](#utilização)
+ - [Demonstração](#demonstração)
- [Cartão de principais linguagens de programação](#cartão-de-principais-linguagens-de-programação)
+ - [Utilização](#utilização-1)
+ - [Ocultar linguagens individualmente](#ocultar-linguagens-individualmente)
+ - [Layout de cartão de linguagens compacto](#layout-de-cartão-de-linguagens-compacto)
+ - [Demonstração](#demonstração-1)
- [Estatística semanal Wakatime](#estatística-semanal-wakatime)
-- [Temas](#temas)
-- [Personalização](#personalização)
-- [Faça suas próprias implantações](#implante-em-sua-própria-instância-do-vercel)
+ - [Demonstração](#demonstração-2)
+ - [Todas as demonstrações](#todas-as-demonstrações)
+ - [Dica (Alinhandos os cartões de repositório)](#dica-alinhandos-os-cartões-de-repositório)
+ - [Implante em sua própria instância do Vercel](#implante-em-sua-própria-instância-do-vercel)
+ - [:sparkling\_heart: Apoie o projeto](#sparkling_heart-apoie-o-projeto)
# Cartão de estatísticas do GitHub
diff --git a/docs/readme_tr.md b/docs/readme_tr.md
index 9ee358b97bdec..b875c5e911968 100644
--- a/docs/readme_tr.md
+++ b/docs/readme_tr.md
@@ -59,15 +59,30 @@
Projeyi sevdiniz mi? Daha da gelişmesi için lütfen bağış yapın!
-# Features
-
-- [GitHub İstatistikler Kartı](#github-istatistikler-kartı)
+# Features
+
+- [GitHub İstatistikler Kartı](#github-i̇statistikler-kartı)
+ - [Bazı İstatitistikleri Gizleme](#bazı-i̇statitistikleri-gizleme)
+ - [Özel Katkı Sayısını Toplam Commit Sayısına Ekleme](#özel-katkı-sayısını-toplam-commit-sayısına-ekleme)
+ - [İkonları Göstermek](#i̇konları-göstermek)
+ - [Temalar](#temalar)
+ - [Özelleştirmeler](#özelleştirmeler)
- [GitHub Ekstra Pinler](#github-ekstra-pinler)
+ - [Kullanım](#kullanım)
+ - [Demo](#demo)
- [En Çok Kullanılan Diller](#en-çok-kullanılan-diller)
-- [Wakatime Haftalık İstatistikler](#wakatime-haftalık-istatistikler)
-- [Temalar](#temalar)
-- [Özelleştirmeler](#özelleştirmeler)
-- [Yayınlayın](#yayınlayın)
+ - [Kullanım](#kullanım-1)
+ - [Belirli Repoları Çıkartın](#belirli-repoları-çıkartın)
+ - [Belirli Dilleri Çıkartın](#belirli-dilleri-çıkartın)
+ - [Daha Fazla Dil Gösterin](#daha-fazla-dil-gösterin)
+ - [Kompakt Dil Kartı Düzeni](#kompakt-dil-kartı-düzeni)
+ - [Demo](#demo-1)
+- [Wakatime Haftalık İstatistikler](#wakatime-haftalık-i̇statistikler)
+ - [Demo](#demo-2)
+ - [Tüm Demolar](#tüm-demolar)
+ - [Hızlı İpucu (Repo Kartları Hizlayın)](#hızlı-i̇pucu-repo-kartları-hizlayın)
+ - [Kendi Vercel Örneğinizde Yayınlayın](#kendi-vercel-örneğinizde-yayınlayın)
+ - [:sparkling\_heart: Projeyi Destekleyin](#sparkling_heart-projeyi-destekleyin)
# GitHub İstatistikler Kartı
From 5218e3408452a963b14ad1158b515bf916c035d4 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 12 Jun 2023 09:29:46 +0300
Subject: [PATCH 270/905] Remove duplicate from .gitignore (#2814)
---
.gitignore | 1 -
1 file changed, 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index d90afc81611cf..5ff51c0b039ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,6 @@
.env
node_modules
*.lock
-.vscode/
.idea/
coverage
vercel_token
From 99d560f57326ec707d9e2726d9d86f69d4cf9a3d Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 12 Jun 2023 10:08:24 +0300
Subject: [PATCH 271/905] Add vscode settings for yzhang.markdown-all-in-one
extension (#2813)
---
.gitignore | 1 +
.vscode/settings.json | 4 ++++
2 files changed, 5 insertions(+)
create mode 100644 .vscode/settings.json
diff --git a/.gitignore b/.gitignore
index 5ff51c0b039ea..80db7787ddad5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ vercel_token
# IDE
.vscode/*
!.vscode/extensions.json
+!.vscode/settings.json
*.code-workspace
.vercel
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000000..b0ca284c85226
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,4 @@
+{
+ "markdown.extension.toc.levels": "1..3",
+ "editor.formatOnSave": true
+}
From 768721f32541c1b586fd14d469550d187b813cdf Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 12 Jun 2023 10:08:49 +0300
Subject: [PATCH 272/905] Improve pull requests labeler (#2812)
---
.github/labeler.yml | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/.github/labeler.yml b/.github/labeler.yml
index fad3eeeb8d101..ad3ba92fa4889 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -2,3 +2,26 @@ themes: themes/index.js
doc-translation: docs/*
card-i18n: src/translations.js
documentation: readme.md
+dependencies:
+ - package.json
+ - package-lock.json
+lang-card:
+ - api/top-langs.js
+ - src/cards/top-languages-card.js
+ - src/fetchers/top-languages-fetcher.js
+repo-card:
+ - api/pin.js
+ - src/cards/repo-card.js
+ - src/fetchers/repo-fetcher.js
+stats-card:
+ - api/index.js
+ - src/cards/stats-card.js
+ - src/fetchers/stats-fetcher.js
+wakatime-card:
+ - api/wakatime.js
+ - src/cards/wakatime-card.js
+ - src/fetchers/wakatime-fetcher.js
+ranks: src/calculateRank.js
+ci:
+ - .github/workflows/*
+ - scripts/*
From 66e54926543be6343cc875d7504896a9ef37c0c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Rozet?=
Date: Mon, 12 Jun 2023 14:38:07 +0200
Subject: [PATCH 273/905] Add finer ranking levels (#2762)
* Add finer ranking levels
* Update rank description
---
readme.md | 2 +-
src/calculateRank.js | 54 ++++++++++++++---------------
src/cards/stats-card.js | 5 ++-
src/fetchers/stats-fetcher.js | 2 +-
src/fetchers/types.d.ts | 2 +-
tests/calculateRank.test.js | 64 +++++++++++++++++++++--------------
6 files changed, 69 insertions(+), 60 deletions(-)
diff --git a/readme.md b/readme.md
index df8d768d18472..2bc0863ae7074 100644
--- a/readme.md
+++ b/readme.md
@@ -137,7 +137,7 @@ Change the `?username=` value to your GitHub username.
> By default, the stats card only shows statistics like stars, commits and pull requests from public repositories. To show private statistics on the stats card, you should [deploy your own instance](#deploy-on-your-own) using your own GitHub API token.
> **Note**
-> Available ranks are S+ (top 1%), S (top 25%), A++ (top 45%), A+ (top 60%), and B+ (everyone). The values are calculated by using the [cumulative distribution function](https://en.wikipedia.org/wiki/Cumulative_distribution_function) using commits, contributions, issues, stars, pull requests, followers, and owned repositories. The implementation can be investigated at [src/calculateRank.js](./src/calculateRank.js).
+> Available ranks are S (top 1%), A+ (12.5%), A (25%), A- (37.5%), B+ (50%), B (62.5%), B- (75%), C+ (87.5%) and C (everyone). This ranking scheme is based on the [Japanese academic grading](https://wikipedia.org/wiki/Academic_grading_in_Japan) system. The global percentile is calculated as a weighted sum of percentiles for each statistic (number of commits, pull requests, issues, stars and followers), based on the cumulative distribution function of the [exponential](https://wikipedia.org/wiki/exponential_distribution) and the [log-normal](https://wikipedia.org/wiki/Log-normal_distribution) distributions. The implementation can be investigated at [src/calculateRank.js](./src/calculateRank.js). The circle around the rank shows 100 minus the global percentile.
### Hiding individual stats
diff --git a/src/calculateRank.js b/src/calculateRank.js
index 7648ad412ed67..c4583da0e804f 100644
--- a/src/calculateRank.js
+++ b/src/calculateRank.js
@@ -1,5 +1,10 @@
-function expsf(x, lambda = 1) {
- return 2 ** (-lambda * x);
+function exponential_cdf(x) {
+ return 1 - 2 ** -x;
+}
+
+function log_normal_cdf(x) {
+ // approximation
+ return x / (1 + x);
}
/**
@@ -13,7 +18,7 @@ function expsf(x, lambda = 1) {
* @param {number} params.repos Total number of repos.
* @param {number} params.stars The number of stars.
* @param {number} params.followers The number of followers.
- * @returns {{level: string, score: number}}} The users rank.
+ * @returns {{level: string, percentile: number}}} The users rank.
*/
function calculateRank({
all_commits,
@@ -24,15 +29,15 @@ function calculateRank({
stars,
followers,
}) {
- const COMMITS_MEAN = all_commits ? 1000 : 250,
+ const COMMITS_MEDIAN = all_commits ? 1000 : 250,
COMMITS_WEIGHT = 2;
- const PRS_MEAN = 50,
+ const PRS_MEDIAN = 50,
PRS_WEIGHT = 3;
- const ISSUES_MEAN = 25,
+ const ISSUES_MEDIAN = 25,
ISSUES_WEIGHT = 1;
- const STARS_MEAN = 250,
+ const STARS_MEDIAN = 50,
STARS_WEIGHT = 4;
- const FOLLOWERS_MEAN = 25,
+ const FOLLOWERS_MEDIAN = 10,
FOLLOWERS_WEIGHT = 1;
const TOTAL_WEIGHT =
@@ -42,30 +47,21 @@ function calculateRank({
STARS_WEIGHT +
FOLLOWERS_WEIGHT;
- const rank =
- (COMMITS_WEIGHT * expsf(commits, 1 / COMMITS_MEAN) +
- PRS_WEIGHT * expsf(prs, 1 / PRS_MEAN) +
- ISSUES_WEIGHT * expsf(issues, 1 / ISSUES_MEAN) +
- STARS_WEIGHT * expsf(stars, 1 / STARS_MEAN) +
- FOLLOWERS_WEIGHT * expsf(followers, 1 / FOLLOWERS_MEAN)) /
- TOTAL_WEIGHT;
+ const THRESHOLDS = [1, 12.5, 25, 37.5, 50, 62.5, 75, 87.5, 100];
+ const LEVELS = ["S", "A+", "A", "A-", "B+", "B", "B-", "C+", "C"];
- const RANK_S_PLUS = 0.025;
- const RANK_S = 0.1;
- const RANK_A_PLUS = 0.25;
- const RANK_A = 0.5;
- const RANK_B_PLUS = 0.75;
+ const rank =
+ 1 -
+ (COMMITS_WEIGHT * exponential_cdf(commits / COMMITS_MEDIAN) +
+ PRS_WEIGHT * exponential_cdf(prs / PRS_MEDIAN) +
+ ISSUES_WEIGHT * exponential_cdf(issues / ISSUES_MEDIAN) +
+ STARS_WEIGHT * log_normal_cdf(stars / STARS_MEDIAN) +
+ FOLLOWERS_WEIGHT * log_normal_cdf(followers / FOLLOWERS_MEDIAN)) /
+ TOTAL_WEIGHT;
- const level = (() => {
- if (rank <= RANK_S_PLUS) return "S+";
- if (rank <= RANK_S) return "S";
- if (rank <= RANK_A_PLUS) return "A+";
- if (rank <= RANK_A) return "A";
- if (rank <= RANK_B_PLUS) return "B+";
- return "B";
- })();
+ const level = LEVELS[THRESHOLDS.findIndex((t) => rank * 100 <= t)];
- return { level, score: rank * 100 };
+ return { level: level, percentile: rank * 100 };
}
export { calculateRank };
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index bf0c2c8c50785..c483cdd8f56d2 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -209,9 +209,8 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
hide_rank ? 0 : 150,
);
- // the better user's score the the rank will be closer to zero so
- // subtracting 100 to get the progress in 100%
- const progress = 100 - rank.score;
+ // the lower the user's percentile the better
+ const progress = 100 - rank.percentile;
const cssStyles = getStyles({
titleColor,
ringColor,
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index bad5fe22ef278..cebc38e8f53db 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -189,7 +189,7 @@ const fetchStats = async (
totalIssues: 0,
totalStars: 0,
contributedTo: 0,
- rank: { level: "B", score: 0 },
+ rank: { level: "C", percentile: 100 },
};
let res = await statsFetcher(username);
diff --git a/src/fetchers/types.d.ts b/src/fetchers/types.d.ts
index 854e1315a04ac..3e7381a7fae0d 100644
--- a/src/fetchers/types.d.ts
+++ b/src/fetchers/types.d.ts
@@ -22,7 +22,7 @@ export type StatsData = {
totalIssues: number;
totalStars: number;
contributedTo: number;
- rank: { level: string; score: number };
+ rank: { level: string; percentile: number };
};
export type Lang = {
diff --git a/tests/calculateRank.test.js b/tests/calculateRank.test.js
index 3bfd7f4376248..4dd29f8ff2a81 100644
--- a/tests/calculateRank.test.js
+++ b/tests/calculateRank.test.js
@@ -2,7 +2,7 @@ import "@testing-library/jest-dom";
import { calculateRank } from "../src/calculateRank.js";
describe("Test calculateRank", () => {
- it("new user gets B rank", () => {
+ it("new user gets C rank", () => {
expect(
calculateRank({
all_commits: false,
@@ -13,10 +13,24 @@ describe("Test calculateRank", () => {
stars: 0,
followers: 0,
}),
- ).toStrictEqual({ level: "B", score: 100 });
+ ).toStrictEqual({ level: "C", percentile: 100 });
});
- it("average user gets A rank", () => {
+ it("beginner user gets B- rank", () => {
+ expect(
+ calculateRank({
+ all_commits: false,
+ commits: 125,
+ prs: 25,
+ issues: 10,
+ repos: 0,
+ stars: 25,
+ followers: 5,
+ }),
+ ).toStrictEqual({ level: "B-", percentile: 69.333868386557 });
+ });
+
+ it("median user gets B+ rank", () => {
expect(
calculateRank({
all_commits: false,
@@ -24,13 +38,13 @@ describe("Test calculateRank", () => {
prs: 50,
issues: 25,
repos: 0,
- stars: 250,
- followers: 25,
+ stars: 50,
+ followers: 10,
}),
- ).toStrictEqual({ level: "A", score: 50 });
+ ).toStrictEqual({ level: "B+", percentile: 50 });
});
- it("average user gets A rank (include_all_commits)", () => {
+ it("average user gets B+ rank (include_all_commits)", () => {
expect(
calculateRank({
all_commits: true,
@@ -38,13 +52,13 @@ describe("Test calculateRank", () => {
prs: 50,
issues: 25,
repos: 0,
- stars: 250,
- followers: 25,
+ stars: 50,
+ followers: 10,
}),
- ).toStrictEqual({ level: "A", score: 50 });
+ ).toStrictEqual({ level: "B+", percentile: 50 });
});
- it("more than average user gets A+ rank", () => {
+ it("advanced user gets A rank", () => {
expect(
calculateRank({
all_commits: false,
@@ -52,13 +66,13 @@ describe("Test calculateRank", () => {
prs: 100,
issues: 50,
repos: 0,
- stars: 500,
- followers: 50,
+ stars: 200,
+ followers: 40,
}),
- ).toStrictEqual({ level: "A+", score: 25 });
+ ).toStrictEqual({ level: "A", percentile: 22.72727272727273 });
});
- it("expert user gets S rank", () => {
+ it("expert user gets A+ rank", () => {
expect(
calculateRank({
all_commits: false,
@@ -66,23 +80,23 @@ describe("Test calculateRank", () => {
prs: 200,
issues: 100,
repos: 0,
- stars: 1000,
- followers: 100,
+ stars: 800,
+ followers: 160,
}),
- ).toStrictEqual({ level: "S", score: 6.25 });
+ ).toStrictEqual({ level: "A+", percentile: 6.082887700534744 });
});
- it("ezyang gets S+ rank", () => {
+ it("sindresorhus gets S rank", () => {
expect(
calculateRank({
all_commits: false,
- commits: 1000,
- prs: 4000,
- issues: 2000,
+ commits: 1300,
+ prs: 1500,
+ issues: 4500,
repos: 0,
- stars: 5000,
- followers: 2000,
+ stars: 600000,
+ followers: 50000,
}),
- ).toStrictEqual({ level: "S+", score: 1.1363983154296875 });
+ ).toStrictEqual({ level: "S", percentile: 0.49947889605312934 });
});
});
From 9831d254d7eef7bd41a2557eae10c131c1113fa5 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Tue, 13 Jun 2023 15:58:30 +0200
Subject: [PATCH 274/905] test: update 2e2 rank values (#2816)
This commit ensures the new rank values introduced by #2762 are added
to the 2e2 test.
---
tests/e2e/e2e.test.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js
index e778597542077..685d5aeed9753 100644
--- a/tests/e2e/e2e.test.js
+++ b/tests/e2e/e2e.test.js
@@ -20,7 +20,10 @@ const STATS_DATA = {
totalIssues: 1,
totalStars: 1,
contributedTo: 1,
- rank: { level: "B", score: 98.50610674501908 },
+ rank: {
+ level: "C",
+ percentile: 97.89377603631637,
+ },
};
const LANGS_DATA = {
From c4035a5765f073d117404fbdd271a4f7569be044 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Wed, 14 Jun 2023 10:08:40 +0300
Subject: [PATCH 275/905] Use node 18.x in continuous integration (#2819)
---
.github/workflows/e2e-test.yml | 2 +-
.github/workflows/generate-theme-doc.yml | 2 +-
.github/workflows/preview-theme.yml | 2 +-
.github/workflows/stale-theme-pr-closer.yaml | 2 +-
.github/workflows/test.yml | 2 +-
.github/workflows/update-langs.yaml | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index d45c76ba08e58..09e1bc01f93b0 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node-version: [16.x]
+ node-version: [18.x]
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/generate-theme-doc.yml b/.github/workflows/generate-theme-doc.yml
index 75f6511f09015..18099ae92e1b1 100644
--- a/.github/workflows/generate-theme-doc.yml
+++ b/.github/workflows/generate-theme-doc.yml
@@ -12,7 +12,7 @@ jobs:
name: Generate theme doc
strategy:
matrix:
- node-version: [16.x]
+ node-version: [18.x]
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/preview-theme.yml b/.github/workflows/preview-theme.yml
index 132d4eb741e14..f29155c8241aa 100644
--- a/.github/workflows/preview-theme.yml
+++ b/.github/workflows/preview-theme.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node-version: [16.x]
+ node-version: [18.x]
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/stale-theme-pr-closer.yaml b/.github/workflows/stale-theme-pr-closer.yaml
index aa104feb528ca..cc963c32a2440 100644
--- a/.github/workflows/stale-theme-pr-closer.yaml
+++ b/.github/workflows/stale-theme-pr-closer.yaml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node-version: [16.x]
+ node-version: [18.x]
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e8fc84a7df963..b6fe191e79b46 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node-version: [16.x]
+ node-version: [18.x]
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/update-langs.yaml b/.github/workflows/update-langs.yaml
index ad6bfb6213b8f..1c31950a7d4bc 100644
--- a/.github/workflows/update-langs.yaml
+++ b/.github/workflows/update-langs.yaml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node-version: [16.x]
+ node-version: [18.x]
steps:
- uses: actions/checkout@v3
From d5a4dbdc7e3a79e1ffc828d414684cc4d5a9e1cf Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Thu, 15 Jun 2023 10:25:58 +0300
Subject: [PATCH 276/905] Specify node version inside package.json (#2823)
---
package.json | 3 +++
1 file changed, 3 insertions(+)
diff --git a/package.json b/package.json
index bc501ad38a877..fd15ee0e39c71 100644
--- a/package.json
+++ b/package.json
@@ -61,5 +61,8 @@
},
"lint-staged": {
"*.{js,css,md}": "prettier --write"
+ },
+ "engines": {
+ "node": ">=18.0.0"
}
}
From 1474a3abbee179d955f7eb445230716e47e1e68e Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Thu, 15 Jun 2023 10:27:28 +0300
Subject: [PATCH 277/905] Use default json import (#2820)
---
src/cards/wakatime-card.js | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index 396ede13c1ed8..9d03cbd9e68a6 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -10,17 +10,7 @@ import {
} from "../common/utils.js";
import { getStyles } from "../getStyles.js";
import { wakatimeCardLocales } from "../translations.js";
-
-/** Import language colors.
- *
- * @description Here we use the workaround found in
- * https://stackoverflow.com/questions/66726365/how-should-i-import-json-in-node
- * since vercel is using v16.14.0 which does not yet support json imports without the
- * --experimental-json-modules flag.
- */
-import { createRequire } from "module";
-const require = createRequire(import.meta.url);
-const languageColors = require("../common/languageColors.json"); // now works
+import languageColors from "../common/languageColors.json";
/**
* Creates the no coding activity SVG node.
From c86cc72df21e886cec9c8ea6181a84948c7e8acb Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Thu, 15 Jun 2023 10:27:48 +0300
Subject: [PATCH 278/905] Specify node version for NVM (node version manager)
users (#2824)
---
.nvmrc | 1 +
1 file changed, 1 insertion(+)
create mode 100644 .nvmrc
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000000000..25bf17fc5aaab
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+18
\ No newline at end of file
From 1bb65ddc29351bda8630c20eb58540c2ef6e2c23 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20Tyrkk=C3=B6?=
Date: Thu, 15 Jun 2023 10:35:09 +0300
Subject: [PATCH 279/905] Added pr reviews to stats (#1404)
* Added pr reviews to stats
* Add 'show' query parameter
* Fix show test
* refactoring
* cleanup
* refactor: restructure stats-card code
---------
Co-authored-by: Markus
Co-authored-by: Alexandr
Co-authored-by: rickstaa
---
api/index.js | 2 +
readme.md | 1 +
src/cards/stats-card.js | 78 ++++++++++++++++++++---------------
src/cards/types.d.ts | 1 +
src/common/icons.js | 1 +
src/fetchers/stats-fetcher.js | 6 ++-
src/fetchers/types.d.ts | 1 +
src/translations.js | 26 ++++++++++++
tests/fetchStats.test.js | 8 ++++
tests/renderStatsCard.test.js | 22 ++++++++++
10 files changed, 112 insertions(+), 34 deletions(-)
diff --git a/api/index.js b/api/index.js
index 67619f4d0830a..a3d9f2a9c0f90 100644
--- a/api/index.js
+++ b/api/index.js
@@ -37,6 +37,7 @@ export default async (req, res) => {
number_format,
border_color,
rank_icon,
+ show_total_reviews,
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
@@ -95,6 +96,7 @@ export default async (req, res) => {
locale: locale ? locale.toLowerCase() : null,
disable_animations: parseBoolean(disable_animations),
rank_icon,
+ show_total_reviews: parseBoolean(show_total_reviews),
}),
);
} catch (err) {
diff --git a/readme.md b/readme.md
index 2bc0863ae7074..4e4de58537104 100644
--- a/readme.md
+++ b/readme.md
@@ -306,6 +306,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
- `ring_color` - Color of the rank circle _(hex color)_. Defaults to the theme ring color if it exists and otherwise the title color.
- `number_format` - Switch between two available formats for displaying the card values `short` (i.e. `6.6k`) and `long` (i.e. `6626`). Default: `short`.
+- `show_total_reviews` - Show total PR reviews _(boolean)_. Default: `false`.
> **Note**
> When hide_rank=`true`, the minimum card width is 270 px + the title length and padding.
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index c483cdd8f56d2..30f85f79e66be 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -85,6 +85,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
totalCommits,
totalIssues,
totalPRs,
+ totalReviews,
contributedTo,
rank,
} = stats;
@@ -111,6 +112,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
locale,
disable_animations = false,
rank_icon = "default",
+ show_total_reviews = false,
} = options;
const lheight = parseInt(String(line_height), 10);
@@ -136,40 +138,50 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
});
// Meta data for creating text nodes with createTextNode function
- const STATS = {
- stars: {
- icon: icons.star,
- label: i18n.t("statcard.totalstars"),
- value: totalStars,
- id: "stars",
- },
- commits: {
- icon: icons.commits,
- label: `${i18n.t("statcard.commits")}${
- include_all_commits ? "" : ` (${new Date().getFullYear()})`
- }`,
- value: totalCommits,
- id: "commits",
- },
- prs: {
- icon: icons.prs,
- label: i18n.t("statcard.prs"),
- value: totalPRs,
- id: "prs",
- },
- issues: {
- icon: icons.issues,
- label: i18n.t("statcard.issues"),
- value: totalIssues,
- id: "issues",
- },
- contribs: {
- icon: icons.contribs,
- label: i18n.t("statcard.contribs"),
- value: contributedTo,
- id: "contribs",
- },
+ const STATS = {};
+
+ STATS.stars = {
+ icon: icons.star,
+ label: i18n.t("statcard.totalstars"),
+ value: totalStars,
+ id: "stars",
};
+ STATS.commits = {
+ icon: icons.commits,
+ label: `${i18n.t("statcard.commits")}${
+ include_all_commits ? "" : ` (${new Date().getFullYear()})`
+ }`,
+ value: totalCommits,
+ id: "commits",
+ };
+ STATS.prs = {
+ icon: icons.prs,
+ label: i18n.t("statcard.prs"),
+ value: totalPRs,
+ id: "prs",
+ };
+ STATS.issues = {
+ icon: icons.issues,
+ label: i18n.t("statcard.issues"),
+ value: totalIssues,
+ id: "issues",
+ };
+ STATS.contribs = {
+ icon: icons.contribs,
+ label: i18n.t("statcard.contribs"),
+ value: contributedTo,
+ id: "contribs",
+ };
+
+ // Extra stats items.
+ if (show_total_reviews) {
+ STATS.reviews = {
+ icon: icons.reviews,
+ label: i18n.t("statcard.reviews"),
+ value: totalReviews,
+ id: "reviews",
+ };
+ }
const longLocales = [
"cn",
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index d6a1de05d176f..cec7b7f705308 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -27,6 +27,7 @@ export type StatCardOptions = CommonOptions & {
ring_color: string;
text_bold: boolean;
rank_icon: RankIcon;
+ show_total_reviews: boolean;
};
export type RepoCardOptions = CommonOptions & {
diff --git a/src/common/icons.js b/src/common/icons.js
index 948ca0bc427d1..949ce65326985 100644
--- a/src/common/icons.js
+++ b/src/common/icons.js
@@ -6,6 +6,7 @@ const icons = {
icon: ``,
contribs: ``,
fork: ``,
+ reviews: ``,
};
/**
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index cebc38e8f53db..931f3e264c10b 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -45,7 +45,8 @@ const GRAPHQL_STATS_QUERY = `
name
login
contributionsCollection {
- totalCommitContributions
+ totalCommitContributions,
+ totalPullRequestReviewContributions
}
repositoriesContributedTo(first: 1, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) {
totalCount
@@ -185,6 +186,7 @@ const fetchStats = async (
const stats = {
name: "",
totalPRs: 0,
+ totalReviews: 0,
totalCommits: 0,
totalIssues: 0,
totalStars: 0,
@@ -227,6 +229,8 @@ const fetchStats = async (
}
stats.totalPRs = user.pullRequests.totalCount;
+ stats.totalReviews =
+ user.contributionsCollection.totalPullRequestReviewContributions;
stats.totalIssues = user.openIssues.totalCount + user.closedIssues.totalCount;
stats.contributedTo = user.repositoriesContributedTo.totalCount;
diff --git a/src/fetchers/types.d.ts b/src/fetchers/types.d.ts
index 3e7381a7fae0d..a810c6c6a0d1d 100644
--- a/src/fetchers/types.d.ts
+++ b/src/fetchers/types.d.ts
@@ -18,6 +18,7 @@ export type RepositoryData = {
export type StatsData = {
name: string;
totalPRs: number;
+ totalReviews: number;
totalCommits: number;
totalIssues: number;
totalStars: number;
diff --git a/src/translations.js b/src/translations.js
index cea5059966842..fd36b4800f887 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -196,6 +196,32 @@ const statCardLocales = ({ name, apostrophe }) => {
vi: "Đã Đóng Góp (năm ngoái)",
se: "Bidragit till (förra året)",
},
+ "statcard.reviews": {
+ ar: "Total PR reviews",
+ cn: "Total PR reviews",
+ cs: "Total PR reviews",
+ de: "Total PR reviews",
+ en: "Total PR reviews",
+ bn: "Total PR reviews",
+ es: "Total PR reviews",
+ fr: "Total PR reviews",
+ hu: "Total PR reviews",
+ it: "Total PR reviews",
+ ja: "Total PR reviews",
+ kr: "Total PR reviews",
+ nl: "Total PR reviews",
+ "pt-pt": "Total PR reviews",
+ "pt-br": "Total PR reviews",
+ np: "Total PR reviews",
+ el: "Total PR reviews",
+ ru: "Total PR reviews",
+ "uk-ua": "Total PR reviews",
+ id: "Total PR reviews",
+ my: "Total PR reviews",
+ sk: "Total PR reviews",
+ tr: "Total PR reviews",
+ pl: "Total PR reviews",
+ },
};
};
diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js
index f42b8fa78033d..3b0f915b3d0d6 100644
--- a/tests/fetchStats.test.js
+++ b/tests/fetchStats.test.js
@@ -12,6 +12,7 @@ const data_stats = {
repositoriesContributedTo: { totalCount: 61 },
contributionsCollection: {
totalCommitContributions: 100,
+ totalPullRequestReviewContributions: 50,
},
pullRequests: { totalCount: 300 },
openIssues: { totalCount: 100 },
@@ -116,6 +117,7 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
+ totalReviews: 50,
totalStars: 300,
rank,
});
@@ -146,6 +148,7 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
+ totalReviews: 50,
totalStars: 300,
rank,
});
@@ -182,6 +185,7 @@ describe("Test fetchStats", () => {
totalCommits: 1000,
totalIssues: 200,
totalPRs: 300,
+ totalReviews: 50,
totalStars: 300,
rank,
});
@@ -209,6 +213,7 @@ describe("Test fetchStats", () => {
totalCommits: 1000,
totalIssues: 200,
totalPRs: 300,
+ totalReviews: 50,
totalStars: 200,
rank,
});
@@ -234,6 +239,7 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
+ totalReviews: 50,
totalStars: 400,
rank,
});
@@ -259,6 +265,7 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
+ totalReviews: 50,
totalStars: 300,
rank,
});
@@ -284,6 +291,7 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
+ totalReviews: 50,
totalStars: 300,
rank,
});
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 0dd5883060d13..6b751d9d80a8c 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -16,6 +16,7 @@ const stats = {
totalCommits: 200,
totalIssues: 300,
totalPRs: 400,
+ totalReviews: 50,
contributedTo: 500,
rank: { level: "A+", score: 40 },
};
@@ -38,6 +39,9 @@ describe("Test renderStatsCard", () => {
expect(getByTestId(document.body, "contribs").textContent).toBe("500");
expect(queryByTestId(document.body, "card-bg")).toBeInTheDocument();
expect(queryByTestId(document.body, "rank-circle")).toBeInTheDocument();
+
+ // Default hidden stats
+ expect(queryByTestId(document.body, "reviews")).not.toBeInTheDocument();
});
it("should have proper name apostrophe", () => {
@@ -68,6 +72,24 @@ describe("Test renderStatsCard", () => {
expect(queryByTestId(document.body, "issues")).toBeNull();
expect(queryByTestId(document.body, "prs")).toBeNull();
expect(queryByTestId(document.body, "contribs")).toBeNull();
+ expect(queryByTestId(document.body, "reviews")).toBeNull();
+ });
+
+ it("should show total reviews", () => {
+ document.body.innerHTML = renderStatsCard(stats, {
+ show_total_reviews: true,
+ });
+
+ expect(
+ document.body.getElementsByTagName("svg")[0].getAttribute("height"),
+ ).toBe("220");
+
+ expect(queryByTestId(document.body, "stars")).toBeDefined();
+ expect(queryByTestId(document.body, "commits")).toBeDefined();
+ expect(queryByTestId(document.body, "issues")).toBeDefined();
+ expect(queryByTestId(document.body, "prs")).toBeDefined();
+ expect(queryByTestId(document.body, "contribs")).toBeDefined();
+ expect(queryByTestId(document.body, "reviews")).toBeDefined();
});
it("should hide_rank", () => {
From 89e37aa88506b5c2e62caf051e989edd552e5bc7 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Thu, 15 Jun 2023 22:24:47 +0200
Subject: [PATCH 280/905] refactor: add PR review translations (#2825)
---
src/translations.js | 54 +++++++++++++++++++++++----------------------
1 file changed, 28 insertions(+), 26 deletions(-)
diff --git a/src/translations.js b/src/translations.js
index fd36b4800f887..01da0a8db3446 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -6,6 +6,8 @@ import { encodeHTML } from "./common/utils.js";
* @param {string} name The name of the locale.
* @param {string} apostrophe Whether to use apostrophe or not.
* @returns {Object} The locales object.
+ *
+ * @see https://www.andiamo.co.uk/resources/iso-language-codes/ for language codes.
*/
const statCardLocales = ({ name, apostrophe }) => {
const encodedName = encodeHTML(name);
@@ -197,30 +199,30 @@ const statCardLocales = ({ name, apostrophe }) => {
se: "Bidragit till (förra året)",
},
"statcard.reviews": {
- ar: "Total PR reviews",
- cn: "Total PR reviews",
- cs: "Total PR reviews",
- de: "Total PR reviews",
+ ar: "إجمالي مراجعات العلاقات العامة",
+ cn: "公关评论总数",
+ cs: "Celkové PR recenze",
+ de: "Gesamtzahl der PR-Bewertungen",
en: "Total PR reviews",
- bn: "Total PR reviews",
- es: "Total PR reviews",
- fr: "Total PR reviews",
- hu: "Total PR reviews",
- it: "Total PR reviews",
- ja: "Total PR reviews",
- kr: "Total PR reviews",
- nl: "Total PR reviews",
- "pt-pt": "Total PR reviews",
- "pt-br": "Total PR reviews",
- np: "Total PR reviews",
- el: "Total PR reviews",
- ru: "Total PR reviews",
- "uk-ua": "Total PR reviews",
- id: "Total PR reviews",
- my: "Total PR reviews",
- sk: "Total PR reviews",
- tr: "Total PR reviews",
- pl: "Total PR reviews",
+ bn: "মোট জনসংযোগ পর্যালোচনা",
+ es: "Revisiones de relaciones públicas totales",
+ fr: "Total des revues de relations publiques",
+ hu: "Összes PR értékelés",
+ it: "Totale recensioni di pubbliche relazioni",
+ ja: "PRレビューの合計",
+ kr: "총 PR 리뷰",
+ nl: "Totale PR-recensies",
+ "pt-pt": "Total de avaliações de relações públicas",
+ "pt-br": "Total de avaliações de relações públicas",
+ np: "कुल PR समीक्षाहरू",
+ el: "Συνολικές κριτικές δημοσίων σχέσεων",
+ ru: "Всего PR отзывов",
+ "uk-ua": "Тотальний PR оглядів",
+ id: "Ulasan PR total",
+ my: "စုစုပေါင်း PR သုံးသပ်ချက်",
+ sk: "Celkové hodnotenia PR",
+ tr: "Toplam halkla ilişkiler incelemesi",
+ pl: "Razem recenzje PR",
},
};
};
@@ -444,10 +446,10 @@ const isLocaleAvailable = (locale) => {
};
export {
- isLocaleAvailable,
availableLocales,
- statCardLocales,
- repoCardLocales,
+ isLocaleAvailable,
langCardLocales,
+ repoCardLocales,
+ statCardLocales,
wakatimeCardLocales,
};
From 632549ddee6c829a18c394f8f23856e2598a8b17 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Thu, 15 Jun 2023 22:25:07 +0200
Subject: [PATCH 281/905] Revert "Use default json import (#2820)" (#2829)
This reverts commit 1474a3abbee179d955f7eb445230716e47e1e68e.
---
src/cards/wakatime-card.js | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index 9d03cbd9e68a6..396ede13c1ed8 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -10,7 +10,17 @@ import {
} from "../common/utils.js";
import { getStyles } from "../getStyles.js";
import { wakatimeCardLocales } from "../translations.js";
-import languageColors from "../common/languageColors.json";
+
+/** Import language colors.
+ *
+ * @description Here we use the workaround found in
+ * https://stackoverflow.com/questions/66726365/how-should-i-import-json-in-node
+ * since vercel is using v16.14.0 which does not yet support json imports without the
+ * --experimental-json-modules flag.
+ */
+import { createRequire } from "module";
+const require = createRequire(import.meta.url);
+const languageColors = require("../common/languageColors.json"); // now works
/**
* Creates the no coding activity SVG node.
From 22a12e1adeeeab9010b242f953f02a83a0772dd5 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Thu, 15 Jun 2023 22:28:19 +0200
Subject: [PATCH 282/905] ci: increase top-issues-action list size (#2826)
---
.github/workflows/top-issues-dashboard.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/top-issues-dashboard.yml b/.github/workflows/top-issues-dashboard.yml
index 969a696ebfb01..11ca141f007f1 100644
--- a/.github/workflows/top-issues-dashboard.yml
+++ b/.github/workflows/top-issues-dashboard.yml
@@ -15,6 +15,7 @@ jobs:
env:
github_token: ${{ secrets.GITHUB_TOKEN }}
with:
+ top_list_size: 10
filter: "1772"
label: true
dashboard: true
From 7a89ceedc96ee74b417b3498c036a55278a574ee Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Fri, 16 Jun 2023 09:43:07 +0300
Subject: [PATCH 283/905] Stats card: Reorder total reviews count position
(#2834)
---
src/cards/stats-card.js | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index 30f85f79e66be..9b5763e8489c9 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -160,6 +160,16 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
value: totalPRs,
id: "prs",
};
+
+ if (show_total_reviews) {
+ STATS.reviews = {
+ icon: icons.reviews,
+ label: i18n.t("statcard.reviews"),
+ value: totalReviews,
+ id: "reviews",
+ };
+ }
+
STATS.issues = {
icon: icons.issues,
label: i18n.t("statcard.issues"),
@@ -173,16 +183,6 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
id: "contribs",
};
- // Extra stats items.
- if (show_total_reviews) {
- STATS.reviews = {
- icon: icons.reviews,
- label: i18n.t("statcard.reviews"),
- value: totalReviews,
- id: "reviews",
- };
- }
-
const longLocales = [
"cn",
"es",
From 3831d18991d300f162454bd13c19798805dfebd8 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Fri, 16 Jun 2023 09:44:19 +0300
Subject: [PATCH 284/905] Stats card: Change total reviews label and add
missing translations (#2835)
---
src/translations.js | 52 ++++++++++++++++++++++++---------------------
1 file changed, 28 insertions(+), 24 deletions(-)
diff --git a/src/translations.js b/src/translations.js
index 01da0a8db3446..d6d173ea4e962 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -199,30 +199,34 @@ const statCardLocales = ({ name, apostrophe }) => {
se: "Bidragit till (förra året)",
},
"statcard.reviews": {
- ar: "إجمالي مراجعات العلاقات العامة",
- cn: "公关评论总数",
- cs: "Celkové PR recenze",
- de: "Gesamtzahl der PR-Bewertungen",
- en: "Total PR reviews",
- bn: "মোট জনসংযোগ পর্যালোচনা",
- es: "Revisiones de relaciones públicas totales",
- fr: "Total des revues de relations publiques",
- hu: "Összes PR értékelés",
- it: "Totale recensioni di pubbliche relazioni",
- ja: "PRレビューの合計",
- kr: "총 PR 리뷰",
- nl: "Totale PR-recensies",
- "pt-pt": "Total de avaliações de relações públicas",
- "pt-br": "Total de avaliações de relações públicas",
- np: "कुल PR समीक्षाहरू",
- el: "Συνολικές κριτικές δημοσίων σχέσεων",
- ru: "Всего PR отзывов",
- "uk-ua": "Тотальний PR оглядів",
- id: "Ulasan PR total",
- my: "စုစုပေါင်း PR သုံးသပ်ချက်",
- sk: "Celkové hodnotenia PR",
- tr: "Toplam halkla ilişkiler incelemesi",
- pl: "Razem recenzje PR",
+ ar: "تمت مراجعة إجمالي العلاقات العامة",
+ cn: "審查的 PR 總數",
+ "zh-tw": "审查的 PR 总数",
+ cs: "Celkový počet PR",
+ de: "Insgesamt überprüfte PRs",
+ en: "Total PRs reviewed",
+ bn: "সর্বমোট পুনরালোচনা করা PR",
+ es: "PR totales revisados",
+ fr: "Nombre total de PR examinés",
+ hu: "Összes ellenőrzött PR",
+ it: "PR totali esaminati",
+ ja: "レビューされた PR の総数",
+ kr: "검토된 총 PR",
+ nl: "Totaal beoordeelde PR's",
+ "pt-pt": "Total de PRs revistos",
+ "pt-br": "Total de PRs revisados",
+ np: "कुल पीआर समीक्षित",
+ el: "Σύνολο Αναθεωρημένων PR",
+ ru: "Всего pull request`ов проверено",
+ "uk-ua": "Всього pull request`iв перевірено",
+ id: "Total PR yang Direview",
+ my: "Jumlah PR Dikaji Semula",
+ sk: "Celkový počet PR",
+ tr: "İncelenen toplam PR",
+ pl: "Łącznie sprawdzonych PR",
+ uz: "Koʻrib chiqilgan PR-lar soni",
+ vi: "Tổng Số PR Đã Xem Xét",
+ se: "Totalt antal granskade PR",
},
};
};
From 05efc2811b45abf21eae4048a1fa78818e58af90 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Fri, 16 Jun 2023 09:45:25 +0300
Subject: [PATCH 285/905] Docs: make discussion link clickable (#2831)
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index 4e4de58537104..5485b70418501 100644
--- a/readme.md
+++ b/readme.md
@@ -635,7 +635,7 @@ Since the GitHub API only allows 5k requests per hour, my `https://github-readme
## On other platforms
> **Warning**
-> This way of using GRS is not officially supported and was added to cater to some particular use cases where Vercel could not be used (e.g. #2341). The support for this method, therefore, is limited.
+> This way of using GRS is not officially supported and was added to cater to some particular use cases where Vercel could not be used (e.g. [#2341](https://github.com/anuraghazra/github-readme-stats/discussions/2341)). The support for this method, therefore, is limited.
:hammer_and_wrench: Step-by-step guide for deploying on other platforms
From 4db78d779628474dba28734745b24980af114971 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Fri, 16 Jun 2023 09:46:44 +0300
Subject: [PATCH 286/905] Docs: improve GitHub media feature HTML example
formatting (#2830)
---
readme.md | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/readme.md b/readme.md
index 5485b70418501..0e843a81bac2d 100644
--- a/readme.md
+++ b/readme.md
@@ -235,15 +235,15 @@ You can use [GitHub's new media feature](https://github.blog/changelog/2022-05-1
```html
-
-
-
+
+
+
```
From 99aca1b6d5e06724737908f8b859ddf4d94b7fbf Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Fri, 16 Jun 2023 10:25:46 +0300
Subject: [PATCH 287/905] Fixed docstring for trimTopLanguages function (#2833)
* Fixed docstring for trimTopLanguages function
* dev
---
src/cards/top-languages-card.js | 8 ++++----
tests/renderTopLanguages.test.js | 10 ++++------
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index a757114f48ec7..90f5a5681d873 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -163,11 +163,11 @@ const donutCenterTranslation = (totalLangs) => {
* Trim top languages to lang_count while also hiding certain languages.
*
* @param {Record} topLangs Top languages.
- * @param {string[]} hide Languages to hide.
* @param {string} langs_count Number of languages to show.
- * @returns {{topLangs: Record, totalSize: number}} Trimmed top languages and total size.
+ * @param {string[]=} hide Languages to hide.
+ * @returns {{ langs: Lang[], totalLanguageSize: number }} Trimmed top languages and total size.
*/
-const trimTopLanguages = (topLangs, hide, langs_count) => {
+const trimTopLanguages = (topLangs, langs_count, hide) => {
let langs = Object.values(topLangs);
let langsToHide = {};
let langsCount = clampValue(parseInt(langs_count), 1, 10);
@@ -733,8 +733,8 @@ const renderTopLanguages = (topLangs, options = {}) => {
const { langs, totalLanguageSize } = trimTopLanguages(
topLangs,
- hide,
String(langs_count),
+ hide,
);
let width = isNaN(card_width)
diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js
index e9e43f22e4f23..fb42fbbcfb48a 100644
--- a/tests/renderTopLanguages.test.js
+++ b/tests/renderTopLanguages.test.js
@@ -310,21 +310,19 @@ describe("Test renderTopLanguages helper functions", () => {
langs: [langs.javascript],
totalLanguageSize: 200,
});
- expect(
- trimTopLanguages([langs.javascript, langs.HTML], [], 5),
- ).toStrictEqual({
+ expect(trimTopLanguages([langs.javascript, langs.HTML], 5)).toStrictEqual({
langs: [langs.javascript, langs.HTML],
totalLanguageSize: 400,
});
- expect(trimTopLanguages(langs, [], 5)).toStrictEqual({
+ expect(trimTopLanguages(langs, 5)).toStrictEqual({
langs: Object.values(langs),
totalLanguageSize: 500,
});
- expect(trimTopLanguages(langs, [], 2)).toStrictEqual({
+ expect(trimTopLanguages(langs, 2)).toStrictEqual({
langs: Object.values(langs).slice(0, 2),
totalLanguageSize: 400,
});
- expect(trimTopLanguages(langs, ["javascript"], 5)).toStrictEqual({
+ expect(trimTopLanguages(langs, 5, ["javascript"])).toStrictEqual({
langs: [langs.HTML, langs.css],
totalLanguageSize: 300,
});
From 1997328951ac458a14bdf264266913e3f1d02575 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Fri, 16 Jun 2023 10:27:37 +0300
Subject: [PATCH 288/905] Top langs card: Increase maximum languages count to
20 (#2832)
---
src/cards/top-languages-card.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 90f5a5681d873..4e8ed3c5eb3bd 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -17,6 +17,7 @@ const MIN_CARD_WIDTH = 280;
const DEFAULT_LANG_COLOR = "#858585";
const CARD_PADDING = 25;
const COMPACT_LAYOUT_BASE_HEIGHT = 90;
+const MAXIMUM_LANGS_COUNT = 20;
const NORMAL_LAYOUT_DEFAULT_LANGS_COUNT = 5;
const COMPACT_LAYOUT_DEFAULT_LANGS_COUNT = 6;
@@ -170,7 +171,7 @@ const donutCenterTranslation = (totalLangs) => {
const trimTopLanguages = (topLangs, langs_count, hide) => {
let langs = Object.values(topLangs);
let langsToHide = {};
- let langsCount = clampValue(parseInt(langs_count), 1, 10);
+ let langsCount = clampValue(parseInt(langs_count), 1, MAXIMUM_LANGS_COUNT);
// populate langsToHide map for quick lookup
// while filtering out
From a43fb81b23bcc656a8beaea947a84535d215d3e4 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sat, 17 Jun 2023 07:14:13 +0300
Subject: [PATCH 289/905] Add missing bracket inside CONTRIBUTING.md notice
(#2842)
---
CONTRIBUTING.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e2091c0baf850..bea64c94428c6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -53,7 +53,7 @@ All you need to do is edit the [themes/index.js](./themes/index.js) file and add
> If you are contributing your theme just because you are using it personally, then you can [customize the looks](./readme.md#customization) of your card with URL params instead.
> **Note**
-> Keep in mind that we already have a vast collection of different themes. To keep their number manageable, we began to add only themes supported by the community. Your pull request with theme addition will be merged once we get enough positive feedback from the community in the form of thumbs up (see [#1935](https://github.com/anuraghazra/github-readme-stats/issues/1935#top-themes-prs). Remember that you can also support themes of other contributors that you liked to speed up their merge.
+> Keep in mind that we already have a vast collection of different themes. To keep their number manageable, we began to add only themes supported by the community. Your pull request with theme addition will be merged once we get enough positive feedback from the community in the form of thumbs up (see [#1935](https://github.com/anuraghazra/github-readme-stats/issues/1935#top-themes-prs)). Remember that you can also support themes of other contributors that you liked to speed up their merge.
## Any contributions you make will be under the MIT Software License
From 331fa1183a4f6d50e17db8918057438b6595f09e Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sat, 17 Jun 2023 07:18:02 +0300
Subject: [PATCH 290/905] Docs: Increase maximum languages count to 20 (#2843)
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index 0e843a81bac2d..c06c143c0e66f 100644
--- a/readme.md
+++ b/readme.md
@@ -321,7 +321,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `hide_title` - _(boolean)_. Default: `false`.
- `layout` - Switch between five available layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`. Default: `normal`.
- `card_width` - Set the card's width manually _(number)_. Default `300`.
-- `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default: `5` for `normal` and `donut`, `6` for other layouts.
+- `langs_count` - Show more languages on the card, between 1-20 _(number)_. Default: `5` for `normal` and `donut`, `6` for other layouts.
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
- `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`.
- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
From c5d4bcbc1ac5e1811681e4acd825cd39145fb2d9 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sat, 17 Jun 2023 07:19:20 +0300
Subject: [PATCH 291/905] Docs: make important notice link clickable (#2841)
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index c06c143c0e66f..4c15007112f08 100644
--- a/readme.md
+++ b/readme.md
@@ -121,7 +121,7 @@ Please visit [this link](https://give.do/fundraisers/stand-beside-the-victims-of
# Important Notice
> **Warning**
-> Since the GitHub API only [allows 5k requests per hour per user account](https://docs.github.com/en/graphql/overview/resource-limitations), the public Vercel instance hosted on `https://github-readme-stats.vercel.app/api` could possibly hit the rate limiter (see #1471). We use caching to prevent this from happening (see https://github.com/anuraghazra/github-readme-stats#common-options). You can turn off these rate limit protections by deploying [your own Vercel instance](#disable-rate-limit-protections).
+> Since the GitHub API only [allows 5k requests per hour per user account](https://docs.github.com/en/graphql/overview/resource-limitations), the public Vercel instance hosted on `https://github-readme-stats.vercel.app/api` could possibly hit the rate limiter (see [#1471](https://github.com/anuraghazra/github-readme-stats/issues/1471)). We use caching to prevent this from happening (see https://github.com/anuraghazra/github-readme-stats#common-options). You can turn off these rate limit protections by deploying [your own Vercel instance](#disable-rate-limit-protections).
# GitHub Stats Card
From 6cbb08e218a57b4e7ecd8b2ad3485cba0f7765f5 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sat, 17 Jun 2023 12:14:24 +0300
Subject: [PATCH 292/905] Stats card: remove duplicate hide option default
value from render function (#2845)
---
src/cards/stats-card.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index 9b5763e8489c9..9c97247a635c5 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -78,7 +78,7 @@ const createTextNode = ({
* @param {Partial} options The card options.
* @returns {string} The stats card SVG object.
*/
-const renderStatsCard = (stats = {}, options = { hide: [] }) => {
+const renderStatsCard = (stats = {}, options = {}) => {
const {
name,
totalStars,
From b70b089b8e9f2379177e01614c6b3b8074e500b0 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sat, 17 Jun 2023 23:10:13 +0300
Subject: [PATCH 293/905] Stats card: migrate from show_total_reviews to show
option (resolves #2836) (#2844)
* Stats card: migrate from show_total_reviews to show option (resolves #2836)
* dev
* docs: improve documentation
---------
Co-authored-by: rickstaa
---
api/index.js | 4 +-
readme.md | 300 ++++++++++++++++++----------------
src/cards/stats-card.js | 4 +-
src/cards/types.d.ts | 2 +-
tests/renderStatsCard.test.js | 2 +-
5 files changed, 162 insertions(+), 150 deletions(-)
diff --git a/api/index.js b/api/index.js
index a3d9f2a9c0f90..d171c80f907b0 100644
--- a/api/index.js
+++ b/api/index.js
@@ -37,7 +37,7 @@ export default async (req, res) => {
number_format,
border_color,
rank_icon,
- show_total_reviews,
+ show,
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
@@ -96,7 +96,7 @@ export default async (req, res) => {
locale: locale ? locale.toLowerCase() : null,
disable_animations: parseBoolean(disable_animations),
rank_icon,
- show_total_reviews: parseBoolean(show_total_reviews),
+ show: parseArray(show),
}),
);
} catch (err) {
diff --git a/readme.md b/readme.md
index 4c15007112f08..dc8cd6d0963c8 100644
--- a/readme.md
+++ b/readme.md
@@ -73,50 +73,48 @@
Are you considering supporting the project by donating to me? Please DO NOT!!
-
-India just suffered one of the most devastating train accident and your help will be immensely valuable for the people who were effected by this tragedy.
+India just suffered one of the most devastating train accident and your help will be immensely valuable for the people who were effected by this tragedy.
Please visit [this link](https://give.do/fundraisers/stand-beside-the-victims-of-the-coromandel-express-train-tragedy-in-odisha-donate-now) and make a small donation to help the people in need. A small donation goes a long way. :heart:
-
-
# Features
-- [GitHub Stats Card](#github-stats-card)
- - [Hiding individual stats](#hiding-individual-stats)
- - [Showing icons](#showing-icons)
- - [Themes](#themes)
- - [Customization](#customization)
-- [GitHub Extra Pins](#github-extra-pins)
- - [Usage](#usage)
- - [Demo](#demo)
-- [Top Languages Card](#top-languages-card)
- - [Usage](#usage-1)
- - [Language stats algorithm](#language-stats-algorithm)
- - [Exclude individual repositories](#exclude-individual-repositories)
- - [Hide individual languages](#hide-individual-languages)
- - [Show more languages](#show-more-languages)
- - [Compact Language Card Layout](#compact-language-card-layout)
- - [Donut Chart Language Card Layout](#donut-chart-language-card-layout)
- - [Donut Vertical Chart Language Card Layout](#donut-vertical-chart-language-card-layout)
- - [Pie Chart Language Card Layout](#pie-chart-language-card-layout)
- - [Hide Progress Bars](#hide-progress-bars)
- - [Demo](#demo-1)
-- [Wakatime Stats Card](#wakatime-stats-card)
- - [Demo](#demo-2)
-- [All Demos](#all-demos)
- - [Quick Tip (Align The Repo Cards)](#quick-tip-align-the-repo-cards)
-- [Deploy on your own](#deploy-on-your-own)
- - [On Vercel](#on-vercel)
- - [:film\_projector: Check Out Step By Step Video Tutorial By @codeSTACKr](#film_projector-check-out-step-by-step-video-tutorial-by-codestackr)
- - [On other platforms](#on-other-platforms)
- - [Disable rate limit protections](#disable-rate-limit-protections)
- - [Keep your fork up to date](#keep-your-fork-up-to-date)
-- [:sparkling\_heart: Support the project](#sparkling_heart-support-the-project)
+* [GitHub Stats Card](#github-stats-card)
+ * [Hiding individual stats](#hiding-individual-stats)
+ * [Showing additional individual stats](#showing-additional-individual-stats)
+ * [Showing icons](#showing-icons)
+ * [Themes](#themes)
+ * [Customization](#customization)
+* [GitHub Extra Pins](#github-extra-pins)
+ * [Usage](#usage)
+ * [Demo](#demo)
+* [Top Languages Card](#top-languages-card)
+ * [Usage](#usage-1)
+ * [Language stats algorithm](#language-stats-algorithm)
+ * [Exclude individual repositories](#exclude-individual-repositories)
+ * [Hide individual languages](#hide-individual-languages)
+ * [Show more languages](#show-more-languages)
+ * [Compact Language Card Layout](#compact-language-card-layout)
+ * [Donut Chart Language Card Layout](#donut-chart-language-card-layout)
+ * [Donut Vertical Chart Language Card Layout](#donut-vertical-chart-language-card-layout)
+ * [Pie Chart Language Card Layout](#pie-chart-language-card-layout)
+ * [Hide Progress Bars](#hide-progress-bars)
+ * [Demo](#demo-1)
+* [Wakatime Stats Card](#wakatime-stats-card)
+ * [Demo](#demo-2)
+* [All Demos](#all-demos)
+ * [Quick Tip (Align The Repo Cards)](#quick-tip-align-the-repo-cards)
+* [Deploy on your own](#deploy-on-your-own)
+ * [On Vercel](#on-vercel)
+ * [:film\_projector: Check Out Step By Step Video Tutorial By @codeSTACKr](#film_projector-check-out-step-by-step-video-tutorial-by-codestackr)
+ * [On other platforms](#on-other-platforms)
+ * [Disable rate limit protections](#disable-rate-limit-protections)
+ * [Keep your fork up to date](#keep-your-fork-up-to-date)
+* [:sparkling\_heart: Support the project](#sparkling_heart-support-the-project)
# Important Notice
@@ -149,6 +147,16 @@ You can pass a query parameter `&hide=` to hide any specific stats with comma-se
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&hide=contribs,prs)
```
+### Showing additional individual stats
+
+You can pass a query parameter `&show=` to show any specific additional stats with comma-separated values.
+
+> Options: `&show=reviews`
+
+```md
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show=reviews)
+```
+
### Showing icons
To enable icons, you can pass `&show_icons=true` in the query param, like so:
@@ -177,8 +185,8 @@ You can look at a preview for [all available themes](./themes/README.md) or chec
#### Responsive Card Theme
-[![Anurag's GitHub stats-Dark](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&theme=dark#gh-dark-mode-only)](https://github.com/anuraghazra/github-readme-stats#responsive-card-theme#gh-dark-mode-only)
-[![Anurag's GitHub stats-Light](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&theme=default#gh-light-mode-only)](https://github.com/anuraghazra/github-readme-stats#responsive-card-theme#gh-light-mode-only)
+[![Anurag's GitHub stats-Dark](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show_icons=true\&theme=dark#gh-dark-mode-only)](https://github.com/anuraghazra/github-readme-stats#responsive-card-theme#gh-dark-mode-only)
+[![Anurag's GitHub stats-Light](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show_icons=true\&theme=default#gh-light-mode-only)](https://github.com/anuraghazra/github-readme-stats#responsive-card-theme#gh-light-mode-only)
Since GitHub will re-upload the cards and serve them from their [CDN](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-anonymized-urls), we can not infer the browser/GitHub theme on the server side. There are, however, four methods you can use to create dynamics themes on the client side.
@@ -193,11 +201,11 @@ We have included a `transparent` theme that has a transparent background. This t
:eyes: Show example
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&theme=transparent)
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show_icons=true\&theme=transparent)
-##### Add transparent alpha channel to a themes bg_color
+##### Add transparent alpha channel to a themes bg\_color
You can use the `bg_color` parameter to make any of [the available themes](./themes/README.md) transparent. This is done by setting the `bg_color` to a color with a transparent alpha channel (i.e. `bg_color=00000000`):
@@ -208,7 +216,7 @@ You can use the `bg_color` parameter to make any of [the available themes](./the
:eyes: Show example
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&bg_color=00000000)
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show_icons=true\&bg_color=00000000)
@@ -224,8 +232,8 @@ You can use [GitHub's theme context](https://github.blog/changelog/2021-11-24-sp
:eyes: Show example
-[![Anurag's GitHub stats-Dark](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&theme=dark#gh-dark-mode-only)](https://github.com/anuraghazra/github-readme-stats#gh-dark-mode-only)
-[![Anurag's GitHub stats-Light](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&theme=default#gh-light-mode-only)](https://github.com/anuraghazra/github-readme-stats#gh-light-mode-only)
+[![Anurag's GitHub stats-Dark](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show_icons=true\&theme=dark#gh-dark-mode-only)](https://github.com/anuraghazra/github-readme-stats#gh-dark-mode-only)
+[![Anurag's GitHub stats-Light](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show_icons=true\&theme=default#gh-light-mode-only)](https://github.com/anuraghazra/github-readme-stats#gh-light-mode-only)
@@ -270,64 +278,64 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you
#### Common Options
-- `title_color` - Card's title color _(hex color)_. Default: `2f80ed`.
-- `text_color` - Body text color _(hex color)_. Default: `434d58`.
-- `icon_color` - Icons color if available _(hex color)_. Default: `4c71f2`.
-- `border_color` - Card's border color _(hex color)_. Default: `e4e2e2` (Does not apply when `hide_border` is enabled).
-- `bg_color` - Card's background color _(hex color)_ **or** a gradient in the form of _angle,start,end_. Default: `fffefe`
-- `hide_border` - Hides the card's border _(boolean)_. Default: `false`
-- `theme` - name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme.
-- `cache_seconds` - set the cache header manually _(min: 14400, max: 86400)_. Default: `14400 seconds (4 hours)`.
-- `locale` - set the language in the card _(e.g. cn, de, es, etc.)_. Default: `en`.
-- `border_radius` - Corner rounding on the card. Default: `4.5`.
+* `title_color` - Card's title color *(hex color)*. Default: `2f80ed`.
+* `text_color` - Body text color *(hex color)*. Default: `434d58`.
+* `icon_color` - Icons color if available *(hex color)*. Default: `4c71f2`.
+* `border_color` - Card's border color *(hex color)*. Default: `e4e2e2` (Does not apply when `hide_border` is enabled).
+* `bg_color` - Card's background color *(hex color)* **or** a gradient in the form of *angle,start,end*. Default: `fffefe`
+* `hide_border` - Hides the card's border *(boolean)*. Default: `false`
+* `theme` - name of the theme, choose from [all available themes](./themes/README.md). Default: `default` theme.
+* `cache_seconds` - set the cache header manually *(min: 14400, max: 86400)*. Default: `14400 seconds (4 hours)`.
+* `locale` - set the language in the card *(e.g. cn, de, es, etc.)*. Default: `en`.
+* `border_radius` - Corner rounding on the card. Default: `4.5`.
> **Warning**
> We use caching to decrease the load on our servers (see ). Our cards have a default cache of 4 hours (14400 seconds). Also, note that the cache is clamped to a minimum of 4 hours and a maximum of 24 hours.
-##### Gradient in bg_color
+##### Gradient in bg\_color
-You can provide multiple comma-separated values in the bg_color option to render a gradient with the following format:
+You can provide multiple comma-separated values in the bg\_color option to render a gradient with the following format:
&bg_color=DEG,COLOR1,COLOR2,COLOR3...COLOR10
#### Stats Card Exclusive Options
-- `hide` - Hides the [specified items](#hiding-individual-stats) from stats _(Comma-separated values)_. Default: `[] (blank array)`.
-- `hide_title` - _(boolean)_. Default: `false`.
-- `card_width` - Set the card's width manually _(number)_. Default: `500px (approx.)`.
-- `hide_rank` - _(boolean)_ hides the rank and automatically resizes the card width. Default: `false`.
-- `rank_icon` - Shows alternative rank icon (i.e. `github` or `default`). Default: `default`.
-- `show_icons` - _(boolean)_. Default: `false`.
-- `include_all_commits` - Count total commits instead of just the current year commits _(boolean)_. Default: `false`.
-- `line_height` - Sets the line height between text _(number)_. Default: `25`.
-- `exclude_repo` - Exclude stars from specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
-- `custom_title` - Sets a custom title for the card. Default: ` GitHub Stats`.
-- `text_bold` - Use bold text _(boolean)_. Default: `true`.
-- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
-- `ring_color` - Color of the rank circle _(hex color)_. Defaults to the theme ring color if it exists and otherwise the title color.
-- `number_format` - Switch between two available formats for displaying the card values `short` (i.e. `6.6k`) and `long` (i.e. `6626`). Default: `short`.
-- `show_total_reviews` - Show total PR reviews _(boolean)_. Default: `false`.
+* `hide` - Hides the [specified items](#hiding-individual-stats) from stats *(Comma-separated values)*. Default: `[] (blank array)`.
+* `hide_title` - *(boolean)*. Default: `false`.
+* `card_width` - Set the card's width manually *(number)*. Default: `500px (approx.)`.
+* `hide_rank` - *(boolean)* hides the rank and automatically resizes the card width. Default: `false`.
+* `rank_icon` - Shows alternative rank icon (i.e. `github` or `default`). Default: `default`.
+* `show_icons` - *(boolean)*. Default: `false`.
+* `include_all_commits` - Count total commits instead of just the current year commits *(boolean)*. Default: `false`.
+* `line_height` - Sets the line height between text *(number)*. Default: `25`.
+* `exclude_repo` - Exclude stars from specified repositories *(Comma-separated values)*. Default: `[] (blank array)`.
+* `custom_title` - Sets a custom title for the card. Default: ` GitHub Stats`.
+* `text_bold` - Use bold text *(boolean)*. Default: `true`.
+* `disable_animations` - Disables all animations in the card *(boolean)*. Default: `false`.
+* `ring_color` - Color of the rank circle *(hex color)*. Defaults to the theme ring color if it exists and otherwise the title color.
+* `number_format` - Switch between two available formats for displaying the card values `short` (i.e. `6.6k`) and `long` (i.e. `6626`). Default: `short`.
+* `show` - Show [additional items](#showing-additional-individual-stats) on stats card (i.e. `reviews`) *(Comma-separated values)*. Default: `[] (blank array)`.
> **Note**
-> When hide_rank=`true`, the minimum card width is 270 px + the title length and padding.
+> When hide\_rank=`true`, the minimum card width is 270 px + the title length and padding.
#### Repo Card Exclusive Options
-- `show_owner` - Show the repo's owner name _(boolean)_. Default: `false`.
+* `show_owner` - Show the repo's owner name *(boolean)*. Default: `false`.
#### Language Card Exclusive Options
-- `hide` - Hide the languages specified from the card _(Comma-separated values)_. Default: `[] (blank array)`.
-- `hide_title` - _(boolean)_. Default: `false`.
-- `layout` - Switch between five available layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`. Default: `normal`.
-- `card_width` - Set the card's width manually _(number)_. Default `300`.
-- `langs_count` - Show more languages on the card, between 1-20 _(number)_. Default: `5` for `normal` and `donut`, `6` for other layouts.
-- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
-- `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`.
-- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
-- `hide_progress` - It uses the compact layout option, hides percentages, and removes the bars. Default: `false`.
-- `size_weight` - Configures language stats algorithm _(number)_ (see [Language stats algorithm](#Language-stats-algorithm)), defaults to 1.
-- `count_weight` - Configures language stats algorithm _(number)_ (see [Language stats algorithm](#Language-stats-algorithm)), defaults to 0.
+* `hide` - Hide the languages specified from the card *(Comma-separated values)*. Default: `[] (blank array)`.
+* `hide_title` - *(boolean)*. Default: `false`.
+* `layout` - Switch between five available layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`. Default: `normal`.
+* `card_width` - Set the card's width manually *(number)*. Default `300`.
+* `langs_count` - Show more languages on the card, between 1-20 *(number)*. Default: `5` for `normal` and `donut`, `6` for other layouts.
+* `exclude_repo` - Exclude specified repositories *(Comma-separated values)*. Default: `[] (blank array)`.
+* `custom_title` - Sets a custom title for the card *(string)*. Default `Most Used Languages`.
+* `disable_animations` - Disables all animations in the card *(boolean)*. Default: `false`.
+* `hide_progress` - It uses the compact layout option, hides percentages, and removes the bars. Default: `false`.
+* `size_weight` - Configures language stats algorithm *(number)* (see [Language stats algorithm](#Language-stats-algorithm)), defaults to 1.
+* `count_weight` - Configures language stats algorithm *(number)* (see [Language stats algorithm](#Language-stats-algorithm)), defaults to 0.
> **Warning**
> Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
@@ -336,16 +344,16 @@ You can provide multiple comma-separated values in the bg_color option to render
#### Wakatime Card Exclusive Options
-- `hide` - Hide the languages specified from the card _(Comma-separated values)_. Default: `[] (blank array)`.
-- `hide_title` - _(boolean)_. Default `false`.
-- `line_height` - Sets the line height between text _(number)_. Default `25`.
-- `hide_progress` - Hides the progress bar and percentage _(boolean)_. Default `false`.
-- `custom_title` - Sets a custom title for the card _(string)_. Default `Wakatime Stats`.
-- `layout` - Switch between two available layouts `default` & `compact`. Default `default`.
-- `langs_count` - Limit the number of languages on the card, defaults to all reported languages _(number)_.
-- `api_domain` - Set a custom API domain for the card, e.g. to use services like [Hakatime](https://github.com/mujx/hakatime) or [Wakapi](https://github.com/muety/wakapi) _(string)_. Default `Waka API`.
+* `hide` - Hide the languages specified from the card *(Comma-separated values)*. Default: `[] (blank array)`.
+* `hide_title` - *(boolean)*. Default `false`.
+* `line_height` - Sets the line height between text *(number)*. Default `25`.
+* `hide_progress` - Hides the progress bar and percentage *(boolean)*. Default `false`.
+* `custom_title` - Sets a custom title for the card *(string)*. Default `Wakatime Stats`.
+* `layout` - Switch between two available layouts `default` & `compact`. Default `default`.
+* `langs_count` - Limit the number of languages on the card, defaults to all reported languages *(number)*.
+* `api_domain` - Set a custom API domain for the card, e.g. to use services like [Hakatime](https://github.com/mujx/hakatime) or [Wakapi](https://github.com/muety/wakapi) *(string)*. Default `Waka API`.
-* * *
+***
# GitHub Extra Pins
@@ -365,11 +373,11 @@ Endpoint: `api/pin?username=anuraghazra&repo=github-readme-stats`
### Demo
-![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats)
+![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra\&repo=github-readme-stats)
-Use [show_owner](#customization) variable to include the repo's owner username
+Use [show\_owner](#customization) variable to include the repo's owner username
-![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&show_owner=true)
+![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra\&repo=github-readme-stats\&show_owner=true)
# Top Languages Card
@@ -404,9 +412,9 @@ ranking_index = (byte_count ^ size_weight) * (repo_count ^ count_weight)
By default, only the byte count is used for determining the languages percentages shown on the language card (i.e. `size_weight=1` and `count_weight=0`). You can, however, use the `&size_weight=` and `&count_weight=` options to weight the language usage calculation. The values must be positive real numbers. [More details about the algorithm can be found here](https://github.com/anuraghazra/github-readme-stats/issues/1600#issuecomment-1046056305).
-- `&size_weight=1&count_weight=0` - _(default)_ Orders by byte count.
-- `&size_weight=0.5&count_weight=0.5` - _(recommended)_ Uses both byte and repo count for ranking
-- `&size_weight=0&count_weight=1` - Orders by repo count
+* `&size_weight=1&count_weight=0` - *(default)* Orders by byte count.
+* `&size_weight=0.5&count_weight=0.5` - *(recommended)* Uses both byte and repo count for ranking
+* `&size_weight=0&count_weight=1` - Orders by repo count
```md
![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&size_weight=0.5&count_weight=0.5)
@@ -480,25 +488,25 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)
-- Compact layout
+* Compact layout
-![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)
+![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra\&layout=compact)
-- Donut Chart layout
+* Donut Chart layout
-[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut)](https://github.com/anuraghazra/github-readme-stats)
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra\&layout=donut)](https://github.com/anuraghazra/github-readme-stats)
-- Donut Vertical Chart layout
+* Donut Vertical Chart layout
-[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=donut-vertical)](https://github.com/anuraghazra/github-readme-stats)
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra\&layout=donut-vertical)](https://github.com/anuraghazra/github-readme-stats)
-- Pie Chart layout
+* Pie Chart layout
-[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=pie)](https://github.com/anuraghazra/github-readme-stats)
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra\&layout=pie)](https://github.com/anuraghazra/github-readme-stats)
-- Hidden progress bars
+* Hidden progress bars
-![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide_progress=true)
+![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra\&hide_progress=true)
# Wakatime Stats Card
@@ -515,71 +523,75 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)
-![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)
+![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok\&hide_progress=true)
-- Compact layout
+* Compact layout
-![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)
+![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok\&layout=compact)
-* * *
+***
# All Demos
-- Default
+* Default
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra)
-- Hiding specific stats
+* Hiding specific stats
+
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&hide=contribs,issues)
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&hide=contribs,issues)
+* Showing addition stats
-- Showing icons
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show=reviews)
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&hide=issues&show_icons=true)
+* Showing icons
-- Shows Github logo instead rank level
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&hide=issues\&show_icons=true)
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&rank_icon=github)
+* Shows Github logo instead rank level
-- Customize Border Color
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&rank_icon=github)
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&border_color=2e4058)
+* Customize Border Color
-- Include All Commits
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&border_color=2e4058)
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&include_all_commits=true)
+* Include All Commits
-- Themes
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&include_all_commits=true)
+
+* Themes
Choose from any of the [default themes](#themes)
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&theme=radical)
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show_icons=true\&theme=radical)
-- Gradient
+* Gradient
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&bg_color=30,e96443,904e95&title_color=fff&text_color=fff)
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&bg_color=30,e96443,904e95\&title_color=fff\&text_color=fff)
-- Customizing stats card
+* Customizing stats card
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api/?username=anuraghazra&show_icons=true&title_color=fff&icon_color=79ff97&text_color=9f9f9f&bg_color=151515)
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api/?username=anuraghazra\&show_icons=true\&title_color=fff\&icon_color=79ff97\&text_color=9f9f9f\&bg_color=151515)
-- Setting card locale
+* Setting card locale
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api/?username=anuraghazra&locale=es)
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api/?username=anuraghazra\&locale=es)
-- Customizing repo card
+* Customizing repo card
-![Customized Card](https://github-readme-stats.vercel.app/api/pin?username=anuraghazra&repo=github-readme-stats&title_color=fff&icon_color=f9f9f9&text_color=9f9f9f&bg_color=151515)
+![Customized Card](https://github-readme-stats.vercel.app/api/pin?username=anuraghazra\&repo=github-readme-stats\&title_color=fff\&icon_color=f9f9f9\&text_color=9f9f9f\&bg_color=151515)
-- Top languages
+* Top languages
![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)
-- WakaTime card
+* WakaTime card
![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)
-* * *
+***
## Quick Tip (Align The Repo Cards)
@@ -598,7 +610,7 @@ By default, GitHub does not lay out the cards side by side. To do that, you can
## On Vercel
-### :film_projector: [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
+### :film\_projector: [Check Out Step By Step Video Tutorial By @codeSTACKr](https://youtu.be/n6d4KHSKqGk?t=107)
Since the GitHub API only allows 5k requests per hour, my `https://github-readme-stats.vercel.app/api` could possibly hit the rate limiter. If you host it on your own Vercel server, then you do not have to worry about anything. Click on the deploy button to get started!
@@ -653,7 +665,7 @@ Since the GitHub API only allows 5k requests per hour, my `https://github-readme
Github Readme Stats contains several Vercel environment variables that can be used to remove the rate limit protections:
-- `CACHE_SECONDS`: This environment variable takes precedence over our cache minimum and maximum values and can circumvent these values for self Hosted Vercel instances.
+* `CACHE_SECONDS`: This environment variable takes precedence over our cache minimum and maximum values and can circumvent these values for self Hosted Vercel instances.
See [the Vercel documentation](https://vercel.com/docs/concepts/projects/environment-variables) on adding these environment variables to your Vercel instance.
@@ -661,23 +673,23 @@ See [the Vercel documentation](https://vercel.com/docs/concepts/projects/environ
You can keep your fork, and thus your private Vercel instance up to date with the upstream using GitHub's [Sync Fork button](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork). You can also use the [pull](https://github.com/wei/pull) package created by [@wei](https://github.com/wei) to automate this process.
-# :sparkling_heart: Support the project
+# :sparkling\_heart: Support the project
I open-source almost everything I can and try to reply to everyone needing help using these projects. Obviously,
this takes time. You can use this service for free.
However, if you are using this project and are happy with it or just want to encourage me to continue creating stuff, there are a few ways you can do it:
-- Giving proper credit when you use github-readme-stats on your readme, linking back to it :D
-- Starring and sharing the project :rocket:
-- [![paypal.me/anuraghazra](https://ionicabizau.github.io/badges/paypal.svg)](https://www.paypal.me/anuraghazra) - You can make one-time donations via PayPal. I'll probably buy a ~~coffee~~ tea. :tea:
+* Giving proper credit when you use github-readme-stats on your readme, linking back to it :D
+* Starring and sharing the project :rocket:
+* [![paypal.me/anuraghazra](https://ionicabizau.github.io/badges/paypal.svg)](https://www.paypal.me/anuraghazra) - You can make one-time donations via PayPal. I'll probably buy a ~~coffee~~ tea. :tea:
Thanks! :heart:
-* * *
+***
-[![https://vercel.com?utm_source=github_readme_stats_team&utm_campaign=oss](./powered-by-vercel.svg)](https://vercel.com?utm_source=github_readme_stats_team&utm_campaign=oss)
+[![https://vercel.com?utm\_source=github\_readme\_stats\_team\&utm\_campaign=oss](./powered-by-vercel.svg)](https://vercel.com?utm_source=github_readme_stats_team\&utm_campaign=oss)
-Contributions are welcome! <3
+Contributions are welcome! <3
Made with :heart: and JavaScript.
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index 9c97247a635c5..034c45e08ad07 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -112,7 +112,7 @@ const renderStatsCard = (stats = {}, options = {}) => {
locale,
disable_animations = false,
rank_icon = "default",
- show_total_reviews = false,
+ show = [],
} = options;
const lheight = parseInt(String(line_height), 10);
@@ -161,7 +161,7 @@ const renderStatsCard = (stats = {}, options = {}) => {
id: "prs",
};
- if (show_total_reviews) {
+ if (show.includes("reviews")) {
STATS.reviews = {
icon: icons.reviews,
label: i18n.t("statcard.reviews"),
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index cec7b7f705308..abd7d20fa8fc2 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -27,7 +27,7 @@ export type StatCardOptions = CommonOptions & {
ring_color: string;
text_bold: boolean;
rank_icon: RankIcon;
- show_total_reviews: boolean;
+ show: string[];
};
export type RepoCardOptions = CommonOptions & {
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 6b751d9d80a8c..6a47f944400e0 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -77,7 +77,7 @@ describe("Test renderStatsCard", () => {
it("should show total reviews", () => {
document.body.innerHTML = renderStatsCard(stats, {
- show_total_reviews: true,
+ show: ["reviews"],
});
expect(
From 2e65a2ee100bc7f4b2fef7f2bd5ce7d1f2996609 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sun, 18 Jun 2023 01:03:56 +0300
Subject: [PATCH 294/905] Docs: fix broken demos link (#2848)
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index dc8cd6d0963c8..6b5fe9312ee8a 100644
--- a/readme.md
+++ b/readme.md
@@ -30,7 +30,7 @@
- View Demo
+ View Demo
·
Report Bug
·
From eebaa44f2ad1d63373ca04d4d0be54c3e6eba5e0 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sun, 18 Jun 2023 01:04:35 +0300
Subject: [PATCH 295/905] CI: Add missing bracket inside theme preview workflow
warning (#2847)
---
scripts/preview-theme.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index 44a05d77f62e4..01fc121e6129b 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -30,7 +30,7 @@ const THEME_CONTRIB_GUIDELINES = `
\rHi, thanks for the theme contribution. Please read our theme [contribution guidelines](https://github.com/anuraghazra/github-readme-stats/blob/master/CONTRIBUTING.md#themes-contribution).
\r> **Warning**
- \r> Keep in mind that we already have a vast collection of different themes. To keep their number manageable, we began to add only themes supported by the community. Your pull request with theme addition will be merged once we get enough positive feedback from the community in the form of thumbs up (see [#1935](https://github.com/anuraghazra/github-readme-stats/issues/1935#top-themes-prs). Remember that you can also support themes of other contributors that you liked to speed up their merge.
+ \r> Keep in mind that we already have a vast collection of different themes. To keep their number manageable, we began to add only themes supported by the community. Your pull request with theme addition will be merged once we get enough positive feedback from the community in the form of thumbs up (see [#1935](https://github.com/anuraghazra/github-readme-stats/issues/1935#top-themes-prs)). Remember that you can also support themes of other contributors that you liked to speed up their merge.
\r> **Note**
\r> Also, note that if this theme is exclusively for your personal use, then instead of adding it to our theme collection, you can use card [customization options](https://github.com/anuraghazra/github-readme-stats#customization).
From 03b0ba096c3f406b33d669ce02ede68aea3430e0 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sun, 18 Jun 2023 19:31:58 +0300
Subject: [PATCH 296/905] Wakatime card: add missing translations (resolves
#2839) (#2850)
---
src/translations.js | 114 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 110 insertions(+), 4 deletions(-)
diff --git a/src/translations.js b/src/translations.js
index d6d173ea4e962..9934946814b89 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -389,20 +389,126 @@ const wakatimeCardLocales = {
se: "Wakatime statistik",
},
"wakatimecard.lastyear": {
- en: "last year",
+ ar: "العام الماضي",
cn: "去年",
+ "zh-tw": "去年",
+ cs: "Minulý rok",
+ de: "Letztes Jahr",
+ en: "last year",
+ bn: "গত বছর",
+ es: "El año pasado",
+ fr: "L'année dernière",
+ hu: "Tavaly",
+ it: "L'anno scorso",
+ ja: "昨年",
+ kr: "작년",
+ nl: "Vorig jaar",
+ "pt-pt": "Ano passado",
+ "pt-br": "Ano passado",
+ np: "गत वर्ष",
+ el: "Πέρυσι",
+ ru: "За прошлый год",
+ "uk-ua": "За минулий рік",
+ id: "Tahun lalu",
+ ml: "കഴിഞ്ഞ വർഷം",
+ my: "Tahun lepas",
+ sk: "Minulý rok",
+ tr: "Geçen yıl",
+ pl: "W zeszłym roku",
+ vi: "Năm ngoái",
+ se: "Förra året",
},
"wakatimecard.last7days": {
- en: "last 7 days",
+ ar: "آخر 7 أيام",
cn: "最近 7 天",
+ "zh-tw": "最近 7 天",
+ cs: "Posledních 7 dní",
+ de: "Letzte 7 Tage",
+ en: "last 7 days",
+ bn: "গত ৭ দিন",
+ es: "Últimos 7 días",
+ fr: "7 derniers jours",
+ hu: "Elmúlt 7 nap",
+ it: "Ultimi 7 giorni",
+ ja: "過去 7 日間",
+ kr: "지난 7 일",
+ nl: "Afgelopen 7 dagen",
+ "pt-pt": "Últimos 7 dias",
+ "pt-br": "Últimos 7 dias",
+ np: "गत ७ दिन",
+ el: "Τελευταίες 7 ημέρες",
+ ru: "Последние 7 дней",
+ "uk-ua": "Останні 7 днів",
+ id: "7 hari terakhir",
+ ml: "കഴിഞ്ഞ 7 ദിവസം",
+ my: "7 hari lepas",
+ sk: "Posledných 7 dní",
+ tr: "Son 7 gün",
+ pl: "Ostatnie 7 dni",
+ vi: "7 ngày qua",
+ se: "Senaste 7 dagarna",
},
"wakatimecard.notpublic": {
- en: "Wakatime user profile not public",
+ ar: "ملف المستخدم غير عام",
cn: "Wakatime 用户个人资料未公开",
+ "zh-tw": "Wakatime 使用者個人資料未公開",
+ cs: "Profil uživatele Wakatime není veřejný",
+ de: "Wakatime-Benutzerprofil nicht öffentlich",
+ en: "Wakatime user profile not public",
+ bn: "Wakatime ব্যবহারকারীর প্রোফাইল প্রকাশ্য নয়",
+ es: "Perfil de usuario de Wakatime no público",
+ fr: "Profil utilisateur Wakatime non public",
+ hu: "A Wakatime felhasználói profilja nem nyilvános",
+ it: "Profilo utente Wakatime non pubblico",
+ ja: "Wakatime ユーザープロファイルは公開されていません",
+ kr: "Wakatime 사용자 프로필이 공개되지 않았습니다",
+ nl: "Wakatime gebruikersprofiel niet openbaar",
+ "pt-pt": "Perfil de usuário Wakatime não público",
+ "pt-br": "Perfil de usuário Wakatime não público",
+ np: "Wakatime प्रयोगकर्ता प्रोफाइल सार्वजनिक छैन",
+ el: "Το προφίλ χρήστη Wakatime δεν είναι δημόσιο",
+ ru: "Профиль пользователя Wakatime не является общедоступным",
+ "uk-ua": "Профіль користувача Wakatime не є публічним",
+ id: "Profil pengguna Wakatime tidak publik",
+ ml: "Wakatime ഉപയോക്തൃ പ്രൊഫൈൽ പൊതുവായി പ്രസിദ്ധീകരിക്കപ്പെടാത്തതാണ്",
+ my: "Profil pengguna Wakatime tidak awam",
+ sk: "Profil používateľa Wakatime nie je verejný",
+ tr: "Wakatime kullanıcı profili herkese açık değil",
+ pl: "Profil użytkownika Wakatime nie jest publiczny",
+ vi: "Hồ sơ người dùng Wakatime không công khai",
+ se: "Wakatime användarprofil inte offentlig",
},
"wakatimecard.nocodedetails": {
- en: "User doesn't publicly share detailed code statistics",
+ ar: "المستخدم لا يشارك معلومات تفصيلية عن البرمجة",
cn: "用户不公开分享详细的代码统计信息",
+ "zh-tw": "使用者不公開分享詳細的程式碼統計資訊",
+ cs: "Uživatel nesdílí podrobné statistiky kódu",
+ de: "Benutzer teilt keine detaillierten Code-Statistiken",
+ en: "User doesn't publicly share detailed code statistics",
+ bn: "ব্যবহারকারী বিস্তারিত কোড পরিসংখ্যান প্রকাশ করেন না",
+ es: "El usuario no comparte públicamente estadísticas detalladas de código",
+ fr: "L'utilisateur ne partage pas publiquement de statistiques de code détaillées",
+ hu: "A felhasználó nem osztja meg nyilvánosan a részletes kódstatisztikákat",
+ it: "L'utente non condivide pubblicamente statistiche dettagliate sul codice",
+ ja: "ユーザーは詳細なコード統計を公開しません",
+ kr: "사용자는 자세한 코드 통계를 공개하지 않습니다",
+ nl: "Gebruiker deelt geen gedetailleerde code-statistieken",
+ "pt-pt":
+ "O utilizador não partilha publicamente estatísticas detalhadas de código",
+ "pt-br":
+ "O usuário não compartilha publicamente estatísticas detalhadas de código",
+ np: "प्रयोगकर्ता सार्वजनिक रूपमा विस्तृत कोड तथ्याङ्क साझा गर्दैन",
+ el: "Ο χρήστης δεν δημοσιεύει δημόσια λεπτομερείς στατιστικές κώδικα",
+ ru: "Пользователь не делится подробной статистикой кода",
+ "uk-ua": "Користувач не публікує детальну статистику коду",
+ id: "Pengguna tidak membagikan statistik kode terperinci secara publik",
+ ml: "ഉപയോക്താവ് പൊതുവെ വിശദീകരിച്ച കോഡ് സ്റ്റാറ്റിസ്റ്റിക്സ് പങ്കിടുന്നില്ല",
+ my: "Pengguna tidak berkongsi statistik kod terperinci secara awam",
+ sk: "Používateľ neposkytuje verejne podrobné štatistiky kódu",
+ tr: "Kullanıcı ayrıntılı kod istatistiklerini herkese açık olarak paylaşmıyor",
+ pl: "Użytkownik nie udostępnia publicznie szczegółowych statystyk kodu",
+ vi: "Người dùng không chia sẻ thống kê mã chi tiết công khai",
+ se: "Användaren delar inte offentligt detaljerad kodstatistik",
},
"wakatimecard.nocodingactivity": {
ar: "لا يوجد نشاط برمجي لهذا الأسبوع",
From a5260cb38a0302f545ff657d84987edd9303cae8 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 19 Jun 2023 05:06:24 +0200
Subject: [PATCH 297/905] feat: improve locale translation not found error
(#2853)
---
src/common/I18n.js | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/common/I18n.js b/src/common/I18n.js
index 48242af264c95..8d80a8510bc5c 100644
--- a/src/common/I18n.js
+++ b/src/common/I18n.js
@@ -9,15 +9,17 @@ class I18n {
}
t(str) {
+ const locale = this.locale || this.fallbackLocale;
+
if (!this.translations[str]) {
throw new Error(`${str} Translation string not found`);
}
- if (!this.translations[str][this.locale || this.fallbackLocale]) {
- throw new Error(`${str} Translation locale not found`);
+ if (!this.translations[str][locale]) {
+ throw new Error(`'${str}' translation not found for locale '${locale}'`);
}
- return this.translations[str][this.locale || this.fallbackLocale];
+ return this.translations[str][locale];
}
}
From 92518e375f99bf83b3e0113805ce80dae1f2fb72 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 19 Jun 2023 06:51:58 +0300
Subject: [PATCH 298/905] Stats card: show started and answered discussions
stats (#2849)
* Stats card: show started and answered discussions stats
* trans
* dev
---
readme.md | 8 ++---
src/cards/stats-card.js | 20 ++++++++++++
src/common/icons.js | 2 ++
src/fetchers/stats-fetcher.js | 10 ++++++
src/fetchers/types.d.ts | 2 ++
src/translations.js | 60 +++++++++++++++++++++++++++++++++++
tests/api.test.js | 8 +++++
tests/fetchStats.test.js | 16 ++++++++++
tests/renderStatsCard.test.js | 18 +++++++++--
9 files changed, 137 insertions(+), 7 deletions(-)
diff --git a/readme.md b/readme.md
index 6b5fe9312ee8a..6c3769450e8d9 100644
--- a/readme.md
+++ b/readme.md
@@ -151,7 +151,7 @@ You can pass a query parameter `&hide=` to hide any specific stats with comma-se
You can pass a query parameter `&show=` to show any specific additional stats with comma-separated values.
-> Options: `&show=reviews`
+> Options: `&show=reviews,discussions_started,discussions_answered`
```md
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show=reviews)
@@ -314,7 +314,7 @@ You can provide multiple comma-separated values in the bg\_color option to rende
* `disable_animations` - Disables all animations in the card *(boolean)*. Default: `false`.
* `ring_color` - Color of the rank circle *(hex color)*. Defaults to the theme ring color if it exists and otherwise the title color.
* `number_format` - Switch between two available formats for displaying the card values `short` (i.e. `6.6k`) and `long` (i.e. `6626`). Default: `short`.
-* `show` - Show [additional items](#showing-additional-individual-stats) on stats card (i.e. `reviews`) *(Comma-separated values)*. Default: `[] (blank array)`.
+* `show` - Show [additional items](#showing-additional-individual-stats) on stats card (i.e. `reviews`, `discussions_started` or `discussions_answered`) *(Comma-separated values)*. Default: `[] (blank array)`.
> **Note**
> When hide\_rank=`true`, the minimum card width is 270 px + the title length and padding.
@@ -541,9 +541,9 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&hide=contribs,issues)
-* Showing addition stats
+* Showing additional stats
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show=reviews)
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show=reviews,discussions_started,discussions_answered)
* Showing icons
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index 034c45e08ad07..79b00761e8bf2 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -86,6 +86,8 @@ const renderStatsCard = (stats = {}, options = {}) => {
totalIssues,
totalPRs,
totalReviews,
+ totalDiscussionsStarted,
+ totalDiscussionsAnswered,
contributedTo,
rank,
} = stats;
@@ -176,6 +178,24 @@ const renderStatsCard = (stats = {}, options = {}) => {
value: totalIssues,
id: "issues",
};
+
+ if (show.includes("discussions_started")) {
+ STATS.discussions_started = {
+ icon: icons.discussions_started,
+ label: i18n.t("statcard.discussions-started"),
+ value: totalDiscussionsStarted,
+ id: "discussions_started",
+ };
+ }
+ if (show.includes("discussions_answered")) {
+ STATS.discussions_answered = {
+ icon: icons.discussions_answered,
+ label: i18n.t("statcard.discussions-answered"),
+ value: totalDiscussionsAnswered,
+ id: "discussions_answered",
+ };
+ }
+
STATS.contribs = {
icon: icons.contribs,
label: i18n.t("statcard.contribs"),
diff --git a/src/common/icons.js b/src/common/icons.js
index 949ce65326985..4368375b94bcf 100644
--- a/src/common/icons.js
+++ b/src/common/icons.js
@@ -7,6 +7,8 @@ const icons = {
contribs: ``,
fork: ``,
reviews: ``,
+ discussions_started: ``,
+ discussions_answered: ``,
};
/**
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index 931f3e264c10b..21d2611b42312 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -63,6 +63,12 @@ const GRAPHQL_STATS_QUERY = `
followers {
totalCount
}
+ repositoryDiscussions {
+ totalCount
+ }
+ repositoryDiscussionComments(onlyAnswers: true) {
+ totalCount
+ }
${GRAPHQL_REPOS_FIELD}
}
}
@@ -190,6 +196,8 @@ const fetchStats = async (
totalCommits: 0,
totalIssues: 0,
totalStars: 0,
+ totalDiscussionsStarted: 0,
+ totalDiscussionsAnswered: 0,
contributedTo: 0,
rank: { level: "C", percentile: 100 },
};
@@ -232,6 +240,8 @@ const fetchStats = async (
stats.totalReviews =
user.contributionsCollection.totalPullRequestReviewContributions;
stats.totalIssues = user.openIssues.totalCount + user.closedIssues.totalCount;
+ stats.totalDiscussionsStarted = user.repositoryDiscussions.totalCount;
+ stats.totalDiscussionsAnswered = user.repositoryDiscussionComments.totalCount;
stats.contributedTo = user.repositoriesContributedTo.totalCount;
// Retrieve stars while filtering out repositories to be hidden.
diff --git a/src/fetchers/types.d.ts b/src/fetchers/types.d.ts
index a810c6c6a0d1d..3a86205834c12 100644
--- a/src/fetchers/types.d.ts
+++ b/src/fetchers/types.d.ts
@@ -22,6 +22,8 @@ export type StatsData = {
totalCommits: number;
totalIssues: number;
totalStars: number;
+ totalDiscussionsStarted: number;
+ totalDiscussionsAnswered: number;
contributedTo: number;
rank: { level: string; percentile: number };
};
diff --git a/src/translations.js b/src/translations.js
index 9934946814b89..1c66c28fa6543 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -228,6 +228,66 @@ const statCardLocales = ({ name, apostrophe }) => {
vi: "Tổng Số PR Đã Xem Xét",
se: "Totalt antal granskade PR",
},
+ "statcard.discussions-started": {
+ ar: "مجموع بدء المناقشات",
+ cn: "发起的讨论总数",
+ "zh-tw": "發起的討論總數",
+ cs: "Celkem zahájených diskusí",
+ de: "Gesamt gestartete Diskussionen",
+ en: "Total Discussions Started",
+ bn: "সর্বমোট আলোচনা শুরু",
+ es: "Discusiones totales iniciadas",
+ fr: "Nombre total de discussions lancées",
+ hu: "Összes megkezdett megbeszélés",
+ it: "Discussioni totali avviate",
+ ja: "開始されたディスカッションの総数",
+ kr: "시작된 토론 총 수",
+ nl: "Totaal gestarte discussies",
+ "pt-pt": "Total de Discussões Iniciadas",
+ "pt-br": "Total de Discussões Iniciadas",
+ np: "कुल चर्चा सुरु",
+ el: "Σύνολο Συζητήσεων που Ξεκίνησαν",
+ ru: "Всего начатых дискуссий",
+ "uk-ua": "Всього розпочатих дискусій",
+ id: "Total Diskusi Dimulai",
+ my: "Jumlah Perbincangan Bermula",
+ sk: "Celkový počet začatých diskusií",
+ tr: "Başlatılan Toplam Tartışma",
+ pl: "Łącznie rozpoczętych dyskusji",
+ uz: "Boshlangan muzokaralar soni",
+ vi: "Tổng Số Thảo Luận Bắt Đầu",
+ se: "Totalt antal diskussioner startade",
+ },
+ "statcard.discussions-answered": {
+ ar: "مجموع الردود على المناقشات",
+ cn: "回复的讨论总数",
+ "zh-tw": "回覆的討論總數",
+ cs: "Celkem zodpovězených diskusí",
+ de: "Gesamt beantwortete Diskussionen",
+ en: "Total Discussions Answered",
+ bn: "সর্বমোট আলোচনা উত্তর",
+ es: "Discusiones totales respondidas",
+ fr: "Nombre total de discussions répondues",
+ hu: "Összes megválaszolt megbeszélés",
+ it: "Discussioni totali risposte",
+ ja: "回答されたディスカッションの総数",
+ kr: "답변된 토론 총 수",
+ nl: "Totaal beantwoorde discussies",
+ "pt-pt": "Total de Discussões Respondidas",
+ "pt-br": "Total de Discussões Respondidas",
+ np: "कुल चर्चा उत्तर",
+ el: "Σύνολο Συζητήσεων που Απαντήθηκαν",
+ ru: "Всего отвеченных дискуссий",
+ "uk-ua": "Всього відповідей на дискусії",
+ id: "Total Diskusi Dibalas",
+ my: "Jumlah Perbincangan Dijawab",
+ sk: "Celkový počet zodpovedaných diskusií",
+ tr: "Toplam Cevaplanan Tartışma",
+ pl: "Łącznie odpowiedzianych dyskusji",
+ uz: "Javob berilgan muzokaralar soni",
+ vi: "Tổng Số Thảo Luận Đã Trả Lời",
+ se: "Totalt antal diskussioner besvarade",
+ },
};
};
diff --git a/tests/api.test.js b/tests/api.test.js
index 4fb965ea377f8..715579974e810 100644
--- a/tests/api.test.js
+++ b/tests/api.test.js
@@ -12,6 +12,9 @@ const stats = {
totalCommits: 200,
totalIssues: 300,
totalPRs: 400,
+ totalReviews: 50,
+ totalDiscussionsStarted: 10,
+ totalDiscussionsAnswered: 40,
contributedTo: 50,
rank: null,
};
@@ -33,11 +36,16 @@ const data_stats = {
repositoriesContributedTo: { totalCount: stats.contributedTo },
contributionsCollection: {
totalCommitContributions: stats.totalCommits,
+ totalPullRequestReviewContributions: stats.totalReviews,
},
pullRequests: { totalCount: stats.totalPRs },
openIssues: { totalCount: stats.totalIssues },
closedIssues: { totalCount: 0 },
followers: { totalCount: 0 },
+ repositoryDiscussions: { totalCount: stats.totalDiscussionsStarted },
+ repositoryDiscussionComments: {
+ totalCount: stats.totalDiscussionsAnswered,
+ },
repositories: {
totalCount: 1,
nodes: [{ stargazers: { totalCount: 100 } }],
diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js
index 3b0f915b3d0d6..3945d7570a83c 100644
--- a/tests/fetchStats.test.js
+++ b/tests/fetchStats.test.js
@@ -18,6 +18,8 @@ const data_stats = {
openIssues: { totalCount: 100 },
closedIssues: { totalCount: 100 },
followers: { totalCount: 100 },
+ repositoryDiscussions: { totalCount: 10 },
+ repositoryDiscussionComments: { totalCount: 40 },
repositories: {
totalCount: 5,
nodes: [
@@ -119,6 +121,8 @@ describe("Test fetchStats", () => {
totalPRs: 300,
totalReviews: 50,
totalStars: 300,
+ totalDiscussionsStarted: 10,
+ totalDiscussionsAnswered: 40,
rank,
});
});
@@ -150,6 +154,8 @@ describe("Test fetchStats", () => {
totalPRs: 300,
totalReviews: 50,
totalStars: 300,
+ totalDiscussionsStarted: 10,
+ totalDiscussionsAnswered: 40,
rank,
});
});
@@ -187,6 +193,8 @@ describe("Test fetchStats", () => {
totalPRs: 300,
totalReviews: 50,
totalStars: 300,
+ totalDiscussionsStarted: 10,
+ totalDiscussionsAnswered: 40,
rank,
});
});
@@ -215,6 +223,8 @@ describe("Test fetchStats", () => {
totalPRs: 300,
totalReviews: 50,
totalStars: 200,
+ totalDiscussionsStarted: 10,
+ totalDiscussionsAnswered: 40,
rank,
});
});
@@ -241,6 +251,8 @@ describe("Test fetchStats", () => {
totalPRs: 300,
totalReviews: 50,
totalStars: 400,
+ totalDiscussionsStarted: 10,
+ totalDiscussionsAnswered: 40,
rank,
});
});
@@ -267,6 +279,8 @@ describe("Test fetchStats", () => {
totalPRs: 300,
totalReviews: 50,
totalStars: 300,
+ totalDiscussionsStarted: 10,
+ totalDiscussionsAnswered: 40,
rank,
});
});
@@ -293,6 +307,8 @@ describe("Test fetchStats", () => {
totalPRs: 300,
totalReviews: 50,
totalStars: 300,
+ totalDiscussionsStarted: 10,
+ totalDiscussionsAnswered: 40,
rank,
});
});
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 6a47f944400e0..a2fd5b6095fd4 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -17,6 +17,8 @@ const stats = {
totalIssues: 300,
totalPRs: 400,
totalReviews: 50,
+ totalDiscussionsStarted: 10,
+ totalDiscussionsAnswered: 50,
contributedTo: 500,
rank: { level: "A+", score: 40 },
};
@@ -42,6 +44,12 @@ describe("Test renderStatsCard", () => {
// Default hidden stats
expect(queryByTestId(document.body, "reviews")).not.toBeInTheDocument();
+ expect(
+ queryByTestId(document.body, "discussions_started"),
+ ).not.toBeInTheDocument();
+ expect(
+ queryByTestId(document.body, "discussions_answered"),
+ ).not.toBeInTheDocument();
});
it("should have proper name apostrophe", () => {
@@ -73,16 +81,18 @@ describe("Test renderStatsCard", () => {
expect(queryByTestId(document.body, "prs")).toBeNull();
expect(queryByTestId(document.body, "contribs")).toBeNull();
expect(queryByTestId(document.body, "reviews")).toBeNull();
+ expect(queryByTestId(document.body, "discussions_started")).toBeNull();
+ expect(queryByTestId(document.body, "discussions_answered")).toBeNull();
});
- it("should show total reviews", () => {
+ it("should show additional stats", () => {
document.body.innerHTML = renderStatsCard(stats, {
- show: ["reviews"],
+ show: ["reviews", "discussions_started", "discussions_answered"],
});
expect(
document.body.getElementsByTagName("svg")[0].getAttribute("height"),
- ).toBe("220");
+ ).toBe("270");
expect(queryByTestId(document.body, "stars")).toBeDefined();
expect(queryByTestId(document.body, "commits")).toBeDefined();
@@ -90,6 +100,8 @@ describe("Test renderStatsCard", () => {
expect(queryByTestId(document.body, "prs")).toBeDefined();
expect(queryByTestId(document.body, "contribs")).toBeDefined();
expect(queryByTestId(document.body, "reviews")).toBeDefined();
+ expect(queryByTestId(document.body, "discussions_started")).toBeDefined();
+ expect(queryByTestId(document.body, "discussions_answered")).toBeDefined();
});
it("should hide_rank", () => {
From d727d178f0909b9f48f8481eec48866ed4f6948e Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 19 Jun 2023 09:33:02 +0300
Subject: [PATCH 299/905] Docs: fix link for extra pins card options (#2855)
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index 6c3769450e8d9..ca8a8063942ee 100644
--- a/readme.md
+++ b/readme.md
@@ -375,7 +375,7 @@ Endpoint: `api/pin?username=anuraghazra&repo=github-readme-stats`
![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra\&repo=github-readme-stats)
-Use [show\_owner](#customization) variable to include the repo's owner username
+Use [show\_owner](#repo-card-exclusive-options) query option to include the repo's owner username
![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra\&repo=github-readme-stats\&show_owner=true)
From 9a1cbaf062f677efab7f3bc6caa3b0c58129ac23 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 19 Jun 2023 10:45:23 +0300
Subject: [PATCH 300/905] Set prettier as workspace default formatter (#2854)
* Set prettier as workspace default formatter
* fix: fix conflicts
---------
Co-authored-by: rickstaa
---
.vscode/extensions.json | 3 ++-
.vscode/settings.json | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 408cb64f1d45b..11f71f6658f6c 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,5 +1,6 @@
{
"recommendations": [
- "yzhang.markdown-all-in-one"
+ "yzhang.markdown-all-in-one",
+ "esbenp.prettier-vscode"
]
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index b0ca284c85226..761ce7a6b370d 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,5 @@
{
"markdown.extension.toc.levels": "1..3",
- "editor.formatOnSave": true
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
}
From 62080c019cb9314d4e4c5806c7e5a1770a4875ee Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 19 Jun 2023 13:45:49 +0300
Subject: [PATCH 301/905] Remove several redundant number -> string -> number
conversions (#2856)
* Top langs card: remove redundant number -> string -> number conversion
* refactor(waka): remove redundant praseInt
---------
Co-authored-by: rickstaa
---
src/cards/top-languages-card.js | 6 +++---
src/cards/wakatime-card.js | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 4e8ed3c5eb3bd..f20f0e5c36f59 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -164,14 +164,14 @@ const donutCenterTranslation = (totalLangs) => {
* Trim top languages to lang_count while also hiding certain languages.
*
* @param {Record} topLangs Top languages.
- * @param {string} langs_count Number of languages to show.
+ * @param {number} langs_count Number of languages to show.
* @param {string[]=} hide Languages to hide.
* @returns {{ langs: Lang[], totalLanguageSize: number }} Trimmed top languages and total size.
*/
const trimTopLanguages = (topLangs, langs_count, hide) => {
let langs = Object.values(topLangs);
let langsToHide = {};
- let langsCount = clampValue(parseInt(langs_count), 1, MAXIMUM_LANGS_COUNT);
+ let langsCount = clampValue(langs_count, 1, MAXIMUM_LANGS_COUNT);
// populate langsToHide map for quick lookup
// while filtering out
@@ -734,7 +734,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
const { langs, totalLanguageSize } = trimTopLanguages(
topLangs,
- String(langs_count),
+ langs_count,
hide,
);
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index 396ede13c1ed8..f1df53b9da96e 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -204,7 +204,7 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
const lheight = parseInt(String(line_height), 10);
- const langsCount = clampValue(parseInt(String(langs_count)), 1, langs_count);
+ const langsCount = clampValue(langs_count, 1, langs_count);
// returns theme based colors with proper overrides and defaults
const { titleColor, textColor, iconColor, bgColor, borderColor } =
From a362af0ebc7bbcd6821e70ba559fecde4ce3bf2e Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Mon, 19 Jun 2023 12:58:02 +0200
Subject: [PATCH 302/905] feat: add 'progress' rank icon (#2858)
This pull request allows users to replace the rank level with the rank progress
by setting the `rank_icon` query to `progress`.
---
package-lock.json | 3 +++
readme.md | 6 +++++-
src/cards/stats-card.js | 2 +-
src/cards/types.d.ts | 2 +-
src/common/icons.js | 11 ++++++++++-
src/getStyles.js | 3 +++
tests/__snapshots__/renderWakatimeCard.test.js.snap | 6 ++++++
tests/renderStatsCard.test.js | 12 +++++++++++-
8 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index e6689bafff582..a11ae14d71b4e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -33,6 +33,9 @@
"lodash.snakecase": "^4.1.1",
"parse-diff": "^0.7.0",
"prettier": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
}
},
"node_modules/@actions/core": {
diff --git a/readme.md b/readme.md
index ca8a8063942ee..4a1eef362f9fc 100644
--- a/readme.md
+++ b/readme.md
@@ -304,7 +304,7 @@ You can provide multiple comma-separated values in the bg\_color option to rende
* `hide_title` - *(boolean)*. Default: `false`.
* `card_width` - Set the card's width manually *(number)*. Default: `500px (approx.)`.
* `hide_rank` - *(boolean)* hides the rank and automatically resizes the card width. Default: `false`.
-* `rank_icon` - Shows alternative rank icon (i.e. `github` or `default`). Default: `default`.
+* `rank_icon` - Shows alternative rank icon (i.e. `github`, `progress` or `default`). Default: `default`.
* `show_icons` - *(boolean)*. Default: `false`.
* `include_all_commits` - Count total commits instead of just the current year commits *(boolean)*. Default: `false`.
* `line_height` - Sets the line height between text *(number)*. Default: `25`.
@@ -553,6 +553,10 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&rank_icon=github)
+* Shows rank progress instead of rank level
+
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&rank_icon=progress)
+
* Customize Border Color
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&border_color=2e4058)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index 79b00761e8bf2..c6694f240bc5a 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -328,7 +328,7 @@ const renderStatsCard = (stats = {}, options = {}) => {
- ${rankIcon(rank_icon, rank?.level)}
+ ${rankIcon(rank_icon, rank?.level, progress)}
`;
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index abd7d20fa8fc2..53091b9bffe04 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -1,5 +1,5 @@
type ThemeNames = keyof typeof import("../../themes/index.js");
-type RankIcon = "default" | "github";
+type RankIcon = "default" | "github" | "progress";
export type CommonOptions = {
title_color: string;
diff --git a/src/common/icons.js b/src/common/icons.js
index 4368375b94bcf..fd743ff15bc68 100644
--- a/src/common/icons.js
+++ b/src/common/icons.js
@@ -14,9 +14,12 @@ const icons = {
/**
* Get rank icon
*
+ * @param {string} rankIcon - The rank icon type.
+ * @param {number} rankLevel - The rank level.
+ * @param {number} progress - The rank progress.
* @returns {string} - The SVG code of the rank icon
*/
-const rankIcon = (rankIcon, rankLevel) => {
+const rankIcon = (rankIcon, rankLevel, progress) => {
switch (rankIcon) {
case "github":
return `
@@ -24,6 +27,12 @@ const rankIcon = (rankIcon, rankLevel) => {
`;
+ case "progress":
+ return `
+
+ ${progress.toFixed(1)}%
+
+ `;
case "default":
default:
return `
diff --git a/src/getStyles.js b/src/getStyles.js
index 7e6113921b60d..088f7232af940 100644
--- a/src/getStyles.js
+++ b/src/getStyles.js
@@ -98,6 +98,9 @@ const getStyles = ({
font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor};
animation: scaleInAnimation 0.3s ease-in-out forwards;
}
+ .rank-progress-text {
+ font-size: 16px;
+ }
.not_bold { font-weight: 400 }
.bold { font-weight: 700 }
diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap
index 055c0f6642a7a..1ad81d231597f 100644
--- a/tests/__snapshots__/renderWakatimeCard.test.js.snap
+++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap
@@ -42,6 +42,9 @@ exports[`Test Render Wakatime Card should render correctly with compact layout 1
font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58;
animation: scaleInAnimation 0.3s ease-in-out forwards;
}
+ .rank-progress-text {
+ font-size: 16px;
+ }
.not_bold { font-weight: 400 }
.bold { font-weight: 700 }
@@ -222,6 +225,9 @@ exports[`Test Render Wakatime Card should render correctly with compact layout w
font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58;
animation: scaleInAnimation 0.3s ease-in-out forwards;
}
+ .rank-progress-text {
+ font-size: 16px;
+ }
.not_bold { font-weight: 400 }
.bold { font-weight: 700 }
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index a2fd5b6095fd4..05d74527c1bc5 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -20,7 +20,7 @@ const stats = {
totalDiscussionsStarted: 10,
totalDiscussionsAnswered: 50,
contributedTo: 500,
- rank: { level: "A+", score: 40 },
+ rank: { level: "A+", percentile: 40 },
};
describe("Test renderStatsCard", () => {
@@ -417,4 +417,14 @@ describe("Test renderStatsCard", () => {
});
expect(queryByTestId(document.body, "github-rank-icon")).toBeDefined();
});
+
+ it("should show the progress", () => {
+ document.body.innerHTML = renderStatsCard(stats, {
+ rank_icon: "progress",
+ });
+ expect(queryByTestId(document.body, "rank-progress-text")).toBeDefined();
+ expect(
+ queryByTestId(document.body, "progress-rank-icon").textContent.trim(),
+ ).toBe((100 - stats.rank.percentile).toFixed(1) + "%");
+ });
});
From 697c3e52b40d8c6380cf70aa1e6b9b95f88262d9 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Tue, 20 Jun 2023 08:58:02 +0300
Subject: [PATCH 303/905] Docs: change example wakatime profile (#2861)
---
docs/readme_de.md | 8 ++---
docs/readme_es.md | 10 +++---
docs/readme_kr.md | 10 +++---
docs/readme_nl.md | 8 ++---
docs/readme_np.md | 8 ++---
docs/readme_pt-BR.md | 6 ++--
docs/readme_tr.md | 10 +++---
readme.md | 74 ++++++++++++++++++++++----------------------
8 files changed, 67 insertions(+), 67 deletions(-)
diff --git a/docs/readme_de.md b/docs/readme_de.md
index 4e43031a5e6ae..0e6684529d53e 100644
--- a/docs/readme_de.md
+++ b/docs/readme_de.md
@@ -265,18 +265,18 @@ Du kannst die `&layout=compact` Option nutzen, um das Kartendesign zu ändern.
Ändere `?username=` in den eigenen [Wakatime](https://wakatime.com)-Benutzernamen.
```md
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
```
### Beispiel
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
- Kompaktes Layout
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_es.md b/docs/readme_es.md
index 4c74b4af60601..f48fe1fae1872 100644
--- a/docs/readme_es.md
+++ b/docs/readme_es.md
@@ -297,18 +297,18 @@ Puedes usar la opción `& layout = compact` para cambiar el diseño de la tarjet
cambia el valor del parámetro `?username=` a tu username en [Wakatime](https://wakatime.com).
```md
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
```
### Ejemplo
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
- Diseño compacto
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
---
@@ -358,7 +358,7 @@ Escoja cualquiera de los [temas por defecto](#themes)
- Tarjeta de Wakatime
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_kr.md b/docs/readme_kr.md
index 0520cb9aebaeb..db960051ae3d3 100644
--- a/docs/readme_kr.md
+++ b/docs/readme_kr.md
@@ -313,18 +313,18 @@ _참고:
`?username=` 속성의 값을 [Wakatime](https://wakatime.com) 계정의 사용자 명(닉네임)으로 바꿔주세요.
```md
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
```
### 미리보기
-[![Harlok 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
-[![Harlok 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
- 컴팩트한 레이아웃
-[![Harlok 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok 님의 wakatime 통계](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
---
@@ -374,7 +374,7 @@ _참고:
- Wakatime 카드
-[![Harlok 님의 Wakatime 카드](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok 님의 Wakatime 카드](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_nl.md b/docs/readme_nl.md
index 4159be647c485..0eabbb2b12419 100644
--- a/docs/readme_nl.md
+++ b/docs/readme_nl.md
@@ -298,14 +298,14 @@ Je kan de `&layout=compact` optie gebruiken om het kaart ontwerp aan te passen.
Verander de `?username=` waarde naar je [Wakatime](https://wakatime.com) gebruikersnaam.
```md
-[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
```
### Demo
-[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
-[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
---
@@ -355,7 +355,7 @@ Kies uit de [standaard thema\'s](#themes)
- Wakatime kaart
-[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's Wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_np.md b/docs/readme_np.md
index 7dbefda698a35..3b56312a65463 100644
--- a/docs/readme_np.md
+++ b/docs/readme_np.md
@@ -294,14 +294,14 @@ You can use the `&langs_count=` option to increase or decrease the number of lan
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
```md
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
```
### डेमो
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
---
@@ -351,7 +351,7 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
- वक समय कार्ड
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_pt-BR.md b/docs/readme_pt-BR.md
index fabb33a76c290..d26f457c83ba5 100644
--- a/docs/readme_pt-BR.md
+++ b/docs/readme_pt-BR.md
@@ -255,14 +255,14 @@ Utilize a opção `&layout=compact` para mudar o layout do cartão.
Altere o valor de `?username=` para o seu username do Wakatime.
```md
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
```
### Demonstração
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/docs/readme_tr.md b/docs/readme_tr.md
index b875c5e911968..786154837e1d8 100644
--- a/docs/readme_tr.md
+++ b/docs/readme_tr.md
@@ -297,18 +297,18 @@ Endpoint: `api/top-langs?username=mustafacagri`
`?username=` değerini [Wakatime](https://wakatime.com)'daki kullanıcı adınızla değiştirin.
```md
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
```
### Demo
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
- Kompakt Düzen
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
---
@@ -358,7 +358,7 @@ Endpoint: `api/top-langs?username=mustafacagri`
- Wakatime kart
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
---
diff --git a/readme.md b/readme.md
index 4a1eef362f9fc..687c59c84e641 100644
--- a/readme.md
+++ b/readme.md
@@ -83,38 +83,38 @@ Please visit [this link](https://give.do/fundraisers/stand-beside-the-victims-of
# Features
-* [GitHub Stats Card](#github-stats-card)
- * [Hiding individual stats](#hiding-individual-stats)
- * [Showing additional individual stats](#showing-additional-individual-stats)
- * [Showing icons](#showing-icons)
- * [Themes](#themes)
- * [Customization](#customization)
-* [GitHub Extra Pins](#github-extra-pins)
- * [Usage](#usage)
- * [Demo](#demo)
-* [Top Languages Card](#top-languages-card)
- * [Usage](#usage-1)
- * [Language stats algorithm](#language-stats-algorithm)
- * [Exclude individual repositories](#exclude-individual-repositories)
- * [Hide individual languages](#hide-individual-languages)
- * [Show more languages](#show-more-languages)
- * [Compact Language Card Layout](#compact-language-card-layout)
- * [Donut Chart Language Card Layout](#donut-chart-language-card-layout)
- * [Donut Vertical Chart Language Card Layout](#donut-vertical-chart-language-card-layout)
- * [Pie Chart Language Card Layout](#pie-chart-language-card-layout)
- * [Hide Progress Bars](#hide-progress-bars)
- * [Demo](#demo-1)
-* [Wakatime Stats Card](#wakatime-stats-card)
- * [Demo](#demo-2)
-* [All Demos](#all-demos)
- * [Quick Tip (Align The Repo Cards)](#quick-tip-align-the-repo-cards)
-* [Deploy on your own](#deploy-on-your-own)
- * [On Vercel](#on-vercel)
- * [:film\_projector: Check Out Step By Step Video Tutorial By @codeSTACKr](#film_projector-check-out-step-by-step-video-tutorial-by-codestackr)
- * [On other platforms](#on-other-platforms)
- * [Disable rate limit protections](#disable-rate-limit-protections)
- * [Keep your fork up to date](#keep-your-fork-up-to-date)
-* [:sparkling\_heart: Support the project](#sparkling_heart-support-the-project)
+- [GitHub Stats Card](#github-stats-card)
+ - [Hiding individual stats](#hiding-individual-stats)
+ - [Showing additional individual stats](#showing-additional-individual-stats)
+ - [Showing icons](#showing-icons)
+ - [Themes](#themes)
+ - [Customization](#customization)
+- [GitHub Extra Pins](#github-extra-pins)
+ - [Usage](#usage)
+ - [Demo](#demo)
+- [Top Languages Card](#top-languages-card)
+ - [Usage](#usage-1)
+ - [Language stats algorithm](#language-stats-algorithm)
+ - [Exclude individual repositories](#exclude-individual-repositories)
+ - [Hide individual languages](#hide-individual-languages)
+ - [Show more languages](#show-more-languages)
+ - [Compact Language Card Layout](#compact-language-card-layout)
+ - [Donut Chart Language Card Layout](#donut-chart-language-card-layout)
+ - [Donut Vertical Chart Language Card Layout](#donut-vertical-chart-language-card-layout)
+ - [Pie Chart Language Card Layout](#pie-chart-language-card-layout)
+ - [Hide Progress Bars](#hide-progress-bars)
+ - [Demo](#demo-1)
+- [Wakatime Stats Card](#wakatime-stats-card)
+ - [Demo](#demo-2)
+- [All Demos](#all-demos)
+ - [Quick Tip (Align The Repo Cards)](#quick-tip-align-the-repo-cards)
+- [Deploy on your own](#deploy-on-your-own)
+ - [On Vercel](#on-vercel)
+ - [:film\_projector: Check Out Step By Step Video Tutorial By @codeSTACKr](#film_projector-check-out-step-by-step-video-tutorial-by-codestackr)
+ - [On other platforms](#on-other-platforms)
+ - [Disable rate limit protections](#disable-rate-limit-protections)
+ - [Keep your fork up to date](#keep-your-fork-up-to-date)
+- [:sparkling\_heart: Support the project](#sparkling_heart-support-the-project)
# Important Notice
@@ -516,18 +516,18 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
```md
-[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
+[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)](https://github.com/anuraghazra/github-readme-stats)
```
### Demo
-![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)
+![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)
-![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok\&hide_progress=true)
+![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs\&hide_progress=true)
* Compact layout
-![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok\&layout=compact)
+![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs\&layout=compact)
***
@@ -593,7 +593,7 @@ Choose from any of the [default themes](#themes)
* WakaTime card
-![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)
+![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=ffflabs)
***
From ae6e2cc31bf3b9b786dbbf84fc226942727acd87 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Tue, 20 Jun 2023 09:41:40 +0300
Subject: [PATCH 304/905] CI: improve pull requests labeler (#2863)
---
.github/labeler.yml | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/.github/labeler.yml b/.github/labeler.yml
index ad3ba92fa4889..5644aecc0b96c 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -1,7 +1,12 @@
themes: themes/index.js
doc-translation: docs/*
-card-i18n: src/translations.js
-documentation: readme.md
+card-i18n:
+ - src/translations.js
+ - src/common/I18n.js
+documentation:
+ - readme.md
+ - CONTRIBUTING.md
+ - CODE_OF_CONDUCT.md
dependencies:
- package.json
- package-lock.json
From de093e8118f58c120755c83f06fb57d7014dac54 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Tue, 20 Jun 2023 09:42:11 +0300
Subject: [PATCH 305/905] Docs: improve GitHub media feature example HTML
formatting (#2862)
---
readme.md | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/readme.md b/readme.md
index 687c59c84e641..4c1674449c977 100644
--- a/readme.md
+++ b/readme.md
@@ -259,15 +259,15 @@ You can use [GitHub's new media feature](https://github.blog/changelog/2022-05-1
:eyes: Show example
-
-
-
+
+
+
From 2642fc546c16ed7f3896b9a326ddaea829908d80 Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Tue, 20 Jun 2023 08:47:02 +0200
Subject: [PATCH 306/905] add percentile rank icon (#2859)
* feat: add 'percentile' rank icon
This commit adds the `percentile` option for the `rank_icon` query
variable. This option displays the rank percentile the user belongs to.
* style: improve percentile rank icon styling
* dev
* dev
* dev
---------
Co-authored-by: Alexandr
---
.vscode/settings.json | 2 +-
readme.md | 6 +++++-
src/cards/stats-card.js | 2 +-
src/cards/types.d.ts | 2 +-
src/common/icons.js | 15 +++++++++------
src/getStyles.js | 7 +++++--
.../__snapshots__/renderWakatimeCard.test.js.snap | 10 ++++++++--
tests/renderStatsCard.test.js | 14 +++++++++-----
8 files changed, 39 insertions(+), 19 deletions(-)
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 761ce7a6b370d..5d461aafd10ff 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,5 @@
{
"markdown.extension.toc.levels": "1..3",
"editor.formatOnSave": true,
- "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
}
diff --git a/readme.md b/readme.md
index 4c1674449c977..0f9b7876a8f34 100644
--- a/readme.md
+++ b/readme.md
@@ -304,7 +304,7 @@ You can provide multiple comma-separated values in the bg\_color option to rende
* `hide_title` - *(boolean)*. Default: `false`.
* `card_width` - Set the card's width manually *(number)*. Default: `500px (approx.)`.
* `hide_rank` - *(boolean)* hides the rank and automatically resizes the card width. Default: `false`.
-* `rank_icon` - Shows alternative rank icon (i.e. `github`, `progress` or `default`). Default: `default`.
+* `rank_icon` - Shows alternative rank icon (i.e. `github`, `percentile` or `default`). Default: `default`.
* `show_icons` - *(boolean)*. Default: `false`.
* `include_all_commits` - Count total commits instead of just the current year commits *(boolean)*. Default: `false`.
* `line_height` - Sets the line height between text *(number)*. Default: `25`.
@@ -557,6 +557,10 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&rank_icon=progress)
+* Shows user rank percentile instead of rank level
+
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&rank_icon=percentile)
+
* Customize Border Color
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&border_color=2e4058)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index c6694f240bc5a..e3502fc48c136 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -328,7 +328,7 @@ const renderStatsCard = (stats = {}, options = {}) => {
- ${rankIcon(rank_icon, rank?.level, progress)}
+ ${rankIcon(rank_icon, rank?.level, rank?.percentile)}
`;
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index 53091b9bffe04..a3f0b2b7e0cfb 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -1,5 +1,5 @@
type ThemeNames = keyof typeof import("../../themes/index.js");
-type RankIcon = "default" | "github" | "progress";
+type RankIcon = "default" | "github" | "percentile";
export type CommonOptions = {
title_color: string;
diff --git a/src/common/icons.js b/src/common/icons.js
index fd743ff15bc68..28f82ed96c75f 100644
--- a/src/common/icons.js
+++ b/src/common/icons.js
@@ -16,10 +16,10 @@ const icons = {
*
* @param {string} rankIcon - The rank icon type.
* @param {number} rankLevel - The rank level.
- * @param {number} progress - The rank progress.
+ * @param {number} percentile - The rank percentile.
* @returns {string} - The SVG code of the rank icon
*/
-const rankIcon = (rankIcon, rankLevel, progress) => {
+const rankIcon = (rankIcon, rankLevel, percentile) => {
switch (rankIcon) {
case "github":
return `
@@ -27,11 +27,14 @@ const rankIcon = (rankIcon, rankLevel, progress) => {
`;
- case "progress":
+ case "percentile":
return `
-
- ${progress.toFixed(1)}%
-
+
+ Top
+
+
+ ${percentile.toFixed(1)}%
+
`;
case "default":
default:
diff --git a/src/getStyles.js b/src/getStyles.js
index 088f7232af940..79a7f8c9a0d45 100644
--- a/src/getStyles.js
+++ b/src/getStyles.js
@@ -98,7 +98,10 @@ const getStyles = ({
font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor};
animation: scaleInAnimation 0.3s ease-in-out forwards;
}
- .rank-progress-text {
+ .rank-percentile-header {
+ font-size: 14px;
+ }
+ .rank-percentile-text {
font-size: 16px;
}
@@ -130,4 +133,4 @@ const getStyles = ({
`;
};
-export { getStyles, getAnimations };
+export { getAnimations, getStyles };
diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap
index 1ad81d231597f..2050be022d9eb 100644
--- a/tests/__snapshots__/renderWakatimeCard.test.js.snap
+++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap
@@ -42,7 +42,10 @@ exports[`Test Render Wakatime Card should render correctly with compact layout 1
font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58;
animation: scaleInAnimation 0.3s ease-in-out forwards;
}
- .rank-progress-text {
+ .rank-percentile-header {
+ font-size: 14px;
+ }
+ .rank-percentile-text {
font-size: 16px;
}
@@ -225,7 +228,10 @@ exports[`Test Render Wakatime Card should render correctly with compact layout w
font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58;
animation: scaleInAnimation 0.3s ease-in-out forwards;
}
- .rank-progress-text {
+ .rank-percentile-header {
+ font-size: 14px;
+ }
+ .rank-percentile-text {
font-size: 16px;
}
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 05d74527c1bc5..0bb20442aad0f 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -418,13 +418,17 @@ describe("Test renderStatsCard", () => {
expect(queryByTestId(document.body, "github-rank-icon")).toBeDefined();
});
- it("should show the progress", () => {
+ it("should show the rank percentile", () => {
document.body.innerHTML = renderStatsCard(stats, {
- rank_icon: "progress",
+ rank_icon: "percentile",
});
- expect(queryByTestId(document.body, "rank-progress-text")).toBeDefined();
+ expect(queryByTestId(document.body, "percentile-top-header")).toBeDefined();
expect(
- queryByTestId(document.body, "progress-rank-icon").textContent.trim(),
- ).toBe((100 - stats.rank.percentile).toFixed(1) + "%");
+ queryByTestId(document.body, "percentile-top-header").textContent.trim(),
+ ).toBe("Top");
+ expect(queryByTestId(document.body, "rank-percentile-text")).toBeDefined();
+ expect(
+ queryByTestId(document.body, "percentile-rank-value").textContent.trim(),
+ ).toBe(stats.rank.percentile.toFixed(1) + "%");
});
});
From de431b934d5f43c34c75dbbc3f380e23b4d89ecd Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Thu, 22 Jun 2023 11:27:54 +0300
Subject: [PATCH 307/905] Use stable axios version 1.x.x (#2873)
---
package-lock.json | 52 ++++++++++++++++++++++++-----------------------
package.json | 2 +-
2 files changed, 28 insertions(+), 26 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index a11ae14d71b4e..4037fa669b081 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
- "axios": "^0.24.0",
+ "axios": "^1.4.0",
"dotenv": "^8.2.0",
"emoji-name-map": "^1.2.8",
"github-username-regex": "^1.0.0",
@@ -1605,15 +1605,16 @@
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "dev": true
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
- "version": "0.24.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
- "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
+ "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
"dependencies": {
- "follow-redirects": "^1.14.4"
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
}
},
"node_modules/axios-mock-adapter": {
@@ -2036,7 +2037,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
"dependencies": {
"delayed-stream": "~1.0.0"
},
@@ -2171,7 +2171,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "dev": true,
"engines": {
"node": ">=0.4.0"
}
@@ -2486,7 +2485,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
- "dev": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -4325,7 +4323,6 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -4334,7 +4331,6 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dev": true,
"dependencies": {
"mime-db": "1.52.0"
},
@@ -4764,6 +4760,11 @@
"node": ">= 6"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"node_modules/psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@@ -6899,15 +6900,16 @@
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "dev": true
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
- "version": "0.24.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
- "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
+ "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
"requires": {
- "follow-redirects": "^1.14.4"
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
}
},
"axios-mock-adapter": {
@@ -7207,7 +7209,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
"requires": {
"delayed-stream": "~1.0.0"
}
@@ -7317,8 +7318,7 @@
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "dev": true
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"deprecation": {
"version": "2.3.1",
@@ -7546,7 +7546,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
- "dev": true,
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -8899,14 +8898,12 @@
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "dev": true
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dev": true,
"requires": {
"mime-db": "1.52.0"
}
@@ -9217,6 +9214,11 @@
"sisteransi": "^1.0.5"
}
},
+ "proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
diff --git a/package.json b/package.json
index fd15ee0e39c71..4565d897b1312 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
"prettier": "^2.1.2"
},
"dependencies": {
- "axios": "^0.24.0",
+ "axios": "^1.4.0",
"dotenv": "^8.2.0",
"emoji-name-map": "^1.2.8",
"github-username-regex": "^1.0.0",
From f282ce4d64a69e9494a2e0d1793425a31ac6ba5f Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Thu, 22 Jun 2023 11:29:10 +0300
Subject: [PATCH 308/905] Docs: improve quick align tip section (#2865)
* Docs: move extra pins align tip into correct section
* dev
* dev
* dev
* dev
* dev
* dev
---
readme.md | 34 ++++++++++++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
diff --git a/readme.md b/readme.md
index 0f9b7876a8f34..456a977c65bf8 100644
--- a/readme.md
+++ b/readme.md
@@ -107,7 +107,7 @@ Please visit [this link](https://give.do/fundraisers/stand-beside-the-victims-of
- [Wakatime Stats Card](#wakatime-stats-card)
- [Demo](#demo-2)
- [All Demos](#all-demos)
- - [Quick Tip (Align The Repo Cards)](#quick-tip-align-the-repo-cards)
+ - [Quick Tip (Align The Cards)](#quick-tip-align-the-cards)
- [Deploy on your own](#deploy-on-your-own)
- [On Vercel](#on-vercel)
- [:film\_projector: Check Out Step By Step Video Tutorial By @codeSTACKr](#film_projector-check-out-step-by-step-video-tutorial-by-codestackr)
@@ -601,10 +601,19 @@ Choose from any of the [default themes](#themes)
***
-## Quick Tip (Align The Repo Cards)
+## Quick Tip (Align The Cards)
By default, GitHub does not lay out the cards side by side. To do that, you can use this approach:
+```html
+
+
+
+
+
+
+```
+
```html
@@ -614,6 +623,27 @@ By default, GitHub does not lay out the cards side by side. To do that, you can
```
+
+:eyes: Show example
+
+
+
+
+
+
+
+
+***
+
+
+
+
+
+
+
+
+
+
# Deploy on your own
## On Vercel
From a48d653fa4c1d1fbc1c72f0ad4ec4d0648953f83 Mon Sep 17 00:00:00 2001
From: iwbc-mzk <46069337+iwbc-mzk@users.noreply.github.com>
Date: Thu, 22 Jun 2023 19:07:52 +0900
Subject: [PATCH 309/905] Fixed resizing of stats card when all metrics except
rank are hidden (#2868)
* fixed card resizing in case of rank only
* fixed to display error when both stats and rank are hidden
* fix: fix visual alignment
---------
Co-authored-by: rickstaa
---
src/cards/stats-card.js | 50 ++++++++++++++++++++++++++++++++---------
src/translations.js | 31 +++++++++++++++++++++++++
2 files changed, 70 insertions(+), 11 deletions(-)
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index e3502fc48c136..4f61e13a7d746 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -3,6 +3,7 @@ import { Card } from "../common/Card.js";
import { I18n } from "../common/I18n.js";
import { icons, rankIcon } from "../common/icons.js";
import {
+ CustomError,
clampValue,
flexLayout,
getCardColors,
@@ -16,6 +17,8 @@ const CARD_MIN_WIDTH = 287;
const CARD_DEFAULT_WIDTH = 287;
const RANK_CARD_MIN_WIDTH = 420;
const RANK_CARD_DEFAULT_WIDTH = 450;
+const RANK_ONLY_CARD_MIN_WIDTH = 290;
+const RANK_ONLY_CARD_DEFAULT_WIDTH = 290;
/**
* Create a stats card text item.
@@ -234,11 +237,18 @@ const renderStatsCard = (stats = {}, options = {}) => {
}),
);
+ if (statItems.length === 0 && hide_rank) {
+ throw new CustomError(
+ "Could not render stats card.",
+ "Either stats or rank are required.",
+ );
+ }
+
// Calculate the card height depending on how many items there are
// but if rank circle is visible clamp the minimum height to `150`
let height = Math.max(
45 + (statItems.length + 1) * lheight,
- hide_rank ? 0 : 150,
+ hide_rank ? 0 : statItems.length ? 150 : 180,
);
// the lower the user's percentile the better
@@ -253,7 +263,13 @@ const renderStatsCard = (stats = {}, options = {}) => {
});
const calculateTextWidth = () => {
- return measureText(custom_title ? custom_title : i18n.t("statcard.title"));
+ return measureText(
+ custom_title
+ ? custom_title
+ : statItems.length
+ ? i18n.t("statcard.title")
+ : i18n.t("statcard.ranktitle"),
+ );
};
/*
@@ -261,7 +277,7 @@ const renderStatsCard = (stats = {}, options = {}) => {
When hide_rank=false, the minimum card_width is 340 px + the icon width (if show_icons=true).
Numbers are picked by looking at existing dimensions on production.
*/
- const iconWidth = show_icons ? 16 + /* padding */ 1 : 0;
+ const iconWidth = show_icons && statItems.length ? 16 + /* padding */ 1 : 0;
const minCardWidth =
(hide_rank
? clampValue(
@@ -269,9 +285,15 @@ const renderStatsCard = (stats = {}, options = {}) => {
CARD_MIN_WIDTH,
Infinity,
)
- : RANK_CARD_MIN_WIDTH) + iconWidth;
+ : statItems.length
+ ? RANK_CARD_MIN_WIDTH
+ : RANK_ONLY_CARD_MIN_WIDTH) + iconWidth;
const defaultCardWidth =
- (hide_rank ? CARD_DEFAULT_WIDTH : RANK_CARD_DEFAULT_WIDTH) + iconWidth;
+ (hide_rank
+ ? CARD_DEFAULT_WIDTH
+ : statItems.length
+ ? RANK_CARD_DEFAULT_WIDTH
+ : RANK_ONLY_CARD_DEFAULT_WIDTH) + iconWidth;
let width = isNaN(card_width) ? defaultCardWidth : card_width;
if (width < minCardWidth) {
width = minCardWidth;
@@ -279,7 +301,9 @@ const renderStatsCard = (stats = {}, options = {}) => {
const card = new Card({
customTitle: custom_title,
- defaultTitle: i18n.t("statcard.title"),
+ defaultTitle: statItems.length
+ ? i18n.t("statcard.title")
+ : i18n.t("statcard.ranktitle"),
width,
height,
border_radius,
@@ -309,12 +333,16 @@ const renderStatsCard = (stats = {}, options = {}) => {
* @returns {number} - Rank circle translation value.
*/
const calculateRankXTranslation = () => {
- const minXTranslation = RANK_CARD_MIN_WIDTH + iconWidth - 70;
- if (width > RANK_CARD_DEFAULT_WIDTH) {
- const xMaxExpansion = minXTranslation + (450 - minCardWidth) / 2;
- return xMaxExpansion + width - RANK_CARD_DEFAULT_WIDTH;
+ if (statItems.length) {
+ const minXTranslation = RANK_CARD_MIN_WIDTH + iconWidth - 70;
+ if (width > RANK_CARD_DEFAULT_WIDTH) {
+ const xMaxExpansion = minXTranslation + (450 - minCardWidth) / 2;
+ return xMaxExpansion + width - RANK_CARD_DEFAULT_WIDTH;
+ } else {
+ return minXTranslation + (width - minCardWidth) / 2;
+ }
} else {
- return minXTranslation + (width - minCardWidth) / 2;
+ return width / 2 + 20 - 10;
}
};
diff --git a/src/translations.js b/src/translations.js
index 1c66c28fa6543..d46277ae785db 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -43,6 +43,37 @@ const statCardLocales = ({ name, apostrophe }) => {
vi: `Thống Kê GitHub ${encodedName}`,
se: `GitHubstatistik för ${encodedName}`,
},
+ "statcard.ranktitle": {
+ ar: `${encodedName} إحصائيات غيت هاب`,
+ cn: `${encodedName} 的 GitHub 统计数据`,
+ "zh-tw": `${encodedName} 的 GitHub 統計數據`,
+ cs: `GitHub statistiky uživatele ${encodedName}`,
+ de: `${encodedName + apostrophe} GitHub-Statistiken`,
+ en: `${encodedName}'${apostrophe} GitHub Rank`,
+ bn: `${encodedName} এর GitHub পরিসংখ্যান`,
+ es: `Estadísticas de GitHub de ${encodedName}`,
+ fr: `Statistiques GitHub de ${encodedName}`,
+ hu: `${encodedName} GitHub statisztika`,
+ it: `Statistiche GitHub di ${encodedName}`,
+ ja: `${encodedName} の GitHub ランク`,
+ kr: `${encodedName}의 GitHub 통계`,
+ nl: `${encodedName}'${apostrophe} GitHub-statistieken`,
+ "pt-pt": `Estatísticas do GitHub de ${encodedName}`,
+ "pt-br": `Estatísticas do GitHub de ${encodedName}`,
+ np: `${encodedName}'${apostrophe} गिटहब तथ्याङ्क`,
+ el: `Στατιστικά GitHub του ${encodedName}`,
+ ru: `Статистика GitHub пользователя ${encodedName}`,
+ "uk-ua": `Статистика GitHub користувача ${encodedName}`,
+ id: `Statistik GitHub ${encodedName}`,
+ ml: `${encodedName}'${apostrophe} ഗിറ്റ്ഹബ് സ്ഥിതിവിവരക്കണക്കുകൾ`,
+ my: `Statistik GitHub ${encodedName}`,
+ sk: `GitHub štatistiky používateľa ${encodedName}`,
+ tr: `${encodedName} Hesabının GitHub Yıldızları`,
+ pl: `Statystyki GitHub użytkownika ${encodedName}`,
+ uz: `${encodedName}ning GitHub'dagi statistikasi`,
+ vi: `Thống Kê GitHub ${encodedName}`,
+ se: `GitHubstatistik för ${encodedName}`,
+ },
"statcard.totalstars": {
ar: "مجموع النجوم",
cn: "获标星数(star)",
From e5f1399cc2d8afd70bc399c0040fbf085f02c1fb Mon Sep 17 00:00:00 2001
From: Rick Staa
Date: Thu, 22 Jun 2023 15:52:46 +0200
Subject: [PATCH 310/905] docs: remove progress rank icon example (#2876)
---
readme.md | 4 ----
1 file changed, 4 deletions(-)
diff --git a/readme.md b/readme.md
index 456a977c65bf8..8b5bf10e489fd 100644
--- a/readme.md
+++ b/readme.md
@@ -553,10 +553,6 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&rank_icon=github)
-* Shows rank progress instead of rank level
-
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&rank_icon=progress)
-
* Shows user rank percentile instead of rank level
![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&rank_icon=percentile)
From 5486e2ca0602c7286339f44952de990bc832f49d Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Fri, 23 Jun 2023 10:24:17 +0300
Subject: [PATCH 311/905] Increase e2e tests timeout secs (#2878)
---
tests/e2e/e2e.test.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tests/e2e/e2e.test.js b/tests/e2e/e2e.test.js
index 685d5aeed9753..27c0714bdb8a9 100644
--- a/tests/e2e/e2e.test.js
+++ b/tests/e2e/e2e.test.js
@@ -108,7 +108,7 @@ describe("Fetch Cards", () => {
// Check if stats card from deployment matches the stats card from local.
expect(serverStatsSvg.data).toEqual(localStatsCardSVG);
- }, 7000);
+ }, 15000);
test("retrieve language card", async () => {
expect(VERCEL_PREVIEW_URL).toBeDefined();
@@ -133,7 +133,7 @@ describe("Fetch Cards", () => {
// Check if language card from deployment matches the local language card.
expect(severLanguageSVG.data).toEqual(localLanguageCardSVG);
- });
+ }, 15000);
test("retrieve WakaTime card", async () => {
expect(VERCEL_PREVIEW_URL).toBeDefined();
@@ -153,7 +153,7 @@ describe("Fetch Cards", () => {
// Check if WakaTime card from deployment matches the local WakaTime card.
expect(serverWakaTimeSvg.data).toEqual(localWakaCardSVG);
- });
+ }, 15000);
test("retrieve repo card", async () => {
expect(VERCEL_PREVIEW_URL).toBeDefined();
@@ -175,5 +175,5 @@ describe("Fetch Cards", () => {
// Check if Repo card from deployment matches the local Repo card.
expect(serverRepoSvg.data).toEqual(localRepoCardSVG);
- });
+ }, 15000);
});
From a7998f018668ad0a804c938a1a1ab37095112d57 Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sat, 24 Jun 2023 12:39:23 +0300
Subject: [PATCH 312/905] Top langs card: Fixed getLongestLang function
docstring to resolve vscode errors (#2881)
---
src/cards/top-languages-card.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index f20f0e5c36f59..1e02670d12a5d 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -33,13 +33,13 @@ const DONUT_VERTICAL_LAYOUT_DEFAULT_LANGS_COUNT = 6;
* Retrieves the programming language whose name is the longest.
*
* @param {Lang[]} arr Array of programming languages.
- * @returns {Object} Longest programming language object.
+ * @returns {{ name: string, size: number, color: string }} Longest programming language object.
*/
const getLongestLang = (arr) =>
arr.reduce(
(savedLang, lang) =>
lang.name.length > savedLang.name.length ? lang : savedLang,
- { name: "", size: null, color: "" },
+ { name: "", size: 0, color: "" },
);
/**
From b7eb65f819420c9073f1d3abe015e7947874e5aa Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Sun, 25 Jun 2023 23:07:46 +0300
Subject: [PATCH 313/905] I18n: Fixed docstring for statsCardLocales function
and enable ts-check (#2883)
---
src/translations.js | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/translations.js b/src/translations.js
index d46277ae785db..8cfdee5199a6b 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -1,11 +1,14 @@
+// @ts-check
+
import { encodeHTML } from "./common/utils.js";
/**
* Retrieves stat card labels in the available locales.
*
- * @param {string} name The name of the locale.
- * @param {string} apostrophe Whether to use apostrophe or not.
- * @returns {Object} The locales object.
+ * @param {object} props Function arguments.
+ * @param {string} props.name The name of the locale.
+ * @param {string} props.apostrophe Whether to use apostrophe or not.
+ * @returns {object} The locales object.
*
* @see https://www.andiamo.co.uk/resources/iso-language-codes/ for language codes.
*/
From 18c9de0a188904d9960bebc701aefe04d873607b Mon Sep 17 00:00:00 2001
From: Max Duval
Date: Mon, 26 Jun 2023 09:40:54 +0100
Subject: [PATCH 314/905] refactor: object shorthand (#2882)
---
src/calculateRank.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/calculateRank.js b/src/calculateRank.js
index c4583da0e804f..5556e8b72d23e 100644
--- a/src/calculateRank.js
+++ b/src/calculateRank.js
@@ -61,7 +61,7 @@ function calculateRank({
const level = LEVELS[THRESHOLDS.findIndex((t) => rank * 100 <= t)];
- return { level: level, percentile: rank * 100 };
+ return { level, percentile: rank * 100 };
}
export { calculateRank };
From e2fa7ad4238a2bb63ab9d5c8ef5761fc9f9fd7bf Mon Sep 17 00:00:00 2001
From: Alexandr Garbuzov
Date: Mon, 26 Jun 2023 15:27:54 +0300
Subject: [PATCH 315/905] CI: Add OSSF scorecard analysis workflow (#2879)
* CI: Add OSSF scorecard analysis workflow
* dev
* dev
* dev
* replace action versions with hashes
* readme badge
---
.github/workflows/ossf-analysis.yml | 48 +++++++++++++++++++++++++++++
readme.md | 3 ++
2 files changed, 51 insertions(+)
create mode 100644 .github/workflows/ossf-analysis.yml
diff --git a/.github/workflows/ossf-analysis.yml b/.github/workflows/ossf-analysis.yml
new file mode 100644
index 0000000000000..9249b3f2cfc76
--- /dev/null
+++ b/.github/workflows/ossf-analysis.yml
@@ -0,0 +1,48 @@
+name: OSSF Scorecard analysis workflow
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+
+permissions: read-all
+
+jobs:
+ analysis:
+ name: Scorecard analysis
+ runs-on: ubuntu-latest
+ permissions:
+ # Needed if using Code scanning alerts
+ security-events: write
+ # Needed for GitHub OIDC token if publish_results is true
+ id-token: write
+
+ steps:
+ - name: "Checkout code"
+ uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ with:
+ persist-credentials: false
+
+ - name: "Run analysis"
+ uses: ossf/scorecard-action@80e868c13c90f172d68d1f4501dee99e2479f7af # v2.1.3
+ with:
+ results_file: results.sarif
+ results_format: sarif
+ publish_results: true
+
+ # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
+ # format to the repository Actions tab.
+ - name: "Upload artifact"
+ uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ with:
+ name: SARIF file
+ path: results.sarif
+ retention-days: 5
+
+ # required for Code scanning alerts
+ - name: "Upload SARIF results to code scanning"
+ uses: github/codeql-action/upload-sarif@83f0fe6c4988d98a455712a27f0255212bba9bd4 # v2.3.6
+ with:
+ sarif_file: results.sarif
diff --git a/readme.md b/readme.md
index 8b5bf10e489fd..8ebcccc46cdd2 100644
--- a/readme.md
+++ b/readme.md
@@ -19,6 +19,9 @@
+
+
+