diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 931c461c..13eb4b3c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,6 +1,6 @@ version: 2 updates: - # Maintain dependencies for NPM + # Maintain dependencies for npm - package-ecosystem: npm directory: "/" schedule: diff --git a/api-renamed/gist.js b/api-renamed/gist.js index 1b326d45..8f2de341 100644 --- a/api-renamed/gist.js +++ b/api-renamed/gist.js @@ -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", { diff --git a/api-renamed/index.js b/api-renamed/index.js index 1b61d3ac..a1a7b90b 100644 --- a/api-renamed/index.js +++ b/api-renamed/index.js @@ -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, + }, + ), ); } diff --git a/api-renamed/pin.js b/api-renamed/pin.js index 3fc690d2..8dc7e8d7 100644 --- a/api-renamed/pin.js +++ b/api-renamed/pin.js @@ -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, + }, + ), ); } diff --git a/api-renamed/top-langs.js b/api-renamed/top-langs.js index f7d759d8..46672cf4 100644 --- a/api-renamed/top-langs.js +++ b/api-renamed/top-langs.js @@ -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, + }, + ), ); } diff --git a/api-renamed/wakatime.js b/api-renamed/wakatime.js index e619fecb..32c501a4 100644 --- a/api-renamed/wakatime.js +++ b/api-renamed/wakatime.js @@ -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", { diff --git a/package-lock.json b/package-lock.json index 0118854e..03c17f8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 1730ec34..656dbafb 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/readme.md b/readme.md index 367ca1ec..aa34bba1 100644 --- a/readme.md +++ b/readme.md @@ -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) @@ -308,6 +308,7 @@ Here is a list of all available locales: | `es` | Spanish | | `fr` | French | | `hu` | Hungarian | +| `fi` | Finnish | @@ -323,6 +324,7 @@ Here is a list of all available locales: | `el` | Greek | | `ru` | Russian | | `uk-ua` | Ukrainian | +| `ro` | Romanian | @@ -337,6 +339,7 @@ Here is a list of all available locales: | `uz` | Uzbek | | `vi` | Vietnamese | | `se` | Swedish | +| `az` | Azerbaijani | @@ -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 🎉 -## 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: diff --git a/src/cards/stats.js b/src/cards/stats.js index f0977619..d92b2199 100644 --- a/src/cards/stats.js +++ b/src/cards/stats.js @@ -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 }), diff --git a/src/common/utils.js b/src/common/utils.js index d179d111..046c7fc7 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -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}"/> 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" } diff --git a/src/common/whitelist.js b/src/common/whitelist.js new file mode 100644 index 00000000..b5df7c70 --- /dev/null +++ b/src/common/whitelist.js @@ -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; diff --git a/src/fetchers/gist.js b/src/fetchers/gist.js index 4e0e0f5e..cd4006b2 100644 --- a/src/fetchers/gist.js +++ b/src/fetchers/gist.js @@ -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} Gist data. */ const fetchGist = async (id) => { diff --git a/src/fetchers/stats.js b/src/fetchers/stats.js index 84541ddc..c55dd044 100644 --- a/src/fetchers/stats.js +++ b/src/fetchers/stats.js @@ -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. diff --git a/src/translations.js b/src/translations.js index fe03b60d..719cec71 100644 --- a/src/translations.js +++ b/src/translations.js @@ -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", diff --git a/tests/api.test.js b/tests/api.test.js index b488eea3..43f1c8ac 100644 --- a/tests/api.test.js +++ b/tests/api.test.js @@ -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 }, + ), ); }); diff --git a/tests/pin.test.js b/tests/pin.test.js index 1b03e5cb..117d6127 100644 --- a/tests/pin.test.js +++ b/tests/pin.test.js @@ -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 }, + ), ); }); diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js index b7129b3c..cf6c7f44 100644 --- a/tests/renderStatsCard.test.js +++ b/tests/renderStatsCard.test.js @@ -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", () => { diff --git a/tests/top-langs.test.js b/tests/top-langs.test.js index ced13915..ccbb0c61 100644 --- a/tests/top-langs.test.js +++ b/tests/top-langs.test.js @@ -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 }, + ), ); });