Merge branch 'technical-improvements' into user-management

This commit is contained in:
martin-mfg
2025-09-16 13:28:20 +02:00
19 changed files with 387 additions and 164 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
version: 2
updates:
# Maintain dependencies for NPM
# Maintain dependencies for npm
- package-ecosystem: npm
directory: "/"
schedule:
+18
View File
@@ -4,6 +4,7 @@ import {
renderError,
parseBoolean,
} from "../src/common/utils.js";
import { gistWhitelist } from "../src/common/whitelist.js";
import { isLocaleAvailable } from "../src/translations.js";
import { renderGistCard } from "../src/cards/gist.js";
import { fetchGist } from "../src/fetchers/gist.js";
@@ -27,6 +28,23 @@ export default async (req, res) => {
res.setHeader("Content-Type", "image/svg+xml");
if (gistWhitelist && !gistWhitelist.includes(id)) {
return res.send(
renderError(
"This gist ID is not whitelisted",
"Please deploy your own instance",
{
title_color,
text_color,
bg_color,
border_color,
theme,
show_repo_link: false,
},
),
);
}
if (locale && !isLocaleAvailable(locale)) {
return res.send(
renderError("Something went wrong", "Language not found", {
+31 -8
View File
@@ -1,5 +1,6 @@
import { renderStatsCard } from "../src/cards/stats.js";
import { blacklist } from "../src/common/blacklist.js";
import { whitelist } from "../src/common/whitelist.js";
import {
clampValue,
CONSTANTS,
@@ -45,15 +46,37 @@ export default async (req, res) => {
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
if (blacklist.includes(username)) {
if (whitelist && !whitelist.includes(username)) {
return res.send(
renderError("Something went wrong", "This username is blacklisted", {
title_color,
text_color,
bg_color,
border_color,
theme,
}),
renderError(
"This username is not whitelisted",
"Please deploy your own instance",
{
title_color,
text_color,
bg_color,
border_color,
theme,
show_repo_link: false,
},
),
);
}
if (whitelist === undefined && blacklist.includes(username)) {
return res.send(
renderError(
"This username is blacklisted",
"Please deploy your own instance",
{
title_color,
text_color,
bg_color,
border_color,
theme,
show_repo_link: false,
},
),
);
}
+31 -8
View File
@@ -1,5 +1,6 @@
import { renderRepoCard } from "../src/cards/repo.js";
import { blacklist } from "../src/common/blacklist.js";
import { whitelist } from "../src/common/whitelist.js";
import {
clampValue,
CONSTANTS,
@@ -37,15 +38,37 @@ export default async (req, res) => {
res.setHeader("Content-Type", "image/svg+xml");
if (blacklist.includes(username)) {
if (whitelist && !whitelist.includes(username)) {
return res.send(
renderError("Something went wrong", "This username is blacklisted", {
title_color,
text_color,
bg_color,
border_color,
theme,
}),
renderError(
"This username is not whitelisted",
"Please deploy your own instance",
{
title_color,
text_color,
bg_color,
border_color,
theme,
show_repo_link: false,
},
),
);
}
if (whitelist === undefined && blacklist.includes(username)) {
return res.send(
renderError(
"This username is blacklisted",
"Please deploy your own instance",
{
title_color,
text_color,
bg_color,
border_color,
theme,
show_repo_link: false,
},
),
);
}
+31 -8
View File
@@ -1,5 +1,6 @@
import { renderTopLanguages } from "../src/cards/top-languages.js";
import { blacklist } from "../src/common/blacklist.js";
import { whitelist } from "../src/common/whitelist.js";
import {
clampValue,
CONSTANTS,
@@ -38,15 +39,37 @@ export default async (req, res) => {
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
if (blacklist.includes(username)) {
if (whitelist && !whitelist.includes(username)) {
return res.send(
renderError("Something went wrong", "This username is blacklisted", {
title_color,
text_color,
bg_color,
border_color,
theme,
}),
renderError(
"This username is not whitelisted",
"Please deploy your own instance",
{
title_color,
text_color,
bg_color,
border_color,
theme,
show_repo_link: false,
},
),
);
}
if (whitelist === undefined && blacklist.includes(username)) {
return res.send(
renderError(
"This username is blacklisted",
"Please deploy your own instance",
{
title_color,
text_color,
bg_color,
border_color,
theme,
show_repo_link: false,
},
),
);
}
+18
View File
@@ -6,6 +6,7 @@ import {
parseBoolean,
renderError,
} from "../src/common/utils.js";
import { whitelist } from "../src/common/whitelist.js";
import { fetchWakatimeStats } from "../src/fetchers/wakatime.js";
import { isLocaleAvailable } from "../src/translations.js";
import { storeRequest } from "../src/common/database.js";
@@ -38,6 +39,23 @@ export default async (req, res) => {
res.setHeader("Content-Type", "image/svg+xml");
if (whitelist && !whitelist.includes(username)) {
return res.send(
renderError(
"This username is not whitelisted",
"Please deploy your own instance",
{
title_color,
text_color,
bg_color,
border_color,
theme,
show_repo_link: false,
},
),
);
}
if (locale && !isLocaleAvailable(locale)) {
return res.send(
renderError("Something went wrong", "Language not found", {
+83 -61
View File
@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"axios": "^1.11.0",
"axios": "^1.12.1",
"dotenv": "^17.2.2",
"emoji-name-map": "^2.0.3",
"github-username-regex": "^1.0.0",
@@ -29,8 +29,8 @@
"color-contrast-checker": "^2.1.0",
"eslint": "^9.35.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-jsdoc": "^54.5.0",
"globals": "^16.3.0",
"eslint-plugin-jsdoc": "^55.2.0",
"globals": "^16.4.0",
"hjson": "^3.2.2",
"husky": "^9.1.7",
"jest": "^29.7.0",
@@ -752,16 +752,16 @@
}
},
"node_modules/@es-joy/jsdoccomment": {
"version": "0.56.0",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.56.0.tgz",
"integrity": "sha512-c6EW+aA1w2rjqOMjbL93nZlwxp6c1Ln06vTYs5FjRRhmJXK8V/OrSXdT+pUr4aRYgjCgu8/OkiZr0tzeVrRSbw==",
"version": "0.57.0",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.57.0.tgz",
"integrity": "sha512-M4isJXgy+ZLXvt9EFLHuG5+6Q8hl1iSn3ZnO5R+DiPLUBvsTOh93fZ9X/X1z3l6/pmq3STZtqrEAi6SaPzB4AQ==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.8",
"@typescript-eslint/types": "^8.42.0",
"comment-parser": "1.4.1",
"esquery": "^1.6.0",
"jsdoc-type-pratt-parser": "~5.1.0"
"jsdoc-type-pratt-parser": "~5.2.0"
},
"engines": {
"node": ">=20.11.0"
@@ -2077,9 +2077,9 @@
"dev": true
},
"node_modules/@typescript-eslint/types": {
"version": "8.42.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.42.0.tgz",
"integrity": "sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw==",
"version": "8.43.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.43.0.tgz",
"integrity": "sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2224,9 +2224,9 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz",
"integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.4",
@@ -3096,18 +3096,19 @@
}
},
"node_modules/eslint-plugin-jsdoc": {
"version": "54.5.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-54.5.0.tgz",
"integrity": "sha512-f+AOXbKa9QtOrJr1lfEZ6ScSnS4Lun8czm+U9VNB39jq5mTUc1WQTXDOaESm0C5veSyuo3WBz2ge0Ah79Jzo7g==",
"version": "55.3.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-55.3.0.tgz",
"integrity": "sha512-oo8ByBStn+VO/mPRTkNOCORoJxCegmevFV6v70xf+7+KgCFCyP9ay67l/2420OU0zZUMWfq61BTIaXi+DjVVWQ==",
"dev": true,
"dependencies": {
"@es-joy/jsdoccomment": "~0.56.0",
"@es-joy/jsdoccomment": "~0.57.0",
"are-docs-informative": "^0.0.2",
"comment-parser": "1.4.1",
"debug": "^4.4.1",
"escape-string-regexp": "^4.0.0",
"espree": "^10.4.0",
"esquery": "^1.6.0",
"object-deep-merge": "^1.0.5",
"parse-imports-exports": "^0.2.4",
"semver": "^7.7.2",
"spdx-expression-parse": "^4.0.0"
@@ -3173,18 +3174,6 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint/node_modules/@eslint/js": {
"version": "9.34.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz",
"integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://eslint.org/donate"
}
},
"node_modules/eslint/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -3718,9 +3707,9 @@
}
},
"node_modules/globals": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz",
"integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==",
"version": "16.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
"integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
"dev": true,
"engines": {
"node": ">=18"
@@ -5281,9 +5270,9 @@
}
},
"node_modules/jsdoc-type-pratt-parser": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-5.1.1.tgz",
"integrity": "sha512-DYYlVP1fe4QBMh2xTIs20/YeTz2GYVbWAEZweHSZD+qQ/Cx2d5RShuhhsdk64eTjNq0FeVnteP/qVOgaywSRbg==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-5.2.0.tgz",
"integrity": "sha512-qJmErzgL4DLj4lyRkDWnEXZRNu3X3CJxVKKhuUPwqPFMiJV6K7/6O//D2Uf+rRi6+qTPgHWxDAgfGllEXoGkMA==",
"dev": true,
"engines": {
"node": ">=12.0.0"
@@ -5990,6 +5979,27 @@
"integrity": "sha512-o6nIY3qwiSXl7/LuOU0Dmuctd34Yay0yeuZRLFmDPrrdHpXKFndPj3hM+YEPVHYC5fx2otBx4Ilc/gyYSAUaIA==",
"dev": true
},
"node_modules/object-deep-merge": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-1.0.5.tgz",
"integrity": "sha512-3DioFgOzetbxbeUq8pB2NunXo8V0n4EvqsWM/cJoI6IA9zghd7cl/2pBOuWRf4dlvA+fcg5ugFMZaN2/RuoaGg==",
"dev": true,
"dependencies": {
"type-fest": "4.2.0"
}
},
"node_modules/object-deep-merge/node_modules/type-fest": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.2.0.tgz",
"integrity": "sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w==",
"dev": true,
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -7863,16 +7873,16 @@
"dev": true
},
"@es-joy/jsdoccomment": {
"version": "0.56.0",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.56.0.tgz",
"integrity": "sha512-c6EW+aA1w2rjqOMjbL93nZlwxp6c1Ln06vTYs5FjRRhmJXK8V/OrSXdT+pUr4aRYgjCgu8/OkiZr0tzeVrRSbw==",
"version": "0.57.0",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.57.0.tgz",
"integrity": "sha512-M4isJXgy+ZLXvt9EFLHuG5+6Q8hl1iSn3ZnO5R+DiPLUBvsTOh93fZ9X/X1z3l6/pmq3STZtqrEAi6SaPzB4AQ==",
"dev": true,
"requires": {
"@types/estree": "^1.0.8",
"@typescript-eslint/types": "^8.42.0",
"comment-parser": "1.4.1",
"esquery": "^1.6.0",
"jsdoc-type-pratt-parser": "~5.1.0"
"jsdoc-type-pratt-parser": "~5.2.0"
}
},
"@eslint-community/eslint-utils": {
@@ -8911,9 +8921,9 @@
"dev": true
},
"@typescript-eslint/types": {
"version": "8.42.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.42.0.tgz",
"integrity": "sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw==",
"version": "8.43.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.43.0.tgz",
"integrity": "sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==",
"dev": true
},
"@uppercod/css-to-object": {
@@ -9014,9 +9024,9 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz",
"integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==",
"requires": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.4",
@@ -9625,12 +9635,6 @@
"optionator": "^0.9.3"
},
"dependencies": {
"@eslint/js": {
"version": "9.34.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz",
"integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==",
"dev": true
},
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -9720,18 +9724,19 @@
"requires": {}
},
"eslint-plugin-jsdoc": {
"version": "54.5.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-54.5.0.tgz",
"integrity": "sha512-f+AOXbKa9QtOrJr1lfEZ6ScSnS4Lun8czm+U9VNB39jq5mTUc1WQTXDOaESm0C5veSyuo3WBz2ge0Ah79Jzo7g==",
"version": "55.3.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-55.3.0.tgz",
"integrity": "sha512-oo8ByBStn+VO/mPRTkNOCORoJxCegmevFV6v70xf+7+KgCFCyP9ay67l/2420OU0zZUMWfq61BTIaXi+DjVVWQ==",
"dev": true,
"requires": {
"@es-joy/jsdoccomment": "~0.56.0",
"@es-joy/jsdoccomment": "~0.57.0",
"are-docs-informative": "^0.0.2",
"comment-parser": "1.4.1",
"debug": "^4.4.1",
"escape-string-regexp": "^4.0.0",
"espree": "^10.4.0",
"esquery": "^1.6.0",
"object-deep-merge": "^1.0.5",
"parse-imports-exports": "^0.2.4",
"semver": "^7.7.2",
"spdx-expression-parse": "^4.0.0"
@@ -10055,9 +10060,9 @@
}
},
"globals": {
"version": "16.3.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz",
"integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==",
"version": "16.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
"integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
"dev": true
},
"gopd": {
@@ -11214,9 +11219,9 @@
}
},
"jsdoc-type-pratt-parser": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-5.1.1.tgz",
"integrity": "sha512-DYYlVP1fe4QBMh2xTIs20/YeTz2GYVbWAEZweHSZD+qQ/Cx2d5RShuhhsdk64eTjNq0FeVnteP/qVOgaywSRbg==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-5.2.0.tgz",
"integrity": "sha512-qJmErzgL4DLj4lyRkDWnEXZRNu3X3CJxVKKhuUPwqPFMiJV6K7/6O//D2Uf+rRi6+qTPgHWxDAgfGllEXoGkMA==",
"dev": true
},
"jsdom": {
@@ -11722,6 +11727,23 @@
"integrity": "sha512-o6nIY3qwiSXl7/LuOU0Dmuctd34Yay0yeuZRLFmDPrrdHpXKFndPj3hM+YEPVHYC5fx2otBx4Ilc/gyYSAUaIA==",
"dev": true
},
"object-deep-merge": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-1.0.5.tgz",
"integrity": "sha512-3DioFgOzetbxbeUq8pB2NunXo8V0n4EvqsWM/cJoI6IA9zghd7cl/2pBOuWRf4dlvA+fcg5ugFMZaN2/RuoaGg==",
"dev": true,
"requires": {
"type-fest": "4.2.0"
},
"dependencies": {
"type-fest": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.2.0.tgz",
"integrity": "sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w==",
"dev": true
}
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+3 -3
View File
@@ -47,8 +47,8 @@
"color-contrast-checker": "^2.1.0",
"eslint": "^9.35.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-jsdoc": "^54.5.0",
"globals": "^16.3.0",
"eslint-plugin-jsdoc": "^55.2.0",
"globals": "^16.4.0",
"hjson": "^3.2.2",
"husky": "^9.1.7",
"jest": "^29.7.0",
@@ -61,7 +61,7 @@
"prettier": "^3.6.2"
},
"dependencies": {
"axios": "^1.11.0",
"axios": "^1.12.1",
"dotenv": "^17.2.2",
"emoji-name-map": "^2.0.3",
"github-username-regex": "^1.0.0",
+11 -6
View File
@@ -87,7 +87,7 @@
- [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)
- [Available environment variables](#available-environment-variables)
- [Keep your fork up to date](#keep-your-fork-up-to-date)
- [:sparkling\_heart: Support the project](#sparkling_heart-support-the-project)
</details>
@@ -308,6 +308,7 @@ Here is a list of all available locales:
| `es` | Spanish |
| `fr` | French |
| `hu` | Hungarian |
| `fi` | Finnish |
</td><td>
@@ -323,6 +324,7 @@ Here is a list of all available locales:
| `el` | Greek |
| `ru` | Russian |
| `uk-ua` | Ukrainian |
| `ro` | Romanian |
</td><td>
@@ -337,6 +339,7 @@ Here is a list of all available locales:
| `uz` | Uzbek |
| `vi` | Vietnamese |
| `se` | Swedish |
| `az` | Azerbaijani |
</td></tr>
</table>
@@ -671,7 +674,7 @@ You can customize the appearance and behavior of the WakaTime stats card using t
![Anurag's GitHub stats](https://github-readme-stats-phi-jet-58.vercel.app/api?username=anuraghazra\&hide=issues\&show_icons=true)
* Shows Github logo instead rank level
* Shows GitHub logo instead rank level
![Anurag's GitHub stats](https://github-readme-stats-phi-jet-58.vercel.app/api?username=anuraghazra\&rank_icon=github)
@@ -832,11 +835,13 @@ Since the GitHub API only allows 5k requests per hour, my `https://github-readme
5. You're done 🎉
</details>
## Disable rate limit protections
## Available environment variables
Github Readme Stats contains several Vercel environment variables that can be used to remove the rate limit protections:
GitHub Readme Stats provides several environment variables that can be used to customize the behavior of your self-hosted instance. These include:
* `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 takes precedence over our cache minimum and maximum values and can circumvent these values for self-hosted instances.
* `WHITELIST`: A comma-separated list of GitHub usernames that are allowed to access your instance. If this variable is not set, all usernames are allowed.
* `GIST_WHITELIST`: A comma-separated list of GitHub gist IDs that are allowed to be accessed on your instance. If this variable is not set, all gist IDs are allowed.
See [the Vercel documentation](https://vercel.com/docs/concepts/projects/environment-variables) on adding these environment variables to your Vercel instance.
@@ -853,7 +858,7 @@ However, if you are using this project and are happy with it or just want to enc
* 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 a one-time donations via PayPal. I'll probably buy a ~~coffee~~ tea. :tea:
* [![paypal.me/anuraghazra](https://ionicabizau.github.io/badges/paypal.svg)](https://www.paypal.me/anuraghazra) - You can make a one-time donation via PayPal. I'll probably buy a ~~coffee~~ tea. :tea:
Thanks! :heart:
+1 -3
View File
@@ -276,9 +276,7 @@ const renderStatsCard = (
theme,
});
const apostrophe = ["x", "s"].includes(name.slice(-1).toLocaleLowerCase())
? ""
: "s";
const apostrophe = /s$/i.test(name.trim()) ? "" : "s";
const i18n = new I18n({
locale,
translations: statCardLocales({ name, apostrophe }),
+8 -1
View File
@@ -373,6 +373,12 @@ const UPSTREAM_API_ERRORS = [
* @param {string} message Main error message.
* @param {string} secondaryMessage The secondary error message.
* @param {object} options Function options.
* @param {string=} options.title_color Card title color.
* @param {string=} options.text_color Card text color.
* @param {string=} options.bg_color Card background color.
* @param {string=} options.border_color Card border color.
* @param {string=} options.theme Card theme.
* @param {boolean=} options.show_repo_link Whether to show repo link or not.
* @returns {string} The SVG markup.
*/
const renderError = (message, secondaryMessage = "", options = {}) => {
@@ -382,6 +388,7 @@ const renderError = (message, secondaryMessage = "", options = {}) => {
bg_color,
border_color,
theme = "default",
show_repo_link = true,
} = options;
// returns theme based colors with proper overrides and defaults
@@ -406,7 +413,7 @@ const renderError = (message, secondaryMessage = "", options = {}) => {
ERROR_CARD_LENGTH - 1
}" height="99%" rx="4.5" fill="${bgColor}" stroke="${borderColor}"/>
<text x="25" y="45" class="text">Something went wrong!${
UPSTREAM_API_ERRORS.includes(secondaryMessage)
UPSTREAM_API_ERRORS.includes(secondaryMessage) || !show_repo_link
? ""
: " file an issue at https://tiny.one/readme-stats"
}</text>
+10
View File
@@ -0,0 +1,10 @@
const whitelist = process.env.WHITELIST
? process.env.WHITELIST.split(",")
: undefined;
const gistWhitelist = process.env.GIST_WHITELIST
? process.env.GIST_WHITELIST.split(",")
: undefined;
export { whitelist, gistWhitelist };
export default whitelist;
+1 -1
View File
@@ -83,7 +83,7 @@ const calculatePrimaryLanguage = (files) => {
/**
* Fetch GitHub gist information by given username and ID.
*
* @param {string} id Github gist ID.
* @param {string} id GitHub gist ID.
* @returns {Promise<GistData>} Gist data.
*/
const fetchGist = async (id) => {
+1 -1
View File
@@ -107,7 +107,7 @@ const fetcher = (variables, token) => {
* Fetch stats information for a given username.
*
* @param {object} variables Fetcher variables.
* @param {string} variables.username Github username.
* @param {string} variables.username GitHub username.
* @param {boolean} variables.includeMergedPullRequests Include merged pull requests.
* @param {boolean} variables.includeDiscussions Include discussions.
* @param {boolean} variables.includeDiscussionsAnswers Include discussions answers.
+118 -52
View File
@@ -16,14 +16,16 @@ const statCardLocales = ({ name, apostrophe }) => {
const encodedName = encodeHTML(name);
return {
"statcard.title": {
ar: `${encodedName} إحصائيات غيت هاب`,
ar: `${encodedName} إحصائيات جيت هاب`,
az: `${encodedName}'${apostrophe} Hesabının GitHub Statistikası`,
cn: `${encodedName} 的 GitHub 统计数据`,
"zh-tw": `${encodedName} 的 GitHub 統計數據`,
"zh-tw": `${encodedName} 的 GitHub 統計資料`,
cs: `GitHub statistiky uživatele ${encodedName}`,
de: `${encodedName + apostrophe} GitHub-Statistiken`,
en: `${encodedName}'${apostrophe} GitHub Stats`,
bn: `${encodedName} এর GitHub পরিসংখ্যান`,
es: `Estadísticas de GitHub de ${encodedName}`,
fi: `${encodedName}:n GitHub-tilastot`,
fr: `Statistiques GitHub de ${encodedName}`,
hu: `${encodedName} GitHub statisztika`,
it: `Statistiche GitHub di ${encodedName}`,
@@ -34,27 +36,30 @@ const statCardLocales = ({ name, apostrophe }) => {
"pt-br": `Estatísticas do GitHub de ${encodedName}`,
np: `${encodedName}'${apostrophe} गिटहब तथ्याङ्क`,
el: `Στατιστικά GitHub του ${encodedName}`,
ro: `Statisticile GitHub ale lui ${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ı`,
tr: `${encodedName} Hesabının GitHub İstatistikleri`,
pl: `Statystyki GitHub użytkownika ${encodedName}`,
uz: `${encodedName}ning GitHub'dagi statistikasi`,
vi: `Thống Kê GitHub ${encodedName}`,
se: `GitHubstatistik för ${encodedName}`,
},
"statcard.ranktitle": {
ar: `${encodedName} إحصائيات غيت هاب`,
ar: `${encodedName} إحصائيات جيت هاب`,
az: `${encodedName}'${apostrophe} Hesabının GitHub Statistikası`,
cn: `${encodedName} 的 GitHub 统计数据`,
"zh-tw": `${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}`,
fi: `${encodedName}:n GitHub-sijoitus`,
fr: `Statistiques GitHub de ${encodedName}`,
hu: `${encodedName} GitHub statisztika`,
it: `Statistiche GitHub di ${encodedName}`,
@@ -65,7 +70,8 @@ const statCardLocales = ({ name, apostrophe }) => {
"pt-br": `Estatísticas do GitHub de ${encodedName}`,
np: `${encodedName}'${apostrophe} गिटहब तथ्याङ्क`,
el: `Στατιστικά GitHub του ${encodedName}`,
ru: `Статистика GitHub пользователя ${encodedName}`,
ro: `Rankul GitHub al lui ${encodedName}`,
ru: `Рейтинг GitHub пользователя ${encodedName}`,
"uk-ua": `Статистика GitHub користувача ${encodedName}`,
id: `Statistik GitHub ${encodedName}`,
ml: `${encodedName}'${apostrophe} ഗിറ്റ്ഹബ് സ്ഥിതിവിവരക്കണക്കുകൾ`,
@@ -79,13 +85,15 @@ const statCardLocales = ({ name, apostrophe }) => {
},
"statcard.totalstars": {
ar: "مجموع النجوم",
cn: "获标星数(star",
"zh-tw": "獲標星數(star",
az: "Ümumi Ulduz",
cn: "获标星数",
"zh-tw": "得標星星數量(Star",
cs: "Celkem hvězd",
de: "Insgesamt erhaltene Sterne",
en: "Total Stars Earned",
bn: "সর্বমোট Star",
es: "Estrellas totales",
fi: "Ansaitut tähdet yhteensä",
fr: "Total d'étoiles",
hu: "Csillagok",
it: "Stelle totali",
@@ -96,7 +104,8 @@ const statCardLocales = ({ name, apostrophe }) => {
"pt-br": "Total de estrelas",
np: "कुल ताराहरू",
el: "Σύνολο Αστεριών",
ru: "Всего звезд",
ro: "Total de stele câștigate",
ru: "Всего звёзд",
"uk-ua": "Всього зірок",
id: "Total Bintang",
ml: "ആകെ നക്ഷത്രങ്ങൾ",
@@ -109,14 +118,16 @@ const statCardLocales = ({ name, apostrophe }) => {
se: "Antal intjänade stjärnor",
},
"statcard.commits": {
ar: "مجموع الحفظ",
cn: "累计提交数(commit",
"zh-tw": "累提交數(commit",
ar: "مجموع المساهمات",
az: "Ümumi Commit",
cn: "累提交总数",
"zh-tw": "累計提交數量(Commit",
cs: "Celkem commitů",
de: "Anzahl Commits",
en: "Total Commits",
bn: "সর্বমোট Commit",
es: "Commits totales",
fi: "Yhteensä committeja",
fr: "Total des Commits",
hu: "Összes commit",
it: "Commit totali",
@@ -127,6 +138,7 @@ const statCardLocales = ({ name, apostrophe }) => {
"pt-br": "Total de Commits",
np: "कुल Commits",
el: "Σύνολο Commits",
ro: "Total Commit-uri",
ru: "Всего коммитов",
"uk-ua": "Всього комітів",
id: "Total Komitmen",
@@ -141,13 +153,15 @@ const statCardLocales = ({ name, apostrophe }) => {
},
"statcard.prs": {
ar: "مجموع طلبات السحب",
cn: "拉取请求数(PR",
"zh-tw": "拉取請求數(PR",
az: "Ümumi PR",
cn: "发起的 PR 总数",
"zh-tw": "拉取請求數量(PR",
cs: "Celkem PRs",
de: "PRs Insgesamt",
en: "Total PRs",
bn: "সর্বমোট PR",
es: "PRs totales",
fi: "Yhteensä PR:t",
fr: "Total des PRs",
hu: "Összes PR",
it: "PR totali",
@@ -158,7 +172,8 @@ const statCardLocales = ({ name, apostrophe }) => {
"pt-br": "Total de PRs",
np: "कुल PRs",
el: "Σύνολο PRs",
ru: "Всего pull request`ов",
ro: "Total PR-uri",
ru: "Всего запросов изменений",
"uk-ua": "Всього pull request`iв",
id: "Total Permintaan Tarik",
ml: "ആകെ പുൾ അഭ്യർത്ഥനകൾ",
@@ -172,13 +187,15 @@ const statCardLocales = ({ name, apostrophe }) => {
},
"statcard.issues": {
ar: "مجموع التحسينات",
cn: "指出问题数(issue",
"zh-tw": "指出問題數(issue",
az: "Ümumi Problem",
cn: "提出的 issue 总数",
"zh-tw": "提出問題數量(Issue",
cs: "Celkem problémů",
de: "Anzahl Issues",
en: "Total Issues",
bn: "সর্বমোট Issue",
es: "Issues totales",
fi: "Yhteensä ongelmat",
fr: "Nombre total d'incidents",
hu: "Összes hibajegy",
it: "Segnalazioni totali",
@@ -189,7 +206,8 @@ const statCardLocales = ({ name, apostrophe }) => {
"pt-br": "Total de Issues",
np: "कुल मुद्दाहरू",
el: "Σύνολο Ζητημάτων",
ru: "Всего issue",
ro: "Total Issue-uri",
ru: "Всего вопросов",
"uk-ua": "Всього issue",
id: "Total Masalah Dilaporkan",
ml: "ആകെ ലക്കങ്ങൾ",
@@ -203,13 +221,15 @@ const statCardLocales = ({ name, apostrophe }) => {
},
"statcard.contribs": {
ar: "ساهم في (العام الماضي)",
cn: "贡献于(去年)",
"zh-tw": "參與項目數 (去年)",
az: "Töhfə verdi (ötən il)",
cn: "贡献的项目数(去年)",
"zh-tw": "參與項目數量(去年)",
cs: "Přispěl k (minulý rok)",
de: "Beigetragen zu (letztes Jahr)",
en: "Contributed to (last year)",
bn: "অবদান (গত বছর)",
es: "Contribuciones en (el año pasado)",
fi: "Osallistunut (viime vuonna)",
fr: "Contribué à (l'année dernière)",
hu: "Hozzájárulások (tavaly)",
it: "Ha contribuito a (l'anno scorso)",
@@ -220,7 +240,8 @@ const statCardLocales = ({ name, apostrophe }) => {
"pt-br": "Contribuiu para (ano passado)",
np: "कुल योगदानहरू (गत वर्ष)",
el: "Συνεισφέρθηκε σε (πέρυσι)",
ru: "Внёс вклад в (за прошлый год)",
ro: "Total Contribuiri",
ru: "Внесено вклада (за прошлый год)",
"uk-ua": "Зробив внесок у (за минулий рік)",
id: "Berkontribusi ke (tahun lalu)",
ml: "സമർപ്പിച്ചിരിക്കുന്നത് (കഴിഞ്ഞ വർഷം)",
@@ -233,14 +254,16 @@ const statCardLocales = ({ name, apostrophe }) => {
se: "Bidragit till (förra året)",
},
"statcard.reviews": {
ar: "تمت مراجعة إجمالي العلاقات العامة",
cn: "審查的 PR 總數",
"zh-tw": "审查的 PR 总数",
ar: "طلبات السحب التي تم مراجعتها",
az: "Nəzərdən Keçirilən Ümumi PR",
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",
fi: "Yhteensä tarkastettuja PR:itä",
fr: "Nombre total de PR examinés",
hu: "Összes ellenőrzött PR",
it: "PR totali esaminati",
@@ -251,7 +274,8 @@ const statCardLocales = ({ name, apostrophe }) => {
"pt-br": "Total de PRs revisados",
np: "कुल पीआर समीक्षित",
el: "Σύνολο Αναθεωρημένων PR",
ru: "Всего pull request`ов проверено",
ro: "Total PR-uri Revizuite",
ru: "Всего запросов проверено",
"uk-ua": "Всього pull request`iв перевірено",
id: "Total PR yang Direview",
ml: "ആകെ പുൾ അഭിപ്രായങ്ങൾ",
@@ -264,7 +288,8 @@ const statCardLocales = ({ name, apostrophe }) => {
se: "Totalt antal granskade PR",
},
"statcard.discussions-started": {
ar: "مجموع بدء المناقشات",
ar: "مجموع المناقشات التي بدأها",
az: "Başladılan Ümumi Müzakirə",
cn: "发起的讨论总数",
"zh-tw": "發起的討論總數",
cs: "Celkem zahájených diskusí",
@@ -272,6 +297,7 @@ const statCardLocales = ({ name, apostrophe }) => {
en: "Total Discussions Started",
bn: "সর্বমোট আলোচনা শুরু",
es: "Discusiones totales iniciadas",
fi: "Aloitetut keskustelut yhteensä",
fr: "Nombre total de discussions lancées",
hu: "Összes megkezdett megbeszélés",
it: "Discussioni totali avviate",
@@ -282,7 +308,8 @@ const statCardLocales = ({ name, apostrophe }) => {
"pt-br": "Total de Discussões Iniciadas",
np: "कुल चर्चा सुरु",
el: "Σύνολο Συζητήσεων που Ξεκίνησαν",
ru: "Всего начатых дискуссий",
ro: "Total Discuții Începute",
ru: "Всего начатых обсуждений",
"uk-ua": "Всього розпочатих дискусій",
id: "Total Diskusi Dimulai",
ml: "ആരംഭിച്ച ആലോചനകൾ",
@@ -295,14 +322,16 @@ const statCardLocales = ({ name, apostrophe }) => {
se: "Totalt antal diskussioner startade",
},
"statcard.discussions-answered": {
ar: "مجموع الردود على المناقشات",
ar: "مجموع المناقشات المُجابة",
az: "Cavablandırılan Ümumi Müzakirə",
cn: "回复的讨论总数",
"zh-tw": "回覆討論總",
"zh-tw": "回覆討論總",
cs: "Celkem zodpovězených diskusí",
de: "Gesamt beantwortete Diskussionen",
en: "Total Discussions Answered",
bn: "সর্বমোট আলোচনা উত্তর",
es: "Discusiones totales respondidas",
fi: "Vastatut keskustelut yhteensä",
fr: "Nombre total de discussions répondues",
hu: "Összes megválaszolt megbeszélés",
it: "Discussioni totali risposte",
@@ -313,7 +342,8 @@ const statCardLocales = ({ name, apostrophe }) => {
"pt-br": "Total de Discussões Respondidas",
np: "कुल चर्चा उत्तर",
el: "Σύνολο Συζητήσεων που Απαντήθηκαν",
ru: "Всего отвеченных дискуссий",
ro: "Total Răspunsuri La Discuții",
ru: "Всего отвеченных обсуждений",
"uk-ua": "Всього відповідей на дискусії",
id: "Total Diskusi Dibalas",
ml: "ഉത്തരം നൽകിയ ആലോചനകൾ",
@@ -341,14 +371,16 @@ const statCardLocales = ({ name, apostrophe }) => {
en: "Issues Commented",
},
"statcard.prs-merged": {
ar: "مجموع الطلبات المدمجة",
ar: "مجموع طلبات السحب المُدمجة",
az: "Birləşdirilmiş Ümumi PR",
cn: "合并的 PR 总数",
"zh-tw": "合併的 PR 總",
"zh-tw": "合併的 PR 總",
cs: "Celkem sloučených PR",
de: "Insgesamt zusammengeführte PRs",
en: "Total PRs Merged",
bn: "সর্বমোট PR একত্রীকৃত",
es: "PR totales fusionados",
fi: "Yhteensä yhdistetyt PR:t",
fr: "Nombre total de PR fusionnés",
hu: "Összes egyesített PR",
it: "PR totali uniti",
@@ -356,10 +388,11 @@ const statCardLocales = ({ name, apostrophe }) => {
kr: "병합된 총 PR",
nl: "Totaal samengevoegde PR's",
"pt-pt": "Total de PRs Fundidos",
"pt-br": "Total de PRs Fundidos",
"pt-br": "Total de PRs Integrados",
np: "कुल PRs मर्ज गरिएको",
el: "Σύνολο Συγχωνευμένων PR",
ru: "Всего объединённых pull request`ов",
ro: "Total PR-uri Fuzionate",
ru: "Всего объединённых запросов",
"uk-ua": "Всього об'єднаних pull request`iв",
id: "Total PR Digabungkan",
my: "Jumlah PR Digabungkan",
@@ -371,14 +404,16 @@ const statCardLocales = ({ name, apostrophe }) => {
se: "Totalt antal sammanfogade PR",
},
"statcard.prs-merged-percentage": {
ar: "نسبة الطلبات المدمجة",
cn: "合并的 PR 百分比",
ar: "نسبة طلبات السحب المُدمجة",
az: "Birləşdirilmiş PR-ların Faizi",
cn: "被合并的 PR 占比",
"zh-tw": "合併的 PR 百分比",
cs: "Sloučené PRs v procentech",
de: "Zusammengeführte PRs in Prozent",
en: "Merged PRs Percentage",
bn: "PR একত্রীকরণের শতাংশ",
es: "Porcentaje de PR fusionados",
fi: "Yhdistettyjen PR:ien prosentti",
fr: "Pourcentage de PR fusionnés",
hu: "Egyesített PR-k százaléka",
it: "Percentuale di PR uniti",
@@ -386,10 +421,11 @@ const statCardLocales = ({ name, apostrophe }) => {
kr: "병합된 PR의 비율",
nl: "Percentage samengevoegde PR's",
"pt-pt": "Percentagem de PRs Fundidos",
"pt-br": "Porcentagem de PRs Fundidos",
"pt-br": "Porcentagem de PRs Integrados",
np: "PR मर्ज गरिएको प्रतिशत",
el: "Ποσοστό Συγχωνευμένων PR",
ru: "Процент объединённых pull request`ов",
ro: "Procentaj PR-uri Fuzionate",
ru: "Процент объединённых запросов",
"uk-ua": "Відсоток об'єднаних pull request`iв",
id: "Persentase PR Digabungkan",
my: "Peratus PR Digabungkan",
@@ -406,6 +442,7 @@ const statCardLocales = ({ name, apostrophe }) => {
const repoCardLocales = {
"repocard.template": {
ar: "قالب",
az: "Şablon",
bn: "টেমপ্লেট",
cn: "模板",
"zh-tw": "模板",
@@ -413,6 +450,7 @@ const repoCardLocales = {
de: "Vorlage",
en: "Template",
es: "Plantilla",
fi: "Malli",
fr: "Modèle",
hu: "Sablon",
it: "Template",
@@ -423,6 +461,7 @@ const repoCardLocales = {
"pt-br": "Modelo",
np: "टेम्पलेट",
el: "Πρότυπο",
ro: "Șablon",
ru: "Шаблон",
"uk-ua": "Шаблон",
id: "Pola",
@@ -436,14 +475,16 @@ const repoCardLocales = {
se: "Mall",
},
"repocard.archived": {
ar: حفوظ",
ar: ُؤرشف",
az: "Arxiv",
bn: "আর্কাইভড",
cn: "已归档",
"zh-tw": "已歸檔",
"zh-tw": "已封存",
cs: "Archivováno",
de: "Archiviert",
en: "Archived",
es: "Archivados",
fi: "Arkistoitu",
fr: "Archivé",
hu: "Archivált",
it: "Archiviata",
@@ -454,6 +495,7 @@ const repoCardLocales = {
"pt-br": "Arquivados",
np: "अभिलेख राखियो",
el: "Αρχειοθετημένα",
ro: "Arhivat",
ru: "Архивирован",
"uk-ua": "Архивований",
id: "Arsip",
@@ -485,7 +527,8 @@ const repoCardLocales = {
const langCardLocales = {
"langcard.title": {
ar: "أكثر اللغات إستخداماً",
ar: "أكثر اللغات استخدامًا",
az: "Ən Çox İstifadə Olunan Dillər",
cn: "最常用的语言",
"zh-tw": "最常用的語言",
cs: "Nejpoužívanější jazyky",
@@ -493,17 +536,19 @@ const langCardLocales = {
bn: "সর্বাধিক ব্যবহৃত ভাষা সমূহ",
en: "Most Used Languages",
es: "Lenguajes más usados",
fi: "Käytetyimmät kielet",
fr: "Langages les plus utilisés",
hu: "Leggyakrabban használt nyelvek",
it: "Linguaggi più utilizzati",
ja: "最もよく使っている言語",
kr: "가장 많이 사용된 언어",
nl: "Meest gebruikte talen",
"pt-pt": "Idiomas mais usados",
"pt-pt": "Linguagens mais usadas",
"pt-br": "Linguagens mais usadas",
np: "अधिक प्रयोग गरिएको भाषाहरू",
el: "Οι περισσότερο χρησιμοποιούμενες γλώσσες",
ru: "Наиболее часто используемые языки",
ro: "Cele Mai Folosite Limbaje",
ru: "Наиболее используемые языки",
"uk-ua": "Найчастіше використовувані мови",
id: "Bahasa Yang Paling Banyak Digunakan",
ml: "കൂടുതൽ ഉപയോഗിച്ച ഭാഷകൾ",
@@ -516,24 +561,27 @@ const langCardLocales = {
se: "Mest använda språken",
},
"langcard.nodata": {
ar: "لا توجد بيانات لغات.",
cn: "沒有語言數據。",
"zh-tw": "沒有語言數據。",
ar: "لا توجد بيانات للغات.",
az: "Dil məlumatı yoxdur.",
cn: "没有语言数据。",
"zh-tw": "沒有語言資料。",
cs: "Žádné jazykové údaje.",
de: "Keine Sprachdaten.",
bn: "কোন ভাষার ডেটা নেই।",
en: "No languages data.",
es: "Sin datos de idiomas.",
fi: "Ei kielitietoja.",
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.",
"pt-pt": "Sem dados de linguagens.",
"pt-br": "Sem dados de linguagens.",
np: "कुनै भाषा डाटा छैन।",
el: "Δεν υπάρχουν δεδομένα γλωσσών.",
ro: "Lipsesc date despre limbă.",
ru: "Нет данных о языках.",
"uk-ua": "Немає даних про мови.",
id: "Tidak ada data bahasa.",
@@ -551,6 +599,7 @@ const langCardLocales = {
const wakatimeCardLocales = {
"wakatimecard.title": {
ar: "إحصائيات واكا تايم",
az: "WakaTime Statistikası",
cn: "WakaTime 周统计",
"zh-tw": "WakaTime 周統計",
cs: "Statistiky WakaTime",
@@ -558,6 +607,7 @@ const wakatimeCardLocales = {
en: "WakaTime Stats",
bn: "WakaTime স্ট্যাটাস",
es: "Estadísticas de WakaTime",
fi: "WakaTime-tilastot",
fr: "Statistiques de WakaTime",
hu: "WakaTime statisztika",
it: "Statistiche WakaTime",
@@ -568,6 +618,7 @@ const wakatimeCardLocales = {
"pt-br": "Estatísticas WakaTime",
np: "WakaTime तथ्या .्क",
el: "Στατιστικά WakaTime",
ro: "Statistici WakaTime",
ru: "Статистика WakaTime",
"uk-ua": "Статистика WakaTime",
id: "Status WakaTime",
@@ -582,6 +633,7 @@ const wakatimeCardLocales = {
},
"wakatimecard.lastyear": {
ar: "العام الماضي",
az: "Ötən il",
cn: "去年",
"zh-tw": "去年",
cs: "Minulý rok",
@@ -589,6 +641,7 @@ const wakatimeCardLocales = {
en: "last year",
bn: "গত বছর",
es: "El año pasado",
fi: "Viime vuosi",
fr: "L'année dernière",
hu: "Tavaly",
it: "L'anno scorso",
@@ -599,6 +652,7 @@ const wakatimeCardLocales = {
"pt-br": "Ano passado",
np: "गत वर्ष",
el: "Πέρυσι",
ro: "Anul trecut",
ru: "За прошлый год",
"uk-ua": "За минулий рік",
id: "Tahun lalu",
@@ -613,6 +667,7 @@ const wakatimeCardLocales = {
},
"wakatimecard.last7days": {
ar: "آخر 7 أيام",
az: "Son 7 gün",
cn: "最近 7 天",
"zh-tw": "最近 7 天",
cs: "Posledních 7 dní",
@@ -620,6 +675,7 @@ const wakatimeCardLocales = {
en: "last 7 days",
bn: "গত দিন",
es: "Últimos 7 días",
fi: "Viimeiset 7 päivää",
fr: "7 derniers jours",
hu: "Elmúlt 7 nap",
it: "Ultimi 7 giorni",
@@ -630,6 +686,7 @@ const wakatimeCardLocales = {
"pt-br": "Últimos 7 dias",
np: "गत ७ दिन",
el: "Τελευταίες 7 ημέρες",
ro: "Ultimele 7 zile",
ru: "Последние 7 дней",
"uk-ua": "Останні 7 днів",
id: "7 hari terakhir",
@@ -643,7 +700,8 @@ const wakatimeCardLocales = {
se: "Senaste 7 dagarna",
},
"wakatimecard.notpublic": {
ar: "ملف المستخدم غير عام",
ar: "ملف مستخدم واكا تايم شخصي",
az: "WakaTime istifadəçi profili ictimai deyil",
cn: "WakaTime 用户个人资料未公开",
"zh-tw": "WakaTime 使用者個人資料未公開",
cs: "Profil uživatele WakaTime není veřejný",
@@ -651,17 +709,19 @@ const wakatimeCardLocales = {
en: "WakaTime user profile not public",
bn: "WakaTime ব্যবহারকারীর প্রোফাইল প্রকাশ্য নয়",
es: "Perfil de usuario de WakaTime no público",
fi: "WakaTime-käyttäjäprofiili ei ole julkinen",
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-pt": "Perfil de utilizador WakaTime não público",
"pt-br": "Perfil de usuário WakaTime não público",
np: "WakaTime प्रयोगकर्ता प्रोफाइल सार्वजनिक छैन",
el: "Το προφίλ χρήστη WakaTime δεν είναι δημόσιο",
ru: "Профиль пользователя WakaTime не является общедоступным",
ro: "Profilul utilizatorului de Wakatime nu este public",
ru: "Профиль пользователя WakaTime не общедоступный",
"uk-ua": "Профіль користувача WakaTime не є публічним",
id: "Profil pengguna WakaTime tidak publik",
ml: "WakaTime ഉപയോക്തൃ പ്രൊഫൈൽ പൊതുവായി പ്രസിദ്ധീകരിക്കപ്പെടാത്തതാണ്",
@@ -674,7 +734,8 @@ const wakatimeCardLocales = {
se: "WakaTime användarprofil inte offentlig",
},
"wakatimecard.nocodedetails": {
ar: "المستخدم لا يشارك معلومات تفصيلية عن البرمجة",
ar: "المستخدم لا يشارك المعلومات التفصيلية",
az: "İstifadəçi kod statistikalarını ictimai şəkildə paylaşmır",
cn: "用户不公开分享详细的代码统计信息",
"zh-tw": "使用者不公開分享詳細的程式碼統計資訊",
cs: "Uživatel nesdílí podrobné statistiky kódu",
@@ -682,6 +743,7 @@ const wakatimeCardLocales = {
en: "User doesn't publicly share detailed code statistics",
bn: "ব্যবহারকারী বিস্তারিত কোড পরিসংখ্যান প্রকাশ করেন না",
es: "El usuario no comparte públicamente estadísticas detalladas de código",
fi: "Käyttäjä ei jaa julkisesti tarkkoja kooditilastoja",
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",
@@ -694,6 +756,7 @@ const wakatimeCardLocales = {
"O usuário não compartilha publicamente estatísticas detalhadas de código",
np: "प्रयोगकर्ता सार्वजनिक रूपमा विस्तृत कोड तथ्याङ्क साझा गर्दैन",
el: "Ο χρήστης δεν δημοσιεύει δημόσια λεπτομερείς στατιστικές κώδικα",
ro: "Utilizatorul nu își publică statisticile detaliate ale codului",
ru: "Пользователь не делится подробной статистикой кода",
"uk-ua": "Користувач не публікує детальну статистику коду",
id: "Pengguna tidak membagikan statistik kode terperinci secara publik",
@@ -708,6 +771,7 @@ const wakatimeCardLocales = {
},
"wakatimecard.nocodingactivity": {
ar: "لا يوجد نشاط برمجي لهذا الأسبوع",
az: "Bu həftə heç bir kodlaşdırma fəaliyyəti olmayıb",
cn: "本周没有编程活动",
"zh-tw": "本周沒有編程活動",
cs: "Tento týden žádná aktivita v kódování",
@@ -715,6 +779,7 @@ const wakatimeCardLocales = {
en: "No coding activity this week",
bn: "এই সপ্তাহে কোন কোডিং অ্যাক্টিভিটি নেই",
es: "No hay actividad de codificación esta semana",
fi: "Ei koodaustoimintaa tällä viikolla",
fr: "Aucune activité de codage cette semaine",
hu: "Nem volt aktivitás ezen a héten",
it: "Nessuna attività in questa settimana",
@@ -725,6 +790,7 @@ const wakatimeCardLocales = {
"pt-br": "Nenhuma atividade de codificação esta semana",
np: "यस हप्ता कुनै कोडिंग गतिविधि छैन",
el: "Δεν υπάρχει δραστηριότητα κώδικα γι' αυτή την εβδομάδα",
ro: "Nicio activitate de programare săptămâna aceasta",
ru: "На этой неделе не было активности",
"uk-ua": "На цьому тижні не було активності",
id: "Tidak ada aktivitas perkodingan minggu ini",
+5 -1
View File
@@ -307,7 +307,11 @@ describe("Test /api/", () => {
expect(res.setHeader).toBeCalledWith("Content-Type", "image/svg+xml");
expect(res.send).toBeCalledWith(
renderError("Something went wrong", "This username is blacklisted"),
renderError(
"This username is blacklisted",
"Please deploy your own instance",
{ show_repo_link: false },
),
);
});
+5 -1
View File
@@ -156,7 +156,11 @@ describe("Test /api/pin", () => {
expect(res.setHeader).toBeCalledWith("Content-Type", "image/svg+xml");
expect(res.send).toBeCalledWith(
renderError("Something went wrong", "This username is blacklisted"),
renderError(
"This username is blacklisted",
"Please deploy your own instance",
{ show_repo_link: false },
),
);
});
+6 -8
View File
@@ -71,7 +71,7 @@ describe("Test renderStatsCard", () => {
document.body.innerHTML = renderStatsCard({ ...stats, name: "Felix" });
expect(document.getElementsByClassName("header")[0].textContent).toBe(
"Felix' GitHub Stats",
"Felix's GitHub Stats",
);
});
@@ -376,29 +376,27 @@ describe("Test renderStatsCard", () => {
document.querySelector(
'g[transform="translate(0, 0)"]>.stagger>.stat.bold',
).textContent,
).toMatchInlineSnapshot(`"获标星数star:"`);
).toMatchInlineSnapshot(`"获标星数:"`);
expect(
document.querySelector(
'g[transform="translate(0, 25)"]>.stagger>.stat.bold',
).textContent,
).toMatchInlineSnapshot(
`"累计提交数(commit (${new Date().getFullYear()}):"`,
);
).toMatchInlineSnapshot(`"累计提交总数 (${new Date().getFullYear()}):"`);
expect(
document.querySelector(
'g[transform="translate(0, 50)"]>.stagger>.stat.bold',
).textContent,
).toMatchInlineSnapshot(`"拉取请求数(PR:"`);
).toMatchInlineSnapshot(`"发起的 PR 总数:"`);
expect(
document.querySelector(
'g[transform="translate(0, 75)"]>.stagger>.stat.bold',
).textContent,
).toMatchInlineSnapshot(`"指出问题数(issue:"`);
).toMatchInlineSnapshot(`"提出的 issue 总数:"`);
expect(
document.querySelector(
'g[transform="translate(0, 100)"]>.stagger>.stat.bold',
).textContent,
).toMatchInlineSnapshot(`"贡献(去年):"`);
).toMatchInlineSnapshot(`"贡献的项目数(去年):"`);
});
it("should render without rounding", () => {
+5 -1
View File
@@ -184,7 +184,11 @@ describe("Test /api/top-langs", () => {
expect(res.setHeader).toBeCalledWith("Content-Type", "image/svg+xml");
expect(res.send).toBeCalledWith(
renderError("Something went wrong", "This username is blacklisted"),
renderError(
"This username is blacklisted",
"Please deploy your own instance",
{ show_repo_link: false },
),
);
});