diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000000000..c3708f4f89ac9
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,3 @@
+node_modules
+*.json
+*.md
\ No newline at end of file
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000000000..6b6938ff65681
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,6 @@
+{
+ "trailingComma": "none",
+ "useTabs": false,
+ "endOfLine": "lf",
+ "proseWrap": "always"
+}
diff --git a/api/pin.js b/api/pin.js
index c09b2d6eaa092..dd7dbb953a218 100644
--- a/api/pin.js
+++ b/api/pin.js
@@ -3,7 +3,7 @@ const {
renderError,
parseBoolean,
clampValue,
- CONSTANTS,
+ CONSTANTS
} = require("../src/common/utils");
const fetchRepo = require("../src/fetchers/repo-fetcher");
const renderRepoCard = require("../src/cards/repo-card");
@@ -13,13 +13,14 @@ module.exports = async (req, res) => {
const {
username,
repo,
+ hide_border,
title_color,
icon_color,
text_color,
bg_color,
theme,
show_owner,
- cache_seconds,
+ cache_seconds
} = req.query;
let repoData;
@@ -56,12 +57,13 @@ module.exports = async (req, res) => {
return res.send(
renderRepoCard(repoData, {
+ hide_border,
title_color,
icon_color,
text_color,
bg_color,
theme,
- show_owner: parseBoolean(show_owner),
+ show_owner: parseBoolean(show_owner)
})
);
} catch (err) {
diff --git a/api/top-langs.js b/api/top-langs.js
index 59692cd2a81be..ff0268049dbfa 100644
--- a/api/top-langs.js
+++ b/api/top-langs.js
@@ -4,7 +4,7 @@ const {
clampValue,
parseBoolean,
parseArray,
- CONSTANTS,
+ CONSTANTS
} = require("../src/common/utils");
const fetchTopLanguages = require("../src/fetchers/top-languages-fetcher");
const renderTopLanguages = require("../src/cards/top-languages-card");
@@ -24,9 +24,10 @@ module.exports = async (req, res) => {
cache_seconds,
layout,
langs_count,
+ count_forks,
+ exclude_repo
} = req.query;
let topLangs;
-
res.setHeader("Content-Type", "image/svg+xml");
if (blacklist.includes(username)) {
@@ -34,7 +35,12 @@ module.exports = async (req, res) => {
}
try {
- topLangs = await fetchTopLanguages(username, langs_count);
+ topLangs = await fetchTopLanguages(
+ username,
+ langs_count,
+ count_forks,
+ parseArray(exclude_repo)
+ );
const cacheSeconds = clampValue(
parseInt(cache_seconds || CONSTANTS.TWO_HOURS, 10),
@@ -54,7 +60,7 @@ module.exports = async (req, res) => {
text_color,
bg_color,
theme,
- layout,
+ layout
})
);
} catch (err) {
diff --git a/readme.md b/readme.md
index 7ef0bef27156c..d23fb03546eda 100644
--- a/readme.md
+++ b/readme.md
@@ -133,6 +133,7 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you
- `text_color` - Body text color _(hex color)_
- `icon_color` - Icons color if available _(hex color)_
- `bg_color` - Card's background color _(hex color)_ **or** a gradient in the form of _angle,start,end_
+- `hide_border` - Hides the card's border _(boolean)_
- `theme` - name of the theme, choose from [all available themes](./themes/README.md)
- `cache_seconds` - set the cache header manually _(min: 1800, max: 86400)_
@@ -166,16 +167,17 @@ You can provide multiple comma-separated values in bg_color option to render a g
- `hide_title` - _(boolean)_
- `layout` - Switch between two available layouts `default` & `compact`
- `card_width` - Set the card's width manually _(number)_
+- `count_forks` - Whether to count languages of forks, default: false _(boolean)_
+- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_
- `langs_count` - Show more languages on the card, between 1-10, defaults to 5 _(number)_
-> :warning: **Important:**
-> Language names should be uri-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
+> :warning: **Important:**
+> Language names should be uri-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
> (i.e: `c++` should become `c%2B%2B`, `jupyter notebook` should become `jupyter%20notebook`, etc.)
#### Wakatime Card Exclusive Options:
- `hide_title` - _(boolean)_
-- `hide_border` - _(boolean)_
- `line_height` - Sets the line-height between text _(number)_
- `hide_progress` - Hides the progress bar and percentage _(boolean)_
@@ -221,6 +223,22 @@ Endpoint: `api/top-langs?username=anuraghazra`
[](https://github.com/anuraghazra/github-readme-stats)
```
+### Count languages of forks
+
+You can use `?count_forks=true` parameter to count languages of forks.
+
+```md
+[](https://github.com/anuraghazra/github-readme-stats)
+```
+
+### Exclude individual repositories
+
+You can use `?exclude_repo=repo1,repo2` parameter to exclude individual repositories.
+
+```md
+[](https://github.com/anuraghazra/github-readme-stats)
+```
+
### Hide individual languages
You can use `?hide=language1,language2` parameter to hide individual languages.
@@ -342,16 +360,16 @@ NOTE: Since [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) we
Guide on setting up Vercel 🔨
1. Go to [vercel.com](https://vercel.com/)
-1. Click on `Log in`
+1. Click on `Log in`

-1. Sign in with GitHub by pressing `Continue with GitHub`
+1. Sign in with GitHub by pressing `Continue with GitHub`

1. Sign into GitHub and allow access to all repositories, if prompted
1. Fork this repo
1. Go back to your [Vercel dashboard](https://vercel.com/dashboard)
-1. Select `Import Project`
+1. Select `Import Project`

-1. Select `Import Git Repository`
+1. Select `Import Git Repository`

1. Select root and keep everything as is, just add your environment variable named PAT_1 (as shown), which will contain a personal access token (PAT), which you can easily create [here](https://github.com/settings/tokens/new) (leave everything as is, just name it something, it can be anything you want)

diff --git a/src/cards/repo-card.js b/src/cards/repo-card.js
index 233812b4b0db9..d04b1583fce82 100644
--- a/src/cards/repo-card.js
+++ b/src/cards/repo-card.js
@@ -3,7 +3,7 @@ const {
encodeHTML,
getCardColors,
FlexLayout,
- wrapTextMultiline,
+ wrapTextMultiline
} = require("../common/utils");
const icons = require("../common/icons");
const Card = require("../common/Card");
@@ -18,15 +18,16 @@ const renderRepoCard = (repo, options = {}) => {
stargazers,
isArchived,
isTemplate,
- forkCount,
+ forkCount
} = repo;
const {
+ hide_border,
title_color,
icon_color,
text_color,
bg_color,
show_owner,
- theme = "default_repocard",
+ theme = "default_repocard"
} = options;
const header = show_owner ? nameWithOwner : name;
@@ -55,7 +56,7 @@ const renderRepoCard = (repo, options = {}) => {
icon_color,
text_color,
bg_color,
- theme,
+ theme
});
const totalStars = kFormatter(stargazers.totalCount);
@@ -101,7 +102,7 @@ const renderRepoCard = (repo, options = {}) => {
const starAndForkCount = FlexLayout({
items: [svgStars, svgForks],
- gap: 65,
+ gap: 65
}).join("");
const card = new Card({
@@ -113,12 +114,12 @@ const renderRepoCard = (repo, options = {}) => {
titleColor,
textColor,
iconColor,
- bgColor,
- },
+ bgColor
+ }
});
card.disableAnimations();
- card.setHideBorder(false);
+ card.setHideBorder(hide_border);
card.setHideTitle(false);
card.setCSS(`
.description { font: 400 13px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
@@ -147,7 +148,7 @@ const renderRepoCard = (repo, options = {}) => {
${svgLanguage}
${starAndForkCount}
diff --git a/src/common/retryer.js b/src/common/retryer.js
index 592463ef2a09c..7b49d93068b78 100644
--- a/src/common/retryer.js
+++ b/src/common/retryer.js
@@ -1,6 +1,6 @@
const { logger, CustomError } = require("../common/utils");
-const retryer = async (fetcher, variables, retries = 0) => {
+const retryer = async (fetcher, variables, retries = 0, count_forks) => {
if (retries > 7) {
throw new CustomError("Maximum retries exceeded", CustomError.MAX_RETRY);
}
@@ -9,7 +9,8 @@ const retryer = async (fetcher, variables, retries = 0) => {
let response = await fetcher(
variables,
process.env[`PAT_${retries + 1}`],
- retries
+ retries,
+ count_forks
);
// prettier-ignore
@@ -21,7 +22,7 @@ const retryer = async (fetcher, variables, retries = 0) => {
logger.log(`PAT_${retries + 1} Failed`);
retries++;
// directly return from the function
- return retryer(fetcher, variables, retries);
+ return retryer(fetcher, variables, retries, count_forks);
}
// finally return the response
@@ -35,7 +36,7 @@ const retryer = async (fetcher, variables, retries = 0) => {
logger.log(`PAT_${retries + 1} Failed`);
retries++;
// directly return from the function
- return retryer(fetcher, variables, retries);
+ return retryer(fetcher, variables, retries, count_forks);
}
}
};
diff --git a/src/fetchers/top-languages-fetcher.js b/src/fetchers/top-languages-fetcher.js
index 51ed8a87b12b4..a9038c56c3ca8 100644
--- a/src/fetchers/top-languages-fetcher.js
+++ b/src/fetchers/top-languages-fetcher.js
@@ -2,15 +2,17 @@ const { request, logger, clampValue } = require("../common/utils");
const retryer = require("../common/retryer");
require("dotenv").config();
-const fetcher = (variables, token) => {
+const fetcher = (variables, token, retries, count_forks) => {
+ const forks = count_forks == "true" ? `` : `isFork: false, `;
return request(
{
query: `
query userInfo($login: String!) {
user(login: $login) {
- # fetch only owner repos & not forks
- repositories(ownerAffiliations: OWNER, isFork: false, first: 100) {
+ # fetch only owner repos
+ repositories(ownerAffiliations: OWNER, ${forks}first: 100) {
nodes {
+ name
languages(first: 10, orderBy: {field: SIZE, direction: DESC}) {
edges {
size
@@ -25,20 +27,25 @@ const fetcher = (variables, token) => {
}
}
`,
- variables,
+ variables
},
{
- Authorization: `bearer ${token}`,
+ Authorization: `bearer ${token}`
}
);
};
-async function fetchTopLanguages(username, langsCount = 5) {
+async function fetchTopLanguages(
+ username,
+ langsCount = 5,
+ count_forks = false,
+ exclude_repo = []
+) {
if (!username) throw Error("Invalid username");
langsCount = clampValue(parseInt(langsCount), 1, 10);
- const res = await retryer(fetcher, { login: username });
+ const res = await retryer(fetcher, { login: username }, 0, count_forks);
if (res.data.errors) {
logger.error(res.data.errors);
@@ -46,6 +53,22 @@ async function fetchTopLanguages(username, langsCount = 5) {
}
let repoNodes = res.data.data.user.repositories.nodes;
+ let repoToHide = {};
+
+ // populate repoToHide map for quick lookup
+ // while filtering out
+ if (exclude_repo) {
+ exclude_repo.forEach((langName) => {
+ repoToHide[langName] = true;
+ });
+ }
+
+ // filter out repositories to be hidden
+ repoNodes = repoNodes
+ .sort((a, b) => b.size - a.size)
+ .filter((name) => {
+ return !repoToHide[name.name];
+ });
repoNodes = repoNodes
.filter((node) => {
@@ -69,8 +92,8 @@ async function fetchTopLanguages(username, langsCount = 5) {
[prev.node.name]: {
name: prev.node.name,
color: prev.node.color,
- size: langSize,
- },
+ size: langSize
+ }
};
}, {});