Compare commits
31
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
084ce7fc8d | ||
|
|
171f970bee | ||
|
|
5514f4e8f1 | ||
|
|
ebc8ce4b7d | ||
|
|
bec23af5f9 | ||
|
|
0582a2adae | ||
|
|
ce8660c825 | ||
|
|
53c49404bf | ||
|
|
683b919c20 | ||
|
|
70f11b0018 | ||
|
|
c6e2a7998b | ||
|
|
dfe91e3596 | ||
|
|
777a3ae786 | ||
|
|
1fa476ac6e | ||
|
|
6f7e35468c | ||
|
|
d7089af346 | ||
|
|
394fef948b | ||
|
|
67b434dc79 | ||
|
|
e7dcda0ee8 | ||
|
|
1412a8dbe0 | ||
|
|
e18f57be3e | ||
|
|
8dca589a13 | ||
|
|
f0b89d0f72 | ||
|
|
56e3745a5c | ||
|
|
416f027fae | ||
|
|
a4486d0327 | ||
|
|
60511778ff | ||
|
|
3b0f1b11a0 | ||
|
|
34b5dcb181 | ||
|
|
0833e8531d | ||
|
|
3c7220e4f7 |
@@ -0,0 +1,30 @@
|
||||
name: Theme preview
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- master
|
||||
- theme-preview-script
|
||||
- "themes/index.js"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "12.x"
|
||||
|
||||
- name: npm install, preview theme
|
||||
run: |
|
||||
npm install
|
||||
npm run preview-theme
|
||||
env:
|
||||
CI: true
|
||||
PERSONAL_TOKEN: ${{ secrets.PERSONAL_TOKEN }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
+10
-4
@@ -5,9 +5,9 @@ const {
|
||||
parseArray,
|
||||
clampValue,
|
||||
CONSTANTS,
|
||||
} = require("../src/utils");
|
||||
const fetchStats = require("../src/fetchStats");
|
||||
const renderStatsCard = require("../src/renderStatsCard");
|
||||
} = require("../src/common/utils");
|
||||
const fetchStats = require("../src/fetchers/stats-fetcher");
|
||||
const renderStatsCard = require("../src/cards/stats-card");
|
||||
|
||||
module.exports = async (req, res) => {
|
||||
const {
|
||||
@@ -18,6 +18,7 @@ module.exports = async (req, res) => {
|
||||
hide_rank,
|
||||
show_icons,
|
||||
count_private,
|
||||
include_all_commits,
|
||||
line_height,
|
||||
title_color,
|
||||
icon_color,
|
||||
@@ -31,7 +32,11 @@ module.exports = async (req, res) => {
|
||||
res.setHeader("Content-Type", "image/svg+xml");
|
||||
|
||||
try {
|
||||
stats = await fetchStats(username, parseBoolean(count_private));
|
||||
stats = await fetchStats(
|
||||
username,
|
||||
parseBoolean(count_private),
|
||||
parseBoolean(include_all_commits)
|
||||
);
|
||||
} catch (err) {
|
||||
return res.send(
|
||||
renderError(
|
||||
@@ -56,6 +61,7 @@ module.exports = async (req, res) => {
|
||||
hide_title: parseBoolean(hide_title),
|
||||
hide_border: parseBoolean(hide_border),
|
||||
hide_rank: parseBoolean(hide_rank),
|
||||
include_all_commits: parseBoolean(include_all_commits),
|
||||
line_height,
|
||||
title_color,
|
||||
icon_color,
|
||||
|
||||
+3
-3
@@ -5,9 +5,9 @@ const {
|
||||
clampValue,
|
||||
CONSTANTS,
|
||||
logger,
|
||||
} = require("../src/utils");
|
||||
const fetchRepo = require("../src/fetchRepo");
|
||||
const renderRepoCard = require("../src/renderRepoCard");
|
||||
} = require("../src/common/utils");
|
||||
const fetchRepo = require("../src/fetchers/repo-fetcher");
|
||||
const renderRepoCard = require("../src/cards/repo-card");
|
||||
|
||||
module.exports = async (req, res) => {
|
||||
const {
|
||||
|
||||
+7
-6
@@ -5,22 +5,23 @@ const {
|
||||
parseBoolean,
|
||||
parseArray,
|
||||
CONSTANTS,
|
||||
} = require("../src/utils");
|
||||
const fetchTopLanguages = require("../src/fetchTopLanguages");
|
||||
const renderTopLanguages = require("../src/renderTopLanguages");
|
||||
} = require("../src/common/utils");
|
||||
const fetchTopLanguages = require("../src/fetchers/top-languages-fetcher");
|
||||
const renderTopLanguages = require("../src/cards/top-languages-card");
|
||||
|
||||
module.exports = async (req, res) => {
|
||||
const {
|
||||
username,
|
||||
hide,
|
||||
hide_title,
|
||||
hide_border,
|
||||
card_width,
|
||||
title_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
theme,
|
||||
cache_seconds,
|
||||
layout
|
||||
layout,
|
||||
} = req.query;
|
||||
let topLangs;
|
||||
|
||||
@@ -42,15 +43,15 @@ module.exports = async (req, res) => {
|
||||
|
||||
res.send(
|
||||
renderTopLanguages(topLangs, {
|
||||
theme,
|
||||
hide_title: parseBoolean(hide_title),
|
||||
hide_border: parseBoolean(hide_border),
|
||||
card_width: parseInt(card_width, 10),
|
||||
hide: parseArray(hide),
|
||||
title_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
theme,
|
||||
layout
|
||||
layout,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
+7
-2
@@ -6,22 +6,27 @@
|
||||
"scripts": {
|
||||
"test": "jest --coverage",
|
||||
"test:watch": "jest --watch",
|
||||
"theme-readme-gen": "node scripts/generate-theme-doc"
|
||||
"theme-readme-gen": "node scripts/generate-theme-doc",
|
||||
"preview-theme": "node scripts/preview-theme"
|
||||
},
|
||||
"author": "Anurag Hazra",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@actions/core": "^1.2.4",
|
||||
"@actions/github": "^4.0.0",
|
||||
"@testing-library/dom": "^7.20.0",
|
||||
"@testing-library/jest-dom": "^5.11.0",
|
||||
"axios": "^0.19.2",
|
||||
"axios-mock-adapter": "^1.18.1",
|
||||
"css-to-object": "^1.1.0",
|
||||
"husky": "^4.2.5",
|
||||
"jest": "^26.1.0"
|
||||
"jest": "^26.1.0",
|
||||
"parse-diff": "^0.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^8.2.0",
|
||||
"emoji-name-map": "^1.2.8",
|
||||
"github-username-regex": "^1.0.0",
|
||||
"word-wrap": "^1.2.3"
|
||||
},
|
||||
"husky": {
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
<a href="readme_de.md">Deutsch</a>
|
||||
·
|
||||
<a href="readme_ja.md">日本語</a>
|
||||
·
|
||||
<a href="readme_pt-BR.md">Português Brasileiro</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center">Loved the project? Please consider <a href="https://www.paypal.me/anuraghazra">donating</a> to help it improve!
|
||||
@@ -118,28 +120,44 @@ You can look at a preview for [all available themes](./themes/README.md) or chec
|
||||
|
||||
You can customize the appearance of your `Stats Card` or `Repo Card` however you want with URL params.
|
||||
|
||||
Customization Options:
|
||||
#### Common Options:
|
||||
|
||||
| Option | type | description | Stats Card (default) | Repo Card (default) | Top Lang Card (default) |
|
||||
| ------------- | --------- | ------------------------------------------- | -------------------- | ------------------- | ----------------------- |
|
||||
| title_color | hex color | title color | 2f80ed | 2f80ed | 2f80ed |
|
||||
| text_color | hex color | body color | 333 | 333 | 333 |
|
||||
| icon_color | hex color | icon color | 4c71f2 | 586069 | 586069 |
|
||||
| bg_color | hex color | card bg color | FFFEFE | FFFEFE | FFFEFE |
|
||||
| line_height | number | control the line-height between text | 30 | N/A | N/A |
|
||||
| hide | CSV | hides the items specified | undefined | N/A | undefined |
|
||||
| hide_rank | boolean | hides the ranking | false | N/A | N/A |
|
||||
| hide_title | boolean | hides the stats title | false | N/A | false |
|
||||
| hide_border | boolean | hides the stats card border | false | N/A | N/A |
|
||||
| show_owner | boolean | shows owner name in repo card | N/A | false | N/A |
|
||||
| show_icons | boolean | shows icons | false | N/A | N/A |
|
||||
| theme | string | sets inbuilt theme | 'default' | 'default_repocard' | 'default' |
|
||||
| cache_seconds | number | manually set custom cache control | 1800 | 1800 | 1800 |
|
||||
| count_private | boolean | counts private contributions too if enabled | false | N/A | N/A |
|
||||
| layout | string | choose a layout option | N/A | N/A | 'default' |
|
||||
- `title_color` - Card's title color _(hex color)_
|
||||
- `text_color` - Body text color _(hex color)_
|
||||
- `icon_color` - Icons color if available _(hex color)_
|
||||
- `bg_color` - Card's background color _(hex color)_
|
||||
- `theme` - name of the theme, choose from [all available themes](./themes/README.md)
|
||||
- `cache_seconds` - set the cache header manually _(min: 1800, max: 86400)_
|
||||
|
||||
> Note on cache: Repo cards have default cache of 30mins (1800 seconds) if the fork count & star count is less than 1k otherwise it's 2hours (7200). Also note that cache is clamped to minimum of 30min and maximum of 24hours
|
||||
|
||||
#### Stats Card Exclusive Options:
|
||||
|
||||
- `hide` - Hide's the specified items from stats _(Comma seperated values)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `hide_rank` - _(boolean)_
|
||||
- `show_icons` - _(boolean)_
|
||||
- `include_all_commits` - Count total commits instead of just the current year commits _(boolean)_
|
||||
- `count_private` - Count private commits _(boolean)_
|
||||
- `line_height` - Sets the line-height between text _(number)_
|
||||
|
||||
#### Repo Card Exclusive Options:
|
||||
|
||||
- `show_owner` - Show the owner name of the repo _(boolean)_
|
||||
|
||||
#### Language Card Exclusive Options:
|
||||
|
||||
- `hide` - Hide the languages specified from the card _(Comma seperated values)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `layout` - Switch between two available layouts `default` & `compact`
|
||||
- `card_width` - Set the card's width manually _(number)_
|
||||
|
||||
> :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.)
|
||||
|
||||
---
|
||||
|
||||
# GitHub Extra Pins
|
||||
|
||||
GitHub extra pins allow you to pin more than 6 repositories in your profile using a GitHub readme profile.
|
||||
@@ -188,10 +206,6 @@ You can use `?hide=language1,language2` parameter to hide individual languages.
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
> :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.)
|
||||
|
||||
### Compact Language Card Layout
|
||||
|
||||
You can use the `&layout=compact` option to change the card design.
|
||||
@@ -224,6 +238,10 @@ You can use the `&layout=compact` option to change the card design.
|
||||
|
||||

|
||||
|
||||
- Include All Commits
|
||||
|
||||

|
||||
|
||||
- Themes
|
||||
|
||||
Choose from any of the [default themes](#themes)
|
||||
@@ -266,7 +284,7 @@ NOTE: Since [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) we
|
||||
[](https://vercel.com/import/project?template=https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
<details>
|
||||
<summary>Guide on setting up Vercel</summary>
|
||||
<summary><b> Guide on setting up Vercel 🔨 </b></summary>
|
||||
|
||||
1. Go to [vercel.com](https://vercel.com/)
|
||||
1. Click on `Log in`
|
||||
|
||||
+123
-53
@@ -44,7 +44,7 @@
|
||||
# Características
|
||||
|
||||
- [Tarjeta de estadísticas de GitHub](#tarjeta-de-estadísticas-de-github)
|
||||
- [Pins extra de GitHub](#pins-extra-de-github)
|
||||
- [Pins adicionales de GitHub](#pines-adicionales-de-github)
|
||||
- [Temas](#temas)
|
||||
- [Personalización](#personalización)
|
||||
- [Despliega por tu cuenta](#despliega-tu-propia-instancia-de-vercel)
|
||||
@@ -107,69 +107,59 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
|
||||
|
||||
<img src="https://res.cloudinary.com/anuraghazra/image/upload/v1595174536/grs-themes_l4ynja.png" alt="GitHub Readme Stat Themes" width="600px"/>
|
||||
|
||||
Puedes ver una vista previa de [todos los temas disponibles](./themes/README.md) o ver el [archivo de configuración](./themes/index.js) del tema y también **puedes contribuir con nuevos temas** si lo deseas: D
|
||||
Puedes ver una vista previa de [todos los temas disponibles](./themes/README.md) o ver el [archivo de configuración](./themes/index.js) del tema y también **puedes contribuir con nuevos temas** si lo deseas :D
|
||||
|
||||
### Personalización
|
||||
|
||||
Puedes personalizar el aspecto de tu `Stats Card` o `Repo Card` de la manera que desees con los parámetros URL.
|
||||
|
||||
Opciones de personalización:
|
||||
#### Opciones Comunes:
|
||||
|
||||
| Option | type | description | Stats Card (default) | Repo Card (default) |
|
||||
| ----------- | --------- | ----------------------------- | -------------------- | ------------------- |
|
||||
| title_color | hex color | color del título | 2f80ed | 2f80ed |
|
||||
| text_color | hex color | color del contenido | 333 | 333 |
|
||||
| icon_color | hex color | color del ícono | 4c71f2 | 586069 |
|
||||
| bg_color | hex color | color de fondo | FFFEFE | FFFEFE |
|
||||
| line_height | number | controla el line_height | 30 | N/A |
|
||||
| hide_rank | boolean | oculta la clasificación | false | N/A |
|
||||
| hide_title | boolean | oculta el título | false | N/A |
|
||||
| hide_border | boolean | oculta el borde | false | N/A |
|
||||
| show_owner | boolean | muestra el propietario | N/A | false |
|
||||
| show_icons | boolean | muestra los íconos | false | N/A |
|
||||
| theme | string | establece un tema incorporado | 'default' | 'default_repocard' |
|
||||
- `title_color` - Color del título _(hex color)_
|
||||
- `text_color` - Color del contenido _(hex color)_
|
||||
- `icon_color` - Color de icono si esta disponible _(hex color)_
|
||||
- `bg_color` - Color de fondo _(hex color)_
|
||||
- `theme` - Nombre del tema, elige uno de [todos los temas disponible ](./themes/README.md)
|
||||
- `cache_seconds` - Cache _(min: 1800, max: 86400)_
|
||||
|
||||
> Nota sobre la caché: las tarjetas de Repo tienen un caché predeterminado de 30 minutos (1800 segundos) si el recuento forks y el recuento de estrellas es inferior a 1k; de lo contrario, son 2 horas (7200). También tenga en cuenta que el caché está sujeto a un mínimo de 30 minutos y un máximo de 24 horas
|
||||
|
||||
#### Opciones exclusivas de la tarjeta de estadísticas:
|
||||
|
||||
- `hide` - Ocultar los elementos especificados de las estadísticas _ (valores separados por comas) _
|
||||
- `hide_title` - _(boolean)_
|
||||
- `hide_rank` - _(boolean)_
|
||||
- `show_icons` - _(boolean)_
|
||||
- `include_all_commits` - Cuente los commits totales en lugar de solo los commits del año actual _(boolean)_
|
||||
- `count_private` - Cuenta los commits privadas _(boolean)_
|
||||
- `line_height` - Establece el alto de línea entre texto _(number)_
|
||||
|
||||
#### Opciones exclusivas de la tarjeta Repo:
|
||||
|
||||
- `show_owner` - Mostrar el nombre del propietario del repositorio _(boolean)_
|
||||
|
||||
#### Opciones exclusivas de la tarjeta de lenguajes:
|
||||
|
||||
- `hide` - Ocultar los lenguajes especificados de la tarjeta _(valores separados por comas)_
|
||||
- `hide_title` - _(boolean)_
|
||||
- `layout` - Cambiar entre dos diseños disponibles `default` & `compact`
|
||||
- `card_width` - Establecer el ancho de la tarjeta manualmente _(number)_
|
||||
|
||||
> :warning: **Importante:**
|
||||
> Los nombres de los idiomas deben tener escape de uri, como se especifica en [Código porciento](https://es.wikipedia.org/wiki/C%C3%B3digo_porciento)
|
||||
> (es decir: `c++` debería convertirse en `c%2B%2B`,`jupyter notebook` debería convertirse en `jupyter%20notebook`, etc.)
|
||||
|
||||
---
|
||||
|
||||
### Ejemplo
|
||||
# Pines adicionales de GitHub
|
||||
|
||||
- Predeterminado
|
||||
Los pines adicionales de GitHub le permiten fijar más de 6 repositorios en su perfil utilizando un readme de perfil de GitHub.
|
||||
|
||||

|
||||
|
||||
- Ocultando estadísticas específicas
|
||||
|
||||

|
||||
|
||||
- Mostrando íconos
|
||||
|
||||

|
||||
|
||||
- Temas
|
||||
|
||||
Elige uno de los [temas predeterminados](#temas)
|
||||
|
||||

|
||||
|
||||
- Personalizando la tarjeta de estadísticas
|
||||
|
||||

|
||||
|
||||
- Personalizando la tarjeta de repositorio
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
# Pins extra de GitHub
|
||||
|
||||
Los pins extra de GitHub te permiten anclar más de 6 repositorios en tu perfil utilizando el archivo README.md.
|
||||
|
||||
¡Bien! Ya no estás limitado a 6 repositorios anclados.
|
||||
Yey! Ya no está limitado a 6 repositorios anclados.
|
||||
|
||||
### Utilización
|
||||
|
||||
Copia y pega este código en tu README.md y cambia los links.
|
||||
Copie y pegue este código en su archivo Léame y cambie los enlaces.
|
||||
|
||||
Endpoint: `api/pin?username=anuraghazra&repo=github-readme-stats`
|
||||
|
||||
@@ -185,9 +175,89 @@ Utiliza la variable [show_owner](#customización) para incluir el nombre de usua
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
### Pequeño consejo (alinear las tarjetas de repositorios)
|
||||
# Tarjeta de lenguajes principales
|
||||
|
||||
Usualmente no serías capaz de alinear las imágenes una al lado de otra. Para lograrlo, puedes realizar esto:
|
||||
La tarjeta de lenguajes principales muestra los lenguajes principales del usuario de github que se han utilizado principalmente.
|
||||
|
||||
_NOTA: los lenguajes principales no indican mi nivel de habilidad o algo así, es una métrica de github de los lenguajes que tengo más código en github, es una nueva característica de github-readme-stats_
|
||||
|
||||
### Utilización
|
||||
|
||||
Copie y pegue este código en su readme y cambie los enlaces.
|
||||
|
||||
Endpoint: `api/top-langs?username=anuraghazra`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Ocultar lenguajes individuales
|
||||
|
||||
Puede usar el parámetro `? Hide = language1, language2` para ocultar lenguajes individuales.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Diseño de tarjeta de lenguaje compacta
|
||||
|
||||
Puede usar la opción `& layout = compact` para cambiar el diseño de la tarjeta.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Ejemplo
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
- Diseño compacto
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Todos los ejemplos
|
||||
|
||||
- Por Defecto
|
||||
|
||||

|
||||
|
||||
- Ocultar estadísticas específicas
|
||||
|
||||

|
||||
|
||||
- Mostrando iconos
|
||||
|
||||

|
||||
|
||||
- Incluir todos los Commits
|
||||
|
||||

|
||||
|
||||
- Temas
|
||||
|
||||
Elija entre cualquiera de los [temas predeterminados](#themes)
|
||||
|
||||

|
||||
|
||||
- Personalizando tarjeta de estadísticas
|
||||
|
||||

|
||||
|
||||
- Personalizar la tarjeta de repositorio
|
||||
|
||||

|
||||
|
||||
- Lenguajes Principales
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Consejo rápido (alinee las tarjetas de repositorio)
|
||||
|
||||
Por lo general, no podrá diseñar las imágenes una al lado de la otra. Para hacerlo, puede usar este enfoque:
|
||||
|
||||
```md
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats">
|
||||
@@ -222,7 +292,7 @@ Nota: debido a esto [#58](https://github.com/anuraghazra/github-readme-stats/pul
|
||||
1. Selecciona `Import Git Repository`
|
||||

|
||||
1. Selecciona "root" y matén todo como está, simplemente añade tu variable de entorno llamada PAT_1 (como se muestra), la cual contendrá un token de acceso personal (PAT), el cual puedes crear fácilmente [aquí](https://github.com/settings/tokens/new) (mantén todo como está, simplemente asígnale un nombre, puede ser cualquiera que desees)
|
||||

|
||||

|
||||
1. Clickea "Deploy" y ya está listo. ¡Ve tus dominios para usar la API!
|
||||
|
||||
</details>
|
||||
|
||||
+325
@@ -0,0 +1,325 @@
|
||||
<p align="center">
|
||||
<img width="100px" src="https://res.cloudinary.com/anuraghazra/image/upload/v1594908242/logo_ccswme.svg" align="center" alt="GitHub Readme Stats" />
|
||||
<h2 align="center">GitHub Readme Stats</h2>
|
||||
<p align="center">Adicione suas estatísticas no GitHub geradas dinamicamente em seus readmes!</p>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
|
||||
<img alt="Testes aprovados" src="https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg" />
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/anuraghazra/github-readme-stats">
|
||||
<img src="https://codecov.io/gh/anuraghazra/github-readme-stats/branch/master/graph/badge.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues">
|
||||
<img alt="Issues" src="https://img.shields.io/github/issues/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/pulls">
|
||||
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/anuraghazra/github-readme-stats?color=0088ff" />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
|
||||
<img src="https://img.shields.io/badge/Apoiado%20por-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
|
||||
</a>
|
||||
<a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
|
||||
<img src="https://img.shields.io/badge/Apoiado%20por-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#demo">Ver demonstração</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Reportar erros</a>
|
||||
·
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats/issues/new/choose">Solicitar recursos</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="readme_cn.md">简体中文</a>
|
||||
·
|
||||
<a href="readme_es.md">Español</a>
|
||||
·
|
||||
<a href="readme_de.md">Deutsch</a>
|
||||
·
|
||||
<a href="readme_ja.md">日本語</a>
|
||||
·
|
||||
<a href="readme_pt-BR.md">Português Brasileiro</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center">Gostou do projeto? Por favor considere <a href="https://www.paypal.me/anuraghazra">fazer uma doação</a> para ajudar a melhorá-lo!
|
||||
|
||||
# Características
|
||||
|
||||
- [Cartão de estatísticas do GitHub](#cartão-de-estatísticas-do-github)
|
||||
- [Pins extras do GitHub](#pins-extras-do-github)
|
||||
- [Cartão de principais linguagens de programação](#cartão-de-principais-linguagens-de-programação)
|
||||
- [Temas](#temas)
|
||||
- [Personalização](#personalização)
|
||||
- [Faça suas próprias implantações](#faça-suas-próprias-implantações)
|
||||
|
||||
# Cartão de estatísticas do GitHub
|
||||
|
||||
Copie e cole isso no seu conteúdo de remarcação e é isso. Simples!
|
||||
|
||||
Mude o valor de `?username=` para o seu nome de usuário no GitHub.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
_Nota: As classificações são baseadas nas estatísticas do usuário, veja [src/calculateRank.js](./src/calculateRank.js)_
|
||||
|
||||
### Ocultando estatísticas específicas
|
||||
|
||||
Para ocultar estatísticas individualmente, você pode passar um parâmetro de consulta `?hide=` com valores separados por vírgula.
|
||||
|
||||
> Opções: `&hide=stars,commits,prs,issues,contribs`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Adicionando contagem de contribuições privadas à contagem total de commits
|
||||
|
||||
Adicione a contagem de todas as suas contribuições privadas à contagem total de confirmações usando o parâmetro de consulta `?count_private=true`.
|
||||
|
||||
_Nota: Se você estiver implantando este projeto, as contribuições privadas serão contadas por padrão; caso contrário, você precisará compartilhar suas contagens de contribuições privadas._
|
||||
|
||||
> Opções: `&count_private=true`
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Exibindo ícones
|
||||
|
||||
Para habilitar ícones, basta utilizar o parâmetro `show_icons=true` na sua requisição, da seguinte forma:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
### Temas
|
||||
|
||||
Com temas predefinidos, pode personalizar a aparência dos cartões sem precisar fazer nenhuma [configuração manual](#personalização).
|
||||
|
||||
Utilize o parâmetro `?theme=THEME_NAME`, da seguinte forma:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
#### Todos os temas predefinidos :
|
||||
|
||||
dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontrast, dracula
|
||||
|
||||
<img src="https://res.cloudinary.com/anuraghazra/image/upload/v1595174536/grs-themes_l4ynja.png" alt="GitHub Readme Stat Themes" width="600px"/>
|
||||
|
||||
Visualize [todos o temas disponíveis](./themes/README.md) ou o [arquivo de configuração de tema](./themes/index.js), além de **também poder contribuir com novos temas**, se desejar :D
|
||||
|
||||
### Personalização
|
||||
|
||||
Personalize a aparência do seu `Stats Card` ou `Repo Card` da maneira que desejar com os parâmetros de URL.
|
||||
|
||||
#### Opções comuns
|
||||
|
||||
- `title_color` - Cor do título do cartão _(hex color)_
|
||||
- `text_color` - Cor de texto do conteúdo _(hex color)_
|
||||
- `icon_color` - Cor dos ícones (se disponível) _(hex color)_
|
||||
- `bg_color` - Cor de fundo do cartão _(hex color)_
|
||||
- `theme` - Nome do tema, escolha em [todos os temas disponíveis](./themes/README.md)
|
||||
- `cache_seconds` - Defina o cabeçalho do cache manualmente _(min: 1800, max: 86400)_
|
||||
|
||||
> Nota sobre o cache: Cartões de repositório tem um cache padrão de 30 minutos (1800 segundos), se o número a contagem de forks e contagem de estrelas é menor que 1 mil o padrão é 2 horas (7200). Note também que o cache é limitado a um mínimo de 30 minutos e um máximo de 24 horas.
|
||||
|
||||
#### Opções exclusivas do cartão de estatísticas:
|
||||
|
||||
- `hide` - Oculta itens específicos das estatísticas _(Valores separados por vírgulas)_
|
||||
- `hide_title` - Ocutar o título _(boolean)_
|
||||
- `hide_rank` - Ocultar a classificação _(boolean)_
|
||||
- `show_icons` - Mostrar ícones _(boolean)_
|
||||
- `include_all_commits` - Contabiliza todos os commits ao invés de apenas os atual ano _(boolean)_
|
||||
- `count_private` - Contabiliza commits privados _(boolean)_
|
||||
- `line_height` - Define a altura do espaçamento entre o texto _(number)_
|
||||
|
||||
#### Opções exclusivas do cartão de repositórios:
|
||||
|
||||
- `show_owner` - Exibir o nome da pessoa a quem o repositório pertence _(boolean)_
|
||||
|
||||
#### Opções exclusivas do cartão de linguagens:
|
||||
|
||||
- `hide` - Oculta linguagens específicas _(Valores separados por vírgulas)_
|
||||
- `hide_title` - Oculta o título _(boolean)_
|
||||
- `layout` - Alterna entre os dois layouts disponíveis `default` & `compact`
|
||||
- `card_width` - Define a largura do cartão manualmente _(number)_
|
||||
|
||||
> :warning: **Importante:**
|
||||
> Nomes de linguagens devem ser uma sequência escapada de URI, como específicado em [Codificação por cento](https://pt.wikipedia.org/wiki/Codificação_por_cento)
|
||||
> (Isso é: `c++` deve se tornar `c%2B%2B`, `jupyter notebook` deve se tornar `jupyter%20notebook`, etc.)
|
||||
|
||||
---
|
||||
|
||||
# Pins extras do GitHub
|
||||
|
||||
Os Pins extras do GitHub permitem fixar mais de 6 repositórios no seu perfil usando um perfil README.me do GitHub.
|
||||
|
||||
Uhu! Você não está mais limitado a 6 repositórios fixados.
|
||||
|
||||
### Utilização
|
||||
|
||||
Copie e cole esse código no seu README.md e altere os atributos.
|
||||
|
||||
Endpoint: `api/pin?username=anuraghazra&repo=github-readme-stats`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Demonstração
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
Utilize a variável [show_owner](#personalização) para incluir o nome de usuário do proprietária do repositório
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
# Cartão de principais linguagens de programação
|
||||
|
||||
Exibe uma métrica de linguagens de programação mais usadas pelo usuário do GitHub.
|
||||
|
||||
_Nota: As principais linguagens de programação não fazem declarações sobre habilidades pessoais ou similares, é apenas uma figura-chave com base nas estatísticas do GitHub do usuário indicando a frequência com que cada uma foi utilizada._
|
||||
|
||||
### Utilização
|
||||
|
||||
Copie e cole esse código no seu README.md e altere os atributos.
|
||||
|
||||
Endpoint: `api/top-langs?username=anuraghazra`
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Ocultar linguagens individualmente
|
||||
|
||||
Utilize o parâmetro `?hide=language1,language2` para ocultar linguagens específicas.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Layout de cartão de linguagens compacto
|
||||
|
||||
Utilize a opção `&layout=compact` para mudar o layout do cartão.
|
||||
|
||||
```md
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
```
|
||||
|
||||
### Demonstração
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
- Layout compacto
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Todas as demonstrações
|
||||
|
||||
- Padronizado
|
||||
|
||||

|
||||
|
||||
- Ocultando estatísticas específicas
|
||||
|
||||

|
||||
|
||||
- Mostrando ícones
|
||||
|
||||

|
||||
|
||||
- Incluir todos os commits
|
||||
|
||||

|
||||
|
||||
- Temas
|
||||
|
||||
Escolha entre um dos [temas predefinidos](#temas)
|
||||
|
||||

|
||||
|
||||
- Personalizando o cartão de estatísticas
|
||||
|
||||

|
||||
|
||||
- Customizando o cartão de repositório
|
||||
|
||||

|
||||
|
||||
- Principais linguagens
|
||||
|
||||
[](https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
---
|
||||
|
||||
### Dica (Alinhandos os cartões de repositório)
|
||||
|
||||
Por padrão, você não poderá organizar as imagens lado a lado. Para fazer isso, você pode usar a seguinte abordagem:
|
||||
|
||||
```md
|
||||
<a href="https://github.com/anuraghazra/github-readme-stats">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats" />
|
||||
</a>
|
||||
<a href="https://github.com/anuraghazra/convoychat">
|
||||
<img align="left" src="https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=convoychat" />
|
||||
</a>
|
||||
```
|
||||
|
||||
## Implante em sua própria instância do Vercel
|
||||
|
||||
Como a API do GitHub permite apenas 5 mil solicitações por hora, é possível que minha `https://github-readme-stats.vercel.app/api` atinja a cota limite. Se hospedar em seu próprio servidor Vercel, não precisará se preocupar com nada. Clique no botão de implantação para começar!
|
||||
|
||||
Nota: Desde [#58](https://github.com/anuraghazra/github-readme-stats/pull/58) há possibilidade de lidar com mais de 5 mil chamadas por hora, sem interrupções :D
|
||||
|
||||
[](https://vercel.com/import/project?template=https://github.com/anuraghazra/github-readme-stats)
|
||||
|
||||
<details>
|
||||
<summary>Guia de configuração do Vercel</summary>
|
||||
|
||||
1. Acesse [vercel.com](https://vercel.com/)
|
||||
1. Clique em `Login`
|
||||

|
||||
1. Acesse com o GitHub clicando em `Continue with GitHub`
|
||||

|
||||
1. Entre no GitHub e permita acesso a todos os repositórios, se solicitado
|
||||
1. Faça Fork neste repositório
|
||||
1. Volte ao seu [painel principal do Vercel](https://vercel.com/dashboard)
|
||||
1. Selecione `Import Project`
|
||||

|
||||
1. Selecione `Import Git Repository`
|
||||

|
||||
1. Selecione a raiz e mantenha tudo como está, basta adicionar sua variável de ambiente chamada PAT_1 (que será exibida), que conterá um token de acesso pessoal (PAT), que você pode criar facilmente [aqui](https://github.com/settings/tokens/new) (deixe tudo como está, apenas dê um nome, que pode ser o que você quiser)
|
||||

|
||||
1. Clique em `deploy` e já estará tudo pronto. Veja seus domínios para usar a API!
|
||||
|
||||
</details>
|
||||
|
||||
## :sparkling_heart: Apoie o projeto
|
||||
|
||||
|
||||
Disponibilizo como código aberto quase tudo o que posso e tento responder a todos que precisam de ajuda para utilizar esses projetos. Claro,
|
||||
isso demanda tempo. Utilize este serviço gratuitamente.
|
||||
|
||||
No entanto, se você utilizar este projeto e estiver satisfeito com ele, ou apenas quiser me encorajar a continuar criando coisas, existem algumas formas fazê-lo:
|
||||
|
||||
- Dando os devidos créditos ao usar github-readme-stats no seu README.me, adicionando uma referência ao projeto :D
|
||||
- Dando uma estrela (Starring) e compartilhando o projeto 🚀
|
||||
- [](https://www.paypal.me/anuraghazra) - Você pode fazer doações únicas via PayPal. Provavelmente vou comprar um ~~café~~ chá. :tea:
|
||||
|
||||
Obrigado! :heart:
|
||||
|
||||
---
|
||||
|
||||
Contribuições são bem-vindas! <3
|
||||
|
||||
Feito com :heart: e JavaScript.
|
||||
@@ -0,0 +1,77 @@
|
||||
const core = require("@actions/core");
|
||||
const github = require("@actions/github");
|
||||
const parse = require("parse-diff");
|
||||
require("dotenv").config();
|
||||
|
||||
const parsePullRequestId = (githubRef) => {
|
||||
const result = /refs\/pull\/(\d+)\/merge/g.exec(githubRef);
|
||||
if (!result) {
|
||||
console.log("Reference not found.");
|
||||
return 297;
|
||||
}
|
||||
const [, pullRequestId] = result;
|
||||
return pullRequestId;
|
||||
};
|
||||
|
||||
async function run() {
|
||||
try {
|
||||
const token = core.getInput("token");
|
||||
const octokit = github.getOctokit(token || process.env.PERSONAL_TOKEN);
|
||||
const pullRequestId = parsePullRequestId(process.env.GITHUB_REF);
|
||||
|
||||
let res = await octokit.pulls.get({
|
||||
owner: "anuraghazra",
|
||||
repo: "github-readme-stats",
|
||||
pull_number: pullRequestId,
|
||||
mediaType: {
|
||||
format: "diff",
|
||||
},
|
||||
});
|
||||
|
||||
let diff = parse(res.data);
|
||||
let colorStrings = diff
|
||||
.find((file) => file.to === "themes/index.js")
|
||||
.chunks[0].changes.filter((c) => c.type === "add")
|
||||
.map((c) => c.content.replace("+", ""))
|
||||
.join("");
|
||||
|
||||
let matches = colorStrings.match(/(title_color:.*bg_color.*\")/);
|
||||
let colors = matches && matches[0].split(",");
|
||||
|
||||
if (!colors) {
|
||||
await octokit.issues.createComment({
|
||||
owner: "anuraghazra",
|
||||
repo: "github-readme-stats",
|
||||
body: `
|
||||
\rTheme preview (bot)
|
||||
Cannot create theme preview
|
||||
`,
|
||||
issue_number: pullRequestId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
colors = colors.map((color) =>
|
||||
color.replace(/.*\:\s/, "").replace(/\"/g, "")
|
||||
);
|
||||
|
||||
let titleColor = colors[0];
|
||||
let iconColor = colors[1];
|
||||
let textColor = colors[2];
|
||||
let bgColor = colors[3];
|
||||
const url = `https://github-readme-stats.vercel.app/api?username=anuraghazra&title_color=${titleColor}&icon_color=${iconColor}&text_color=${textColor}&bg_color=${bgColor}&show_icons=true`;
|
||||
|
||||
await octokit.issues.createComment({
|
||||
owner: "anuraghazra",
|
||||
repo: "github-readme-stats",
|
||||
body: `
|
||||
\rTheme preview (bot)
|
||||
\r
|
||||
`,
|
||||
issue_number: pullRequestId,
|
||||
});
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -4,8 +4,9 @@ const {
|
||||
getCardColors,
|
||||
FlexLayout,
|
||||
wrapTextMultiline,
|
||||
} = require("../src/utils");
|
||||
const icons = require("./icons");
|
||||
} = require("../common/utils");
|
||||
const icons = require("../common/icons");
|
||||
const Card = require("../common/Card");
|
||||
const toEmoji = require("emoji-name-map");
|
||||
|
||||
const renderRepoCard = (repo, options = {}) => {
|
||||
@@ -84,68 +85,75 @@ const renderRepoCard = (repo, options = {}) => {
|
||||
`
|
||||
: "";
|
||||
|
||||
const iconWithLabel = (icon, label, testid) => {
|
||||
return `
|
||||
<svg class="icon" y="-12" viewBox="0 0 16 16" version="1.1" width="16" height="16">
|
||||
${icon}
|
||||
</svg>
|
||||
<text data-testid="${testid}" class="gray" x="25">${label}</text>
|
||||
`;
|
||||
};
|
||||
const svgStars =
|
||||
stargazers.totalCount > 0 &&
|
||||
`
|
||||
<svg class="icon" y="-12" viewBox="0 0 16 16" version="1.1" width="16" height="16">
|
||||
${icons.star}
|
||||
</svg>
|
||||
<text data-testid="stargazers" class="gray" x="25">${totalStars}</text>
|
||||
`;
|
||||
|
||||
iconWithLabel(icons.star, totalStars, "stargazers");
|
||||
const svgForks =
|
||||
forkCount > 0 &&
|
||||
`
|
||||
<svg class="icon" y="-12" viewBox="0 0 16 16" version="1.1" width="16" height="16">
|
||||
${icons.fork}
|
||||
</svg>
|
||||
<text data-testid="forkcount" class="gray" x="25">${totalForks}</text>
|
||||
`;
|
||||
forkCount > 0 && iconWithLabel(icons.fork, totalForks, "forkcount");
|
||||
|
||||
return `
|
||||
<svg version="1.1" width="400" height="${height}" viewBox="0 0 400 ${height}" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.header { font: 600 18px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${titleColor} }
|
||||
.description { font: 400 13px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
|
||||
.gray { font: 400 12px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
|
||||
.icon { fill: ${iconColor} }
|
||||
.badge { font: 600 11px 'Segoe UI', Ubuntu, Sans-Serif; }
|
||||
.badge rect { opacity: 0.2 }
|
||||
</style>
|
||||
const starAndForkCount = FlexLayout({
|
||||
items: [svgStars, svgForks],
|
||||
gap: 65,
|
||||
}).join("");
|
||||
|
||||
<rect data-testid="card-bg" x="0.5" y="0.5" width="399" height="99%" rx="4.5" fill="${bgColor}" stroke="#E4E2E2"/>
|
||||
<svg class="icon" x="25" y="25" viewBox="0 0 16 16" version="1.1" width="16" height="16">
|
||||
${icons.contribs}
|
||||
</svg>
|
||||
const card = new Card({
|
||||
title: header,
|
||||
titlePrefixIcon: icons.contribs,
|
||||
width: 400,
|
||||
height,
|
||||
colors: {
|
||||
titleColor,
|
||||
textColor,
|
||||
iconColor,
|
||||
bgColor,
|
||||
},
|
||||
});
|
||||
|
||||
<text x="50" y="38" class="header">${header}</text>
|
||||
card.disableAnimations();
|
||||
card.setHideBorder(false);
|
||||
card.setHideTitle(false);
|
||||
card.setCSS(`
|
||||
.description { font: 400 13px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
|
||||
.gray { font: 400 12px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
|
||||
.icon { fill: ${iconColor} }
|
||||
.badge { font: 600 11px 'Segoe UI', Ubuntu, Sans-Serif; }
|
||||
.badge rect { opacity: 0.2 }
|
||||
`);
|
||||
|
||||
${
|
||||
isTemplate
|
||||
? getBadgeSVG("Template")
|
||||
: isArchived
|
||||
? getBadgeSVG("Archived")
|
||||
: ""
|
||||
}
|
||||
return card.render(`
|
||||
${
|
||||
isTemplate
|
||||
? getBadgeSVG("Template")
|
||||
: isArchived
|
||||
? getBadgeSVG("Archived")
|
||||
: ""
|
||||
}
|
||||
|
||||
<text class="description" x="25" y="50">
|
||||
${multiLineDescription
|
||||
.map((line) => `<tspan dy="1.2em" x="25">${encodeHTML(line)}</tspan>`)
|
||||
.join("")}
|
||||
</text>
|
||||
<text class="description" x="25" y="-5">
|
||||
${multiLineDescription
|
||||
.map((line) => `<tspan dy="1.2em" x="25">${encodeHTML(line)}</tspan>`)
|
||||
.join("")}
|
||||
</text>
|
||||
|
||||
<g transform="translate(0, ${height - 20})">
|
||||
${svgLanguage}
|
||||
<g transform="translate(0, ${height - 75})">
|
||||
${svgLanguage}
|
||||
|
||||
<g
|
||||
data-testid="star-fork-group"
|
||||
transform="translate(${primaryLanguage ? 155 - shiftText : 25}, 0)"
|
||||
>
|
||||
${FlexLayout({ items: [svgStars, svgForks], gap: 65 }).join("")}
|
||||
</g>
|
||||
<g
|
||||
data-testid="star-fork-group"
|
||||
transform="translate(${primaryLanguage ? 155 - shiftText : 25}, 0)"
|
||||
>
|
||||
${starAndForkCount}
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
</g>
|
||||
`);
|
||||
};
|
||||
|
||||
module.exports = renderRepoCard;
|
||||
@@ -3,11 +3,20 @@ const {
|
||||
getCardColors,
|
||||
FlexLayout,
|
||||
encodeHTML,
|
||||
} = require("../src/utils");
|
||||
const getStyles = require("./getStyles");
|
||||
const icons = require("./icons");
|
||||
} = require("../common/utils");
|
||||
const { getStyles } = require("../getStyles");
|
||||
const icons = require("../common/icons");
|
||||
const Card = require("../common/Card");
|
||||
|
||||
const createTextNode = ({ icon, label, value, id, index, showIcons }) => {
|
||||
const createTextNode = ({
|
||||
icon,
|
||||
label,
|
||||
value,
|
||||
id,
|
||||
index,
|
||||
showIcons,
|
||||
shiftValuePos,
|
||||
}) => {
|
||||
const kValue = kFormatter(value);
|
||||
const staggerDelay = (index + 3) * 150;
|
||||
|
||||
@@ -23,7 +32,12 @@ const createTextNode = ({ icon, label, value, id, index, showIcons }) => {
|
||||
<g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">
|
||||
${iconSvg}
|
||||
<text class="stat bold" ${labelOffset} y="12.5">${label}:</text>
|
||||
<text class="stat" x="135" y="12.5" data-testid="${id}">${kValue}</text>
|
||||
<text
|
||||
class="stat"
|
||||
x="${shiftValuePos ? (showIcons ? 200 : 170) : 150}"
|
||||
y="12.5"
|
||||
data-testid="${id}"
|
||||
>${kValue}</text>
|
||||
</g>
|
||||
`;
|
||||
};
|
||||
@@ -44,6 +58,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
||||
hide_title = false,
|
||||
hide_border = false,
|
||||
hide_rank = false,
|
||||
include_all_commits = false,
|
||||
line_height = 25,
|
||||
title_color,
|
||||
icon_color,
|
||||
@@ -52,7 +67,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
||||
theme = "default",
|
||||
} = options;
|
||||
|
||||
const lheight = parseInt(line_height);
|
||||
const lheight = parseInt(line_height, 10);
|
||||
|
||||
// returns theme based colors with proper overrides and defaults
|
||||
const { titleColor, textColor, iconColor, bgColor } = getCardColors({
|
||||
@@ -73,7 +88,9 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
||||
},
|
||||
commits: {
|
||||
icon: icons.commits,
|
||||
label: "Total Commits",
|
||||
label: `Total Commits${
|
||||
include_all_commits ? "" : ` (${new Date().getFullYear()})`
|
||||
}`,
|
||||
value: totalCommits,
|
||||
id: "commits",
|
||||
},
|
||||
@@ -106,6 +123,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
||||
...STATS[key],
|
||||
index,
|
||||
showIcons: show_icons,
|
||||
shiftValuePos: !include_all_commits,
|
||||
})
|
||||
);
|
||||
|
||||
@@ -116,44 +134,11 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
||||
hide_rank ? 0 : 150
|
||||
);
|
||||
|
||||
// the better user's score the the rank will be closer to zero so
|
||||
// subtracting 100 to get the progress in 100%
|
||||
const progress = 100 - rank.score;
|
||||
|
||||
const styles = getStyles({
|
||||
titleColor,
|
||||
textColor,
|
||||
iconColor,
|
||||
show_icons,
|
||||
progress,
|
||||
});
|
||||
|
||||
// Conditionally rendered elements
|
||||
|
||||
const apostrophe = ["x", "s"].includes(name.slice(-1)) ? "" : "s";
|
||||
const title = hide_title
|
||||
? ""
|
||||
: `<text x="25" y="35" class="header">${encodeHTML(name)}'${apostrophe} GitHub Stats</text>`;
|
||||
|
||||
const border = `
|
||||
<rect
|
||||
data-testid="card-bg"
|
||||
x="0.5"
|
||||
y="0.5"
|
||||
width="494"
|
||||
height="99%"
|
||||
rx="4.5"
|
||||
fill="${bgColor}"
|
||||
stroke="#E4E2E2"
|
||||
stroke-opacity="${hide_border ? 0 : 1}"
|
||||
/>
|
||||
`;
|
||||
|
||||
const rankCircle = hide_rank
|
||||
? ""
|
||||
: `<g data-testid="rank-circle" transform="translate(400, ${
|
||||
height / 1.85
|
||||
})">
|
||||
: `<g data-testid="rank-circle"
|
||||
transform="translate(400, ${height / 2 - 50})">
|
||||
<circle class="rank-circle-rim" cx="-10" cy="8" r="40" />
|
||||
<circle class="rank-circle" cx="-10" cy="8" r="40" />
|
||||
<g class="rank-text">
|
||||
@@ -169,34 +154,45 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
||||
</g>
|
||||
</g>`;
|
||||
|
||||
if (hide_title) {
|
||||
height -= 30;
|
||||
}
|
||||
// the better user's score the the rank will be closer to zero so
|
||||
// subtracting 100 to get the progress in 100%
|
||||
const progress = 100 - rank.score;
|
||||
const cssStyles = getStyles({
|
||||
titleColor,
|
||||
textColor,
|
||||
iconColor,
|
||||
show_icons,
|
||||
progress,
|
||||
});
|
||||
|
||||
return `
|
||||
<svg width="495" height="${height}" viewBox="0 0 495 ${height}" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
${styles}
|
||||
</style>
|
||||
|
||||
${border}
|
||||
${title}
|
||||
const apostrophe = ["x", "s"].includes(name.slice(-1)) ? "" : "s";
|
||||
const card = new Card({
|
||||
title: `${encodeHTML(name)}'${apostrophe} GitHub Stats`,
|
||||
width: 495,
|
||||
height,
|
||||
colors: {
|
||||
titleColor,
|
||||
textColor,
|
||||
iconColor,
|
||||
bgColor,
|
||||
},
|
||||
});
|
||||
|
||||
<g data-testid="card-body-content" transform="translate(0, ${
|
||||
hide_title ? -30 : 0
|
||||
})">
|
||||
${rankCircle}
|
||||
card.setHideBorder(hide_border);
|
||||
card.setHideTitle(hide_title);
|
||||
card.setCSS(cssStyles);
|
||||
|
||||
<svg x="0" y="55">
|
||||
${FlexLayout({
|
||||
items: statItems,
|
||||
gap: lheight,
|
||||
direction: "column",
|
||||
}).join("")}
|
||||
</svg>
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
return card.render(`
|
||||
${rankCircle}
|
||||
|
||||
<svg x="0" y="0">
|
||||
${FlexLayout({
|
||||
items: statItems,
|
||||
gap: lheight,
|
||||
direction: "column",
|
||||
}).join("")}
|
||||
</svg>
|
||||
`);
|
||||
};
|
||||
|
||||
module.exports = renderStatsCard;
|
||||
@@ -1,4 +1,5 @@
|
||||
const { getCardColors, FlexLayout, clampValue } = require("../src/utils");
|
||||
const { getCardColors, FlexLayout, clampValue } = require("../common/utils");
|
||||
const Card = require("../common/Card");
|
||||
|
||||
const createProgressNode = ({ width, color, name, progress }) => {
|
||||
const paddingRight = 95;
|
||||
@@ -63,6 +64,7 @@ const lowercaseTrim = (name) => name.toLowerCase().trim();
|
||||
const renderTopLanguages = (topLangs, options = {}) => {
|
||||
const {
|
||||
hide_title,
|
||||
hide_border,
|
||||
card_width,
|
||||
title_color,
|
||||
text_color,
|
||||
@@ -170,29 +172,29 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
||||
}).join("");
|
||||
}
|
||||
|
||||
if (hide_title) {
|
||||
height -= 30;
|
||||
}
|
||||
const card = new Card({
|
||||
title: "Most Used Languages",
|
||||
width,
|
||||
height,
|
||||
colors: {
|
||||
titleColor,
|
||||
textColor,
|
||||
bgColor,
|
||||
},
|
||||
});
|
||||
|
||||
return `
|
||||
<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.header { font: 600 18px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${titleColor} }
|
||||
.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
|
||||
</style>
|
||||
<rect data-testid="card-bg" x="0.5" y="0.5" width="99.7%" height="99%" rx="4.5" fill="${bgColor}" stroke="#E4E2E2"/>
|
||||
card.disableAnimations();
|
||||
card.setHideBorder(hide_border);
|
||||
card.setHideTitle(hide_title);
|
||||
card.setCSS(`
|
||||
.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
|
||||
`);
|
||||
|
||||
${
|
||||
hide_title
|
||||
? ""
|
||||
: `<text data-testid="header" x="25" y="35" class="header">Most Used Languages</text>`
|
||||
}
|
||||
|
||||
<svg data-testid="lang-items" x="25" y="${hide_title ? 25 : 55}">
|
||||
${finalLayout}
|
||||
</svg>
|
||||
return card.render(`
|
||||
<svg data-testid="lang-items" x="25">
|
||||
${finalLayout}
|
||||
</svg>
|
||||
`;
|
||||
`);
|
||||
};
|
||||
|
||||
module.exports = renderTopLanguages;
|
||||
@@ -0,0 +1,139 @@
|
||||
const { FlexLayout } = require("../common/utils");
|
||||
const { getAnimations } = require("../getStyles");
|
||||
|
||||
class Card {
|
||||
constructor({
|
||||
width = 100,
|
||||
height = 100,
|
||||
colors = {},
|
||||
title = "",
|
||||
titlePrefixIcon,
|
||||
}) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.hideBorder = false;
|
||||
this.hideTitle = false;
|
||||
|
||||
// returns theme based colors with proper overrides and defaults
|
||||
this.colors = colors;
|
||||
this.title = title;
|
||||
this.css = "";
|
||||
|
||||
this.paddingX = 25;
|
||||
this.paddingY = 35;
|
||||
this.titlePrefixIcon = titlePrefixIcon;
|
||||
this.animations = true;
|
||||
}
|
||||
|
||||
disableAnimations() {
|
||||
this.animations = false;
|
||||
}
|
||||
|
||||
setCSS(value) {
|
||||
this.css = value;
|
||||
}
|
||||
|
||||
setHideBorder(value) {
|
||||
this.hideBorder = value;
|
||||
}
|
||||
|
||||
setHideTitle(value) {
|
||||
this.hideTitle = value;
|
||||
if (value) {
|
||||
this.height -= 30;
|
||||
}
|
||||
}
|
||||
|
||||
setTitle(text) {
|
||||
this.title = text;
|
||||
}
|
||||
|
||||
renderTitle() {
|
||||
const titleText = `
|
||||
<text
|
||||
x="0"
|
||||
y="0"
|
||||
class="header"
|
||||
data-testid="header"
|
||||
>${this.title}</text>
|
||||
`;
|
||||
|
||||
const prefixIcon = `
|
||||
<svg
|
||||
class="icon"
|
||||
x="0"
|
||||
y="-13"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
${this.titlePrefixIcon}
|
||||
</svg>
|
||||
`;
|
||||
return `
|
||||
<g
|
||||
data-testid="card-title"
|
||||
transform="translate(${this.paddingX}, ${this.paddingY})"
|
||||
>
|
||||
${FlexLayout({
|
||||
items: [this.titlePrefixIcon && prefixIcon, titleText],
|
||||
gap: 25,
|
||||
}).join("")}
|
||||
</g>
|
||||
`;
|
||||
}
|
||||
|
||||
render(body) {
|
||||
return `
|
||||
<svg
|
||||
width="${this.width}"
|
||||
height="${this.height}"
|
||||
viewBox="0 0 ${this.width} ${this.height}"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<style>
|
||||
.header {
|
||||
font: 600 18px 'Segoe UI', Ubuntu, Sans-Serif;
|
||||
fill: ${this.colors.titleColor};
|
||||
animation: fadeInAnimation 0.8s ease-in-out forwards;
|
||||
}
|
||||
${this.css}
|
||||
|
||||
${
|
||||
process.env.NODE_ENV === "test" || !this.animations
|
||||
? ""
|
||||
: getAnimations()
|
||||
}
|
||||
</style>
|
||||
|
||||
<rect
|
||||
data-testid="card-bg"
|
||||
x="0.5"
|
||||
y="0.5"
|
||||
rx="4.5"
|
||||
height="99%"
|
||||
stroke="#E4E2E2"
|
||||
width="${this.width - 1}"
|
||||
fill="${this.colors.bgColor}"
|
||||
stroke-opacity="${this.hideBorder ? 0 : 1}"
|
||||
/>
|
||||
|
||||
${this.hideTitle ? "" : this.renderTitle()}
|
||||
|
||||
<g
|
||||
data-testid="main-card-body"
|
||||
transform="translate(0, ${
|
||||
this.hideTitle ? this.paddingX : this.paddingY + 20
|
||||
})"
|
||||
>
|
||||
${body}
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Card;
|
||||
@@ -1,4 +1,4 @@
|
||||
const { logger } = require("./utils");
|
||||
const { logger } = require("../common/utils");
|
||||
|
||||
const retryer = async (fetcher, variables, retries = 0) => {
|
||||
if (retries > 7) {
|
||||
@@ -1,6 +1,6 @@
|
||||
const axios = require("axios");
|
||||
const wrap = require("word-wrap");
|
||||
const themes = require("../themes");
|
||||
const themes = require("../../themes");
|
||||
|
||||
const renderError = (message, secondaryMessage = "") => {
|
||||
return `
|
||||
@@ -13,7 +13,7 @@ const renderError = (message, secondaryMessage = "") => {
|
||||
<rect x="0.5" y="0.5" width="494" height="99%" rx="4.5" fill="#FFFEFE" stroke="#E4E2E2"/>
|
||||
<text x="25" y="45" class="text">Something went wrong! file an issue at https://git.io/JJmN9</text>
|
||||
<text data-testid="message" x="25" y="55" class="text small">
|
||||
<tspan x="25" dy="18">${message}</tspan>
|
||||
<tspan x="25" dy="18">${encodeHTML(message)}</tspan>
|
||||
<tspan x="25" dy="18" class="gray">${secondaryMessage}</tspan>
|
||||
</text>
|
||||
</svg>
|
||||
@@ -1,5 +1,5 @@
|
||||
const { request } = require("./utils");
|
||||
const retryer = require("./retryer");
|
||||
const { request } = require("../common/utils");
|
||||
const retryer = require("../common/retryer");
|
||||
|
||||
const fetcher = (variables, token) => {
|
||||
return request(
|
||||
@@ -1,6 +1,9 @@
|
||||
const { request, logger } = require("./utils");
|
||||
const retryer = require("./retryer");
|
||||
const calculateRank = require("./calculateRank");
|
||||
const { request, logger } = require("../common/utils");
|
||||
const axios = require("axios");
|
||||
const retryer = require("../common/retryer");
|
||||
const calculateRank = require("../calculateRank");
|
||||
const githubUsernameRegex = require("github-username-regex");
|
||||
|
||||
require("dotenv").config();
|
||||
|
||||
const fetcher = (variables, token) => {
|
||||
@@ -46,7 +49,45 @@ const fetcher = (variables, token) => {
|
||||
);
|
||||
};
|
||||
|
||||
async function fetchStats(username, count_private = false) {
|
||||
// https://github.com/anuraghazra/github-readme-stats/issues/92#issuecomment-661026467
|
||||
// https://github.com/anuraghazra/github-readme-stats/pull/211/
|
||||
const totalCommitsFetcher = async (username) => {
|
||||
if (!githubUsernameRegex.test(username)) {
|
||||
logger.log("Invalid username");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// https://developer.github.com/v3/search/#search-commits
|
||||
const fetchTotalCommits = (variables, token) => {
|
||||
return axios({
|
||||
method: "get",
|
||||
url: `https://api.github.com/search/commits?q=author:${variables.login}`,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/vnd.github.cloak-preview",
|
||||
Authorization: `bearer ${token}`,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
let res = await retryer(fetchTotalCommits, { login: username });
|
||||
if (res.data.total_count) {
|
||||
return res.data.total_count;
|
||||
}
|
||||
} catch (err) {
|
||||
logger.log(err);
|
||||
// just return 0 if there is something wrong so that
|
||||
// we don't break the whole app
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
async function fetchStats(
|
||||
username,
|
||||
count_private = false,
|
||||
include_all_commits = false
|
||||
) {
|
||||
if (!username) throw Error("Invalid username");
|
||||
|
||||
const stats = {
|
||||
@@ -61,6 +102,11 @@ async function fetchStats(username, count_private = false) {
|
||||
|
||||
let res = await retryer(fetcher, { login: username });
|
||||
|
||||
let experimental_totalCommits = 0;
|
||||
if (include_all_commits) {
|
||||
experimental_totalCommits = await totalCommitsFetcher(username);
|
||||
}
|
||||
|
||||
if (res.data.errors) {
|
||||
logger.error(res.data.errors);
|
||||
throw Error(res.data.errors[0].message || "Could not fetch user");
|
||||
@@ -72,11 +118,11 @@ async function fetchStats(username, count_private = false) {
|
||||
stats.name = user.name || user.login;
|
||||
stats.totalIssues = user.issues.totalCount;
|
||||
|
||||
stats.totalCommits = contributionCount.totalCommitContributions;
|
||||
stats.totalCommits =
|
||||
contributionCount.totalCommitContributions + experimental_totalCommits;
|
||||
|
||||
if (count_private) {
|
||||
stats.totalCommits =
|
||||
contributionCount.totalCommitContributions +
|
||||
contributionCount.restrictedContributionsCount;
|
||||
stats.totalCommits += contributionCount.restrictedContributionsCount;
|
||||
}
|
||||
|
||||
stats.totalPRs = user.pullRequests.totalCount;
|
||||
@@ -1,5 +1,5 @@
|
||||
const { request, logger } = require("./utils");
|
||||
const retryer = require("./retryer");
|
||||
const { request, logger } = require("../common/utils");
|
||||
const retryer = require("../common/retryer");
|
||||
require("dotenv").config();
|
||||
|
||||
const fetcher = (variables, token) => {
|
||||
@@ -49,14 +49,14 @@ async function fetchTopLanguages(username) {
|
||||
.filter((node) => {
|
||||
return node.languages.edges.length > 0;
|
||||
})
|
||||
// flatten the list of language nodes
|
||||
// flatten the list of language nodes
|
||||
.reduce((acc, curr) => curr.languages.edges.concat(acc), [])
|
||||
.sort((a, b) => b.size - a.size)
|
||||
.reduce((acc, prev) => {
|
||||
// get the size of the language (bytes)
|
||||
let langSize = prev.size;
|
||||
|
||||
// if we already have the language in the accumulator
|
||||
// if we already have the language in the accumulator
|
||||
// & the current language name is same as previous name
|
||||
// add the size to the language size.
|
||||
if (acc[prev.node.name] && prev.node.name === acc[prev.node.name].name) {
|
||||
+23
-23
@@ -9,10 +9,23 @@ const calculateCircleProgress = (value) => {
|
||||
return percentage;
|
||||
};
|
||||
|
||||
const getAnimations = ({ progress }) => {
|
||||
const getProgressAnimation = ({ progress }) => {
|
||||
return `
|
||||
@keyframes rankAnimation {
|
||||
from {
|
||||
stroke-dashoffset: ${calculateCircleProgress(0)};
|
||||
}
|
||||
to {
|
||||
stroke-dashoffset: ${calculateCircleProgress(progress)};
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
||||
|
||||
const getAnimations = () => {
|
||||
return `
|
||||
/* Animations */
|
||||
@keyframes scaleIn {
|
||||
@keyframes scaleInAnimation {
|
||||
from {
|
||||
transform: translate(-5px, 5px) scale(0);
|
||||
}
|
||||
@@ -20,7 +33,7 @@ const getAnimations = ({ progress }) => {
|
||||
transform: translate(-5px, 5px) scale(1);
|
||||
}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
@keyframes fadeInAnimation {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
@@ -28,14 +41,6 @@ const getAnimations = ({ progress }) => {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes rankAnimation {
|
||||
from {
|
||||
stroke-dashoffset: ${calculateCircleProgress(0)};
|
||||
}
|
||||
to {
|
||||
stroke-dashoffset: ${calculateCircleProgress(progress)};
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
||||
|
||||
@@ -47,20 +52,16 @@ const getStyles = ({
|
||||
progress,
|
||||
}) => {
|
||||
return `
|
||||
.header {
|
||||
font: 600 18px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${titleColor};
|
||||
animation: fadeIn 0.8s ease-in-out forwards;
|
||||
}
|
||||
.stat {
|
||||
.stat {
|
||||
font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${textColor};
|
||||
}
|
||||
.stagger {
|
||||
.stagger {
|
||||
opacity: 0;
|
||||
animation: fadeIn 0.3s ease-in-out forwards;
|
||||
animation: fadeInAnimation 0.3s ease-in-out forwards;
|
||||
}
|
||||
.rank-text {
|
||||
.rank-text {
|
||||
font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor};
|
||||
animation: scaleIn 0.3s ease-in-out forwards;
|
||||
animation: scaleInAnimation 0.3s ease-in-out forwards;
|
||||
}
|
||||
|
||||
.bold { font-weight: 700 }
|
||||
@@ -86,9 +87,8 @@ const getStyles = ({
|
||||
transform: rotate(-90deg);
|
||||
animation: rankAnimation 1s forwards ease-in-out;
|
||||
}
|
||||
|
||||
${process.env.NODE_ENV === "test" ? "" : getAnimations({ progress })}
|
||||
${process.env.NODE_ENV === "test" ? "" : getProgressAnimation({ progress })}
|
||||
`;
|
||||
};
|
||||
|
||||
module.exports = getStyles;
|
||||
module.exports = { getStyles, getAnimations };
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@ require("@testing-library/jest-dom");
|
||||
const axios = require("axios");
|
||||
const MockAdapter = require("axios-mock-adapter");
|
||||
const api = require("../api/index");
|
||||
const renderStatsCard = require("../src/renderStatsCard");
|
||||
const { renderError, CONSTANTS } = require("../src/utils");
|
||||
const renderStatsCard = require("../src/cards/stats-card");
|
||||
const { renderError, CONSTANTS } = require("../src/common/utils");
|
||||
const calculateRank = require("../src/calculateRank");
|
||||
|
||||
const stats = {
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
require("@testing-library/jest-dom");
|
||||
const cssToObject = require("css-to-object");
|
||||
const Card = require("../src/common/Card");
|
||||
const icons = require("../src/common/icons");
|
||||
const { getCardColors } = require("../src/common/utils");
|
||||
const { queryByTestId } = require("@testing-library/dom");
|
||||
|
||||
describe("Card", () => {
|
||||
it("should hide border", () => {
|
||||
const card = new Card({});
|
||||
card.setHideBorder(true);
|
||||
|
||||
document.body.innerHTML = card.render(``);
|
||||
expect(queryByTestId(document.body, "card-bg")).toHaveAttribute(
|
||||
"stroke-opacity",
|
||||
"0"
|
||||
);
|
||||
});
|
||||
|
||||
it("should not hide border", () => {
|
||||
const card = new Card({});
|
||||
card.setHideBorder(false);
|
||||
|
||||
document.body.innerHTML = card.render(``);
|
||||
expect(queryByTestId(document.body, "card-bg")).toHaveAttribute(
|
||||
"stroke-opacity",
|
||||
"1"
|
||||
);
|
||||
});
|
||||
|
||||
it("should hide title", () => {
|
||||
const card = new Card({});
|
||||
card.setHideTitle(true);
|
||||
|
||||
document.body.innerHTML = card.render(``);
|
||||
expect(queryByTestId(document.body, "card-title")).toBeNull();
|
||||
});
|
||||
|
||||
it("should not hide title", () => {
|
||||
const card = new Card({});
|
||||
card.setHideTitle(false);
|
||||
|
||||
document.body.innerHTML = card.render(``);
|
||||
expect(queryByTestId(document.body, "card-title")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("title should have prefix icon", () => {
|
||||
const card = new Card({ title: "ok", titlePrefixIcon: icons.contribs });
|
||||
|
||||
document.body.innerHTML = card.render(``);
|
||||
expect(document.getElementsByClassName("icon")[0]).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("title should not have prefix icon", () => {
|
||||
const card = new Card({ title: "ok" });
|
||||
|
||||
document.body.innerHTML = card.render(``);
|
||||
expect(document.getElementsByClassName("icon")[0]).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should have proper height, width", () => {
|
||||
const card = new Card({ height: 200, width: 200, title: "ok" });
|
||||
document.body.innerHTML = card.render(``);
|
||||
expect(document.getElementsByTagName("svg")[0]).toHaveAttribute(
|
||||
"height",
|
||||
"200"
|
||||
);
|
||||
expect(document.getElementsByTagName("svg")[0]).toHaveAttribute(
|
||||
"height",
|
||||
"200"
|
||||
);
|
||||
});
|
||||
|
||||
it("should have less height after title is hidden", () => {
|
||||
const card = new Card({ height: 200, title: "ok" });
|
||||
card.setHideTitle(true);
|
||||
|
||||
document.body.innerHTML = card.render(``);
|
||||
expect(document.getElementsByTagName("svg")[0]).toHaveAttribute(
|
||||
"height",
|
||||
"170"
|
||||
);
|
||||
});
|
||||
|
||||
it("main-card-body should have proper when title is visible", () => {
|
||||
const card = new Card({ height: 200 });
|
||||
document.body.innerHTML = card.render(``);
|
||||
expect(queryByTestId(document.body, "main-card-body")).toHaveAttribute(
|
||||
"transform",
|
||||
"translate(0, 55)"
|
||||
);
|
||||
});
|
||||
|
||||
it("main-card-body should have proper position after title is hidden", () => {
|
||||
const card = new Card({ height: 200 });
|
||||
card.setHideTitle(true);
|
||||
|
||||
document.body.innerHTML = card.render(``);
|
||||
expect(queryByTestId(document.body, "main-card-body")).toHaveAttribute(
|
||||
"transform",
|
||||
"translate(0, 25)"
|
||||
);
|
||||
});
|
||||
|
||||
it("should render with correct colors", () => {
|
||||
// returns theme based colors with proper overrides and defaults
|
||||
const { titleColor, textColor, iconColor, bgColor } = getCardColors({
|
||||
title_color: "f00",
|
||||
icon_color: "0f0",
|
||||
text_color: "00f",
|
||||
bg_color: "fff",
|
||||
theme: "default",
|
||||
});
|
||||
|
||||
const card = new Card({
|
||||
height: 200,
|
||||
colors: {
|
||||
titleColor,
|
||||
textColor,
|
||||
iconColor,
|
||||
bgColor,
|
||||
},
|
||||
});
|
||||
document.body.innerHTML = card.render(``);
|
||||
|
||||
const styleTag = document.querySelector("style");
|
||||
const stylesObject = cssToObject(styleTag.innerHTML);
|
||||
const headerClassStyles = stylesObject[".header"];
|
||||
|
||||
expect(headerClassStyles.fill).toBe("#f00");
|
||||
expect(queryByTestId(document.body, "card-bg")).toHaveAttribute(
|
||||
"fill",
|
||||
"#fff"
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
require("@testing-library/jest-dom");
|
||||
const axios = require("axios");
|
||||
const MockAdapter = require("axios-mock-adapter");
|
||||
const fetchRepo = require("../src/fetchRepo");
|
||||
const fetchRepo = require("../src/fetchers/repo-fetcher");
|
||||
|
||||
const data_repo = {
|
||||
repository: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require("@testing-library/jest-dom");
|
||||
const axios = require("axios");
|
||||
const MockAdapter = require("axios-mock-adapter");
|
||||
const fetchStats = require("../src/fetchStats");
|
||||
const fetchStats = require("../src/fetchers/stats-fetcher");
|
||||
const calculateRank = require("../src/calculateRank");
|
||||
|
||||
const data = {
|
||||
@@ -9,7 +9,10 @@ const data = {
|
||||
user: {
|
||||
name: "Anurag Hazra",
|
||||
repositoriesContributedTo: { totalCount: 61 },
|
||||
contributionsCollection: { totalCommitContributions: 100, restrictedContributionsCount: 50 },
|
||||
contributionsCollection: {
|
||||
totalCommitContributions: 100,
|
||||
restrictedContributionsCount: 50,
|
||||
},
|
||||
pullRequests: { totalCount: 300 },
|
||||
issues: { totalCount: 200 },
|
||||
followers: { totalCount: 100 },
|
||||
@@ -102,4 +105,32 @@ describe("Test fetchStats", () => {
|
||||
rank,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should fetch total commits", async () => {
|
||||
mock.onPost("https://api.github.com/graphql").reply(200, data);
|
||||
mock
|
||||
.onGet("https://api.github.com/search/commits?q=author:anuraghazra")
|
||||
.reply(200, { total_count: 1000 });
|
||||
|
||||
let stats = await fetchStats("anuraghazra", true, true);
|
||||
const rank = calculateRank({
|
||||
totalCommits: 1000 + 150,
|
||||
totalRepos: 5,
|
||||
followers: 100,
|
||||
contributions: 61,
|
||||
stargazers: 400,
|
||||
prs: 300,
|
||||
issues: 200,
|
||||
});
|
||||
|
||||
expect(stats).toStrictEqual({
|
||||
contributedTo: 61,
|
||||
name: "Anurag Hazra",
|
||||
totalCommits: 1000 + 150,
|
||||
totalIssues: 200,
|
||||
totalPRs: 300,
|
||||
totalStars: 400,
|
||||
rank,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require("@testing-library/jest-dom");
|
||||
const axios = require("axios");
|
||||
const MockAdapter = require("axios-mock-adapter");
|
||||
const fetchTopLanguages = require("../src/fetchTopLanguages");
|
||||
const fetchTopLanguages = require("../src/fetchers/top-languages-fetcher");
|
||||
|
||||
const mock = new MockAdapter(axios);
|
||||
|
||||
|
||||
+3
-3
@@ -2,8 +2,8 @@ require("@testing-library/jest-dom");
|
||||
const axios = require("axios");
|
||||
const MockAdapter = require("axios-mock-adapter");
|
||||
const pin = require("../api/pin");
|
||||
const renderRepoCard = require("../src/renderRepoCard");
|
||||
const { renderError } = require("../src/utils");
|
||||
const renderRepoCard = require("../src/cards/repo-card");
|
||||
const { renderError } = require("../src/common/utils");
|
||||
|
||||
const data_repo = {
|
||||
repository: {
|
||||
@@ -17,7 +17,7 @@ const data_repo = {
|
||||
name: "TypeScript",
|
||||
},
|
||||
forkCount: 100,
|
||||
isTemplate: false
|
||||
isTemplate: false,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require("@testing-library/jest-dom");
|
||||
const cssToObject = require("css-to-object");
|
||||
const renderRepoCard = require("../src/renderRepoCard");
|
||||
const renderRepoCard = require("../src/cards/repo-card");
|
||||
|
||||
const { queryByTestId } = require("@testing-library/dom");
|
||||
const themes = require("../themes");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require("@testing-library/jest-dom");
|
||||
const cssToObject = require("css-to-object");
|
||||
const renderStatsCard = require("../src/renderStatsCard");
|
||||
const renderStatsCard = require("../src/cards/stats-card");
|
||||
|
||||
const {
|
||||
getByTestId,
|
||||
@@ -69,20 +69,6 @@ describe("Test renderStatsCard", () => {
|
||||
expect(queryByTestId(document.body, "contribs")).toBeNull();
|
||||
});
|
||||
|
||||
it("should hide_border", () => {
|
||||
document.body.innerHTML = renderStatsCard(stats, { hide_border: true });
|
||||
expect(queryByTestId(document.body, "card-bg")).toHaveAttribute(
|
||||
"stroke-opacity",
|
||||
"0"
|
||||
);
|
||||
|
||||
document.body.innerHTML = renderStatsCard(stats, { hide_border: false });
|
||||
expect(queryByTestId(document.body, "card-bg")).toHaveAttribute(
|
||||
"stroke-opacity",
|
||||
"1"
|
||||
);
|
||||
});
|
||||
|
||||
it("should hide_rank", () => {
|
||||
document.body.innerHTML = renderStatsCard(stats, { hide_rank: true });
|
||||
|
||||
@@ -202,36 +188,6 @@ describe("Test renderStatsCard", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("should hide the title", () => {
|
||||
document.body.innerHTML = renderStatsCard(stats, {
|
||||
hide_title: true,
|
||||
});
|
||||
|
||||
expect(document.getElementsByClassName("header")[0]).toBeUndefined();
|
||||
expect(document.getElementsByTagName("svg")[0]).toHaveAttribute(
|
||||
"height",
|
||||
"165"
|
||||
);
|
||||
expect(queryByTestId(document.body, "card-body-content")).toHaveAttribute(
|
||||
"transform",
|
||||
"translate(0, -30)"
|
||||
);
|
||||
});
|
||||
|
||||
it("should not hide the title", () => {
|
||||
document.body.innerHTML = renderStatsCard(stats, {});
|
||||
|
||||
expect(document.getElementsByClassName("header")[0]).toBeDefined();
|
||||
expect(document.getElementsByTagName("svg")[0]).toHaveAttribute(
|
||||
"height",
|
||||
"195"
|
||||
);
|
||||
expect(queryByTestId(document.body, "card-body-content")).toHaveAttribute(
|
||||
"transform",
|
||||
"translate(0, 0)"
|
||||
);
|
||||
});
|
||||
|
||||
it("should render icons correctly", () => {
|
||||
document.body.innerHTML = renderStatsCard(stats, {
|
||||
show_icons: true,
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
require("@testing-library/jest-dom");
|
||||
const cssToObject = require("css-to-object");
|
||||
const renderTopLanguages = require("../src/renderTopLanguages");
|
||||
const renderTopLanguages = require("../src/cards/top-languages-card");
|
||||
|
||||
const {
|
||||
getByTestId,
|
||||
queryByTestId,
|
||||
queryAllByTestId,
|
||||
} = require("@testing-library/dom");
|
||||
const { queryByTestId, queryAllByTestId } = require("@testing-library/dom");
|
||||
const themes = require("../themes");
|
||||
|
||||
describe("Test renderTopLanguages", () => {
|
||||
@@ -72,7 +68,7 @@ describe("Test renderTopLanguages", () => {
|
||||
|
||||
// multiple languages passed
|
||||
document.body.innerHTML = renderTopLanguages(langs, {
|
||||
hide: ["HTML","css"],
|
||||
hide: ["HTML", "css"],
|
||||
});
|
||||
expect(queryAllByTestId(document.body, "lang-name")[0]).toBeInTheDocument(
|
||||
"javascript"
|
||||
@@ -98,25 +94,6 @@ describe("Test renderTopLanguages", () => {
|
||||
expect(document.querySelector("svg")).toHaveAttribute("height", "245");
|
||||
});
|
||||
|
||||
it("should hide_title", () => {
|
||||
document.body.innerHTML = renderTopLanguages(langs, { hide_title: false });
|
||||
expect(document.querySelector("svg")).toHaveAttribute("height", "205");
|
||||
expect(queryByTestId(document.body, "lang-items")).toHaveAttribute(
|
||||
"y",
|
||||
"55"
|
||||
);
|
||||
|
||||
// Lets hide now
|
||||
document.body.innerHTML = renderTopLanguages(langs, { hide_title: true });
|
||||
expect(document.querySelector("svg")).toHaveAttribute("height", "175");
|
||||
|
||||
expect(queryByTestId(document.body, "header")).not.toBeInTheDocument();
|
||||
expect(queryByTestId(document.body, "lang-items")).toHaveAttribute(
|
||||
"y",
|
||||
"25"
|
||||
);
|
||||
});
|
||||
|
||||
it("should render with custom width set", () => {
|
||||
document.body.innerHTML = renderTopLanguages(langs, {});
|
||||
|
||||
@@ -208,18 +185,35 @@ describe("Test renderTopLanguages", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should render with layout compact', () => {
|
||||
document.body.innerHTML = renderTopLanguages(langs, {layout: 'compact'});
|
||||
it("should render with layout compact", () => {
|
||||
document.body.innerHTML = renderTopLanguages(langs, { layout: "compact" });
|
||||
|
||||
expect(queryByTestId(document.body, "header")).toHaveTextContent("Most Used Languages");
|
||||
expect(queryByTestId(document.body, "header")).toHaveTextContent(
|
||||
"Most Used Languages"
|
||||
);
|
||||
|
||||
expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent("HTML 40.00%");
|
||||
expect(queryAllByTestId(document.body, "lang-progress")[0]).toHaveAttribute("width","120.00");
|
||||
expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
|
||||
"HTML 40.00%"
|
||||
);
|
||||
expect(queryAllByTestId(document.body, "lang-progress")[0]).toHaveAttribute(
|
||||
"width",
|
||||
"120.00"
|
||||
);
|
||||
|
||||
expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent("javascript 40.00%");
|
||||
expect(queryAllByTestId(document.body, "lang-progress")[1]).toHaveAttribute("width","120.00");
|
||||
expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent(
|
||||
"javascript 40.00%"
|
||||
);
|
||||
expect(queryAllByTestId(document.body, "lang-progress")[1]).toHaveAttribute(
|
||||
"width",
|
||||
"120.00"
|
||||
);
|
||||
|
||||
expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent("css 20.00%");
|
||||
expect(queryAllByTestId(document.body, "lang-progress")[2]).toHaveAttribute("width","60.00");
|
||||
})
|
||||
expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent(
|
||||
"css 20.00%"
|
||||
);
|
||||
expect(queryAllByTestId(document.body, "lang-progress")[2]).toHaveAttribute(
|
||||
"width",
|
||||
"60.00"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require("@testing-library/jest-dom");
|
||||
const retryer = require("../src/retryer");
|
||||
const { logger } = require("../src/utils");
|
||||
const retryer = require("../src/common/retryer");
|
||||
const { logger } = require("../src/common/utils");
|
||||
|
||||
const fetcher = jest.fn((variables, token) => {
|
||||
logger.log(variables, token);
|
||||
|
||||
@@ -2,8 +2,8 @@ require("@testing-library/jest-dom");
|
||||
const axios = require("axios");
|
||||
const MockAdapter = require("axios-mock-adapter");
|
||||
const topLangs = require("../api/top-langs");
|
||||
const renderTopLanguages = require("../src/renderTopLanguages");
|
||||
const { renderError } = require("../src/utils");
|
||||
const renderTopLanguages = require("../src/cards/top-languages-card");
|
||||
const { renderError } = require("../src/common/utils");
|
||||
|
||||
const data_langs = {
|
||||
data: {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ const {
|
||||
FlexLayout,
|
||||
getCardColors,
|
||||
wrapTextMultiline,
|
||||
} = require("../src/utils");
|
||||
} = require("../src/common/utils");
|
||||
|
||||
const { queryByTestId } = require("@testing-library/dom");
|
||||
|
||||
|
||||
+10
-2
@@ -22,7 +22,8 @@ Use `?theme=THEME_NAME` parameter like so :-
|
||||
| `highcontrast` ![highcontrast][highcontrast] | `dracula` ![dracula][dracula] | `prussian` ![prussian][prussian] |
|
||||
| `monokai` ![monokai][monokai] | `vue` ![vue][vue] | `shades-of-purple` ![shades-of-purple][shades-of-purple] |
|
||||
| `nightowl` ![nightowl][nightowl] | `buefy` ![buefy][buefy] | `blue-green` ![blue-green][blue-green] |
|
||||
| `algolia` ![algolia][algolia] | `great-gatsby` ![great-gatsby][great-gatsby] | [Add your theme][add-theme] |
|
||||
| `algolia` ![algolia][algolia] | `great-gatsby` ![great-gatsby][great-gatsby] | `bear` ![bear][bear] |
|
||||
| `solarized-dark` ![solarized-dark][solarized-dark] | `solarized-light` ![solarized-light][solarized-light] | [Add your theme][add-theme] |
|
||||
|
||||
## Repo Card
|
||||
|
||||
@@ -36,7 +37,8 @@ Use `?theme=THEME_NAME` parameter like so :-
|
||||
| `highcontrast` ![highcontrast][highcontrast_repo] | `dracula` ![dracula][dracula_repo] | `prussian` ![prussian][prussian_repo] |
|
||||
| `monokai` ![monokai][monokai_repo] | `vue` ![vue][vue_repo] | `shades-of-purple` ![shades-of-purple][shades-of-purple_repo] |
|
||||
| `nightowl` ![nightowl][nightowl_repo] | `buefy` ![buefy][buefy_repo] | `blue-green` ![blue-green][blue-green_repo] |
|
||||
| `algolia` ![algolia][algolia_repo] | `great-gatsby` ![great-gatsby][great-gatsby_repo] | [Add your theme][add-theme] |
|
||||
| `algolia` ![algolia][algolia_repo] | `great-gatsby` ![great-gatsby][great-gatsby_repo] | `bear` ![bear][bear_repo] |
|
||||
| `solarized-dark` ![solarized-dark][solarized-dark_repo] | `solarized-light` ![solarized-light][solarized-light_repo] | [Add your theme][add-theme] |
|
||||
|
||||
|
||||
[default]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=default
|
||||
@@ -60,6 +62,9 @@ Use `?theme=THEME_NAME` parameter like so :-
|
||||
[blue-green]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=blue-green
|
||||
[algolia]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=algolia
|
||||
[great-gatsby]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=great-gatsby
|
||||
[bear]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=bear
|
||||
[solarized-dark]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=solarized-dark
|
||||
[solarized-light]: https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true&hide=contribs,prs&cache_seconds=86400&theme=solarized-light
|
||||
|
||||
|
||||
[default_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=default
|
||||
@@ -83,6 +88,9 @@ Use `?theme=THEME_NAME` parameter like so :-
|
||||
[blue-green_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=blue-green
|
||||
[algolia_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=algolia
|
||||
[great-gatsby_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=great-gatsby
|
||||
[bear_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=bear
|
||||
[solarized-dark_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=solarized-dark
|
||||
[solarized-light_repo]: https://github-readme-stats.vercel.app/api/pin/?username=anuraghazra&repo=github-readme-stats&cache_seconds=86400&theme=solarized-light
|
||||
|
||||
|
||||
[add-theme]: https://github.com/anuraghazra/github-readme-stats/edit/master/themes/index.js
|
||||
|
||||
+32
-2
@@ -113,18 +113,48 @@ const themes = {
|
||||
text_color: "0cf574",
|
||||
bg_color: "040f0f",
|
||||
},
|
||||
"algolia": {
|
||||
algolia: {
|
||||
title_color: "00AEFF",
|
||||
icon_color: "2DDE98",
|
||||
text_color: "FFFFFF",
|
||||
bg_color: "050F2C",
|
||||
},
|
||||
"great-gatsby":{
|
||||
"great-gatsby": {
|
||||
title_color: "ffa726",
|
||||
icon_color: "ffb74d",
|
||||
text_color: "ffd95b",
|
||||
bg_color: "000000",
|
||||
},
|
||||
bear: {
|
||||
title_color: "e03c8a",
|
||||
icon_color: "00AEFF",
|
||||
text_color: "bcb28d",
|
||||
bg_color: "1f2023",
|
||||
},
|
||||
"solarized-dark": {
|
||||
title_color: "268bd2",
|
||||
icon_color: "b58900",
|
||||
text_color: "859900",
|
||||
bg_color: "002b36",
|
||||
},
|
||||
"solarized-light": {
|
||||
title_color: "268bd2",
|
||||
icon_color: "b58900",
|
||||
text_color: "859900",
|
||||
bg_color: "fdf6e3",
|
||||
},
|
||||
nord: {
|
||||
title_color: "81a1c1",
|
||||
text_color: "d8dee9",
|
||||
icon_color: "88c0d0",
|
||||
bg_color: "2e3440",
|
||||
},
|
||||
test: {
|
||||
title_color: "81a1c1",
|
||||
text_color: "d8dee9",
|
||||
icon_color: "88c0d0",
|
||||
bg_color: "2e3440",
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = themes;
|
||||
|
||||
Reference in New Issue
Block a user