forked from mirrored/github-readme-stats
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44d5c1db8b |
@@ -15,7 +15,7 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Expected behavior
|
label: Expected behaviour
|
||||||
description:
|
description:
|
||||||
A clear and concise description of what you expected to happen.
|
A clear and concise description of what you expected to happen.
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
name: prs cache clean
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types:
|
|
||||||
- closed
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cleanup:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Cleanup
|
|
||||||
run: |
|
|
||||||
gh extension install actions/gh-actions-cache
|
|
||||||
|
|
||||||
REPO=${{ github.repository }}
|
|
||||||
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
|
|
||||||
|
|
||||||
echo "Fetching list of cache key"
|
|
||||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
|
|
||||||
|
|
||||||
## Setting this to not fail the workflow while deleting cache keys.
|
|
||||||
set +e
|
|
||||||
echo "Deleting caches..."
|
|
||||||
for cacheKey in $cacheKeysForPR
|
|
||||||
do
|
|
||||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
|
||||||
done
|
|
||||||
echo "Done"
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
@@ -34,4 +34,4 @@ jobs:
|
|||||||
npm run format:check
|
npm run format:check
|
||||||
|
|
||||||
- name: Code Coverage
|
- name: Code Coverage
|
||||||
uses: codecov/codecov-action@v3
|
uses: codecov/codecov-action@v1
|
||||||
|
|||||||
+1
-1
@@ -171,7 +171,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
|
|||||||
|
|
||||||
- `hide` - 从卡片中隐藏指定语言 _(Comma seperated values)_
|
- `hide` - 从卡片中隐藏指定语言 _(Comma seperated values)_
|
||||||
- `hide_title` - _(boolean)_
|
- `hide_title` - _(boolean)_
|
||||||
- `layout` - 提供五種佈局 `normal` & `compact` & `donut` & `donut-vertical` & `pie` 间切换
|
- `layout` - 在两个可用布局 `default` & `compact` 间切换
|
||||||
- `card_width` - 手动设置卡片的宽度 _(number)_
|
- `card_width` - 手动设置卡片的宽度 _(number)_
|
||||||
|
|
||||||
> :warning: **重要:**
|
> :warning: **重要:**
|
||||||
|
|||||||
+5
-5
@@ -161,7 +161,7 @@ Du kannst mehrere, mit Kommas separierte, Werte in der bg_color Option angeben,
|
|||||||
|
|
||||||
- `hide` - Verbirgt die angegebenen Sprachen von der Karte _(Komma separierte Werte)_
|
- `hide` - Verbirgt die angegebenen Sprachen von der Karte _(Komma separierte Werte)_
|
||||||
- `hide_title` - _(Boolean)_
|
- `hide_title` - _(Boolean)_
|
||||||
- `layout` - Wechseln Sie zwischen den fünf verfügbaren Layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`
|
- `layout` - Wechsel zwischen den zwei verfügbaren Layouts `default` & `compact`
|
||||||
- `card_width` - Lege die Breite der Karte manuell fest _(Zahl)_
|
- `card_width` - Lege die Breite der Karte manuell fest _(Zahl)_
|
||||||
|
|
||||||
> :warning: **Wichtig:**
|
> :warning: **Wichtig:**
|
||||||
@@ -253,18 +253,18 @@ Du kannst die `&layout=compact` Option nutzen, um das Kartendesign zu ändern.
|
|||||||
Ändere `?username=` in den eigenen [Wakatime](https://wakatime.com)-Benutzernamen.
|
Ändere `?username=` in den eigenen [Wakatime](https://wakatime.com)-Benutzernamen.
|
||||||
|
|
||||||
```md
|
```md
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Beispiel
|
### Beispiel
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
- Kompaktes Layout
|
- Kompaktes Layout
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -175,7 +175,7 @@ Puedes pasar mútliples valores separados por coma en la opción `bg_color` para
|
|||||||
|
|
||||||
- `hide` - Oculta de la tarjeta los lenguajes especificados _(valores separados por comas)_
|
- `hide` - Oculta de la tarjeta los lenguajes especificados _(valores separados por comas)_
|
||||||
- `hide_title` - _(booleano)_
|
- `hide_title` - _(booleano)_
|
||||||
- `layout` - Cambiar entre los cinco diseños disponibles `normal` & `compact` & `donut` & `donut-vertical` & `pie`
|
- `layout` - Cambia entre los dos diseños disponibles `default` & `compact`
|
||||||
- `card_width` - Establece el ancho de la tarjeta manualmente _(número)_
|
- `card_width` - Establece el ancho de la tarjeta manualmente _(número)_
|
||||||
- `langs_count` - Muestra más lenguajes en la tarjeta, entre 1-10, por defecto 5 _(número)_
|
- `langs_count` - Muestra más lenguajes en la tarjeta, entre 1-10, por defecto 5 _(número)_
|
||||||
- `exclude_repo` - Excluye los repositorios especificados _(valores separados por comas)_
|
- `exclude_repo` - Excluye los repositorios especificados _(valores separados por comas)_
|
||||||
@@ -282,18 +282,18 @@ Puedes usar la opción `& layout = compact` para cambiar el diseño de la tarjet
|
|||||||
cambia el valor del parámetro `?username=` a tu username en [Wakatime](https://wakatime.com).
|
cambia el valor del parámetro `?username=` a tu username en [Wakatime](https://wakatime.com).
|
||||||
|
|
||||||
```md
|
```md
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Ejemplo
|
### Ejemplo
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
- Diseño compacto
|
- Diseño compacto
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -343,7 +343,7 @@ Escoja cualquiera de los [temas por defecto](#themes)
|
|||||||
|
|
||||||
- Tarjeta de Wakatime
|
- Tarjeta de Wakatime
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -171,7 +171,7 @@ Vous pouvez fournir plusieurs valeurs (suivie d'une virgule) dans l'option bg_co
|
|||||||
|
|
||||||
- `hide` - Masquer les langages spécifiés sur la carte _(Comma seperated values)_
|
- `hide` - Masquer les langages spécifiés sur la carte _(Comma seperated values)_
|
||||||
- `hide_title` - Masquer le titre _(boolean)_
|
- `hide_title` - Masquer le titre _(boolean)_
|
||||||
- `layout` - Alterner entre 5 mise en page `normal` & `compact` & `donut` & `donut-vertical` & `pie`
|
- `layout` - Alterner entre 2 mise en page `default` & `compact`
|
||||||
- `card_width` - Fixer la largeur de la carte manuellement _(number)_
|
- `card_width` - Fixer la largeur de la carte manuellement _(number)_
|
||||||
|
|
||||||
> :warning: **Important:**
|
> :warning: **Important:**
|
||||||
|
|||||||
+1
-1
@@ -171,7 +171,7 @@ Puoi fornire valori separati da virgola nel parametro bg_color per creare un gra
|
|||||||
|
|
||||||
- `hide` - Nasconde un linguaggio specifico _(valori separati da virgola)_
|
- `hide` - Nasconde un linguaggio specifico _(valori separati da virgola)_
|
||||||
- `hide_title` - Nasconde il titolo _(booleano)_
|
- `hide_title` - Nasconde il titolo _(booleano)_
|
||||||
- `layout` - Specificare il tipo di layout, `normal` (esteso), `compact` (compatto), `donut` (ciambella), `donut-vertical` (ciambella verticale) e `pie` (torta)
|
- `layout` - Specifica il tipo di layout, `default` (esteso) o `compact` (compatto)
|
||||||
- `card_width` - Specifica il valore della larghezza _(numero)_
|
- `card_width` - Specifica il valore della larghezza _(numero)_
|
||||||
|
|
||||||
> :warning: **Importante:**
|
> :warning: **Importante:**
|
||||||
|
|||||||
+1
-1
@@ -174,7 +174,7 @@ bg_color オプションで複数のカンマ区切りの値を指定してグ
|
|||||||
|
|
||||||
- `hide` - 特定の言語を隠す _(カンマ区切りで指定)_
|
- `hide` - 特定の言語を隠す _(カンマ区切りで指定)_
|
||||||
- `hide_title` - _(boolean)_
|
- `hide_title` - _(boolean)_
|
||||||
- `layout` - `normal` & `compact` & `donut` & `donut-vertical` & `pie` のいずれかのレイアウトに切り替える
|
- `layout` - `default` か `compact` のいずれかのレイアウトに切り替える
|
||||||
- `card_width` - カードの横幅 _(number)_
|
- `card_width` - カードの横幅 _(number)_
|
||||||
- `langs_count` - 表示される言語の数 _(1 ~ 10, 初期値 5)_
|
- `langs_count` - 表示される言語の数 _(1 ~ 10, 初期値 5)_
|
||||||
- `exclude_repo` - 指定されたリポジトリを除外する _(カンマ区切りで指定)_
|
- `exclude_repo` - 指定されたリポジトリを除外する _(カンマ区切りで指定)_
|
||||||
|
|||||||
+6
-6
@@ -189,7 +189,7 @@ dark, radical, merko, gruvbox, tokyonight, onedark, cobalt, synthwave, highcontr
|
|||||||
|
|
||||||
- `hide` - 카드에서 특정 언어 제외 _(Comma-separated values)_
|
- `hide` - 카드에서 특정 언어 제외 _(Comma-separated values)_
|
||||||
- `hide_title` - 타이틀 제외 _(boolean)_
|
- `hide_title` - 타이틀 제외 _(boolean)_
|
||||||
- `layout` - 5가지 값 사용 가능, `normal` & `compact` & `donut` & `donut-vertical` & `pie` 중 표시 형태 선택
|
- `layout` - 사용 가능한 두 가지 값, `default` & `compact` 중 표시 형태 선택
|
||||||
- `card_width` - 카드 너비 직접 설정 _(number)_
|
- `card_width` - 카드 너비 직접 설정 _(number)_
|
||||||
- `langs_count` - 카드에 표시할 언어의 수 (1-10 사이, 기본 값 : 5) _(number)_
|
- `langs_count` - 카드에 표시할 언어의 수 (1-10 사이, 기본 값 : 5) _(number)_
|
||||||
- `exclude_repo` - 통계에 제외할 저장소 지정 _(Comma-separated values)_
|
- `exclude_repo` - 통계에 제외할 저장소 지정 _(Comma-separated values)_
|
||||||
@@ -298,18 +298,18 @@ _참고:
|
|||||||
`?username=` 속성의 값을 [Wakatime](https://wakatime.com) 계정의 사용자 명(닉네임)으로 바꿔주세요.
|
`?username=` 속성의 값을 [Wakatime](https://wakatime.com) 계정의 사용자 명(닉네임)으로 바꿔주세요.
|
||||||
|
|
||||||
```md
|
```md
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 미리보기
|
### 미리보기
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
- 컴팩트한 레이아웃
|
- 컴팩트한 레이아웃
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -359,7 +359,7 @@ _참고:
|
|||||||
|
|
||||||
- Wakatime 카드
|
- Wakatime 카드
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -176,7 +176,7 @@ Je kan meerdere komma verdeelde waarden in de bg_color optie geven om een kleure
|
|||||||
|
|
||||||
- `hide` - Verbergt specifieke talen van de kaart _(komma gescheiden waardes)_
|
- `hide` - Verbergt specifieke talen van de kaart _(komma gescheiden waardes)_
|
||||||
- `hide_title` - _(boolean)_
|
- `hide_title` - _(boolean)_
|
||||||
- `layout` - Kies uit de vijf beschikbare lay-outs `normal` & `compact` & `donut` & `donut-vertical` & `pie`
|
- `layout` - Keuze voor de twee beschikbare layouts `default` & `compact`
|
||||||
- `card_width` - Stelt de breedte van de kaart handmatig in. _(nummer)_
|
- `card_width` - Stelt de breedte van de kaart handmatig in. _(nummer)_
|
||||||
- `langs_count` - Laat meer talen op de kaart zien, waarde tussen 1-10, staat standaard op to 5 _(nummer)_
|
- `langs_count` - Laat meer talen op de kaart zien, waarde tussen 1-10, staat standaard op to 5 _(nummer)_
|
||||||
- `exclude_repo` - Verbergt specifieke repositories _(komma gescheiden waardes)_
|
- `exclude_repo` - Verbergt specifieke repositories _(komma gescheiden waardes)_
|
||||||
@@ -283,14 +283,14 @@ Je kan de `&layout=compact` optie gebruiken om het kaart ontwerp aan te passen.
|
|||||||
Verander de `?username=` waarde naar je [Wakatime](https://wakatime.com) gebruikersnaam.
|
Verander de `?username=` waarde naar je [Wakatime](https://wakatime.com) gebruikersnaam.
|
||||||
|
|
||||||
```md
|
```md
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Demo
|
### Demo
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -340,7 +340,7 @@ Kies uit de [standaard thema\'s](#themes)
|
|||||||
|
|
||||||
- Wakatime kaart
|
- Wakatime kaart
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -174,7 +174,7 @@ You can provide multiple comma-separated values in bg_color option to render a g
|
|||||||
|
|
||||||
- `hide` - Hide the languages specified from the card _(Comma-separated values)_
|
- `hide` - Hide the languages specified from the card _(Comma-separated values)_
|
||||||
- `hide_title` - _(boolean)_
|
- `hide_title` - _(boolean)_
|
||||||
- `layout` - Switch between five available layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`. Default: `normal`.
|
- `layout` - Switch between two available layouts `default` & `compact`
|
||||||
- `card_width` - Set the card's width manually _(number)_
|
- `card_width` - Set the card's width manually _(number)_
|
||||||
- `langs_count` - Show more languages on the card, between 1-10, defaults to 5 _(number)_
|
- `langs_count` - Show more languages on the card, between 1-10, defaults to 5 _(number)_
|
||||||
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_
|
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_
|
||||||
@@ -279,14 +279,14 @@ You can use the `&langs_count=` option to increase or decrease the number of lan
|
|||||||
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
|
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
|
||||||
|
|
||||||
```md
|
```md
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
```
|
```
|
||||||
|
|
||||||
### डेमो
|
### डेमो
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -336,7 +336,7 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
|
|||||||
|
|
||||||
- वक समय कार्ड
|
- वक समय कार्ड
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ Personalize a aparência do seu `Stats Card` ou `Repo Card` da maneira que desej
|
|||||||
|
|
||||||
- `hide` - Oculta linguagens específicas _(Valores separados por vírgulas)_
|
- `hide` - Oculta linguagens específicas _(Valores separados por vírgulas)_
|
||||||
- `hide_title` - Oculta o título _(boolean)_
|
- `hide_title` - Oculta o título _(boolean)_
|
||||||
- `layout` - Alternar entre os cinco layouts disponíveis `normal` & `compact` & `donut` & `donut-vertical` & `pie`
|
- `layout` - Alterna entre os dois layouts disponíveis `default` & `compact`
|
||||||
- `card_width` - Define a largura do cartão manualmente _(number)_
|
- `card_width` - Define a largura do cartão manualmente _(number)_
|
||||||
|
|
||||||
> :warning: **Importante:**
|
> :warning: **Importante:**
|
||||||
@@ -242,14 +242,14 @@ Utilize a opção `&layout=compact` para mudar o layout do cartão.
|
|||||||
Altere o valor de `?username=` para o seu username do Wakatime.
|
Altere o valor de `?username=` para o seu username do Wakatime.
|
||||||
|
|
||||||
```md
|
```md
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Demonstração
|
### Demonstração
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -176,7 +176,7 @@ bg_color içerisinde birden fazla rengi gradient olarak göstermek için virgül
|
|||||||
|
|
||||||
- `hide` - Belirli bir dili listede gizler _(Virgül ile ayırılmış değerlerle)_
|
- `hide` - Belirli bir dili listede gizler _(Virgül ile ayırılmış değerlerle)_
|
||||||
- `hide_title` - _(boolean)_
|
- `hide_title` - _(boolean)_
|
||||||
- `layout` - Beş uygun tasarım / düzen arasında geçiş yapın `normal` & `compact` & `donut` & `donut-vertical` & `pie`
|
- `layout` - Uygun olan iki tasarım / layout arasında değişiklik yapar `default` & `compact`
|
||||||
- `card_width` - Kartın genişliğini manuel olarak belirler _(number)_
|
- `card_width` - Kartın genişliğini manuel olarak belirler _(number)_
|
||||||
- `langs_count` - 1-10 arasında istediğiniz kadar dil gösterebilirsiniz. Varsayılan: 5 _(number)_
|
- `langs_count` - 1-10 arasında istediğiniz kadar dil gösterebilirsiniz. Varsayılan: 5 _(number)_
|
||||||
- `exclude_repo` - Belirli repoları listeden çıkartır _(Virgül ile ayırılmış değerlerle)_
|
- `exclude_repo` - Belirli repoları listeden çıkartır _(Virgül ile ayırılmış değerlerle)_
|
||||||
@@ -282,18 +282,18 @@ Endpoint: `api/top-langs?username=mustafacagri`
|
|||||||
`?username=` değerini [Wakatime](https://wakatime.com)'daki kullanıcı adınızla değiştirin.
|
`?username=` değerini [Wakatime](https://wakatime.com)'daki kullanıcı adınızla değiştirin.
|
||||||
|
|
||||||
```md
|
```md
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Demo
|
### Demo
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
- Kompakt Düzen
|
- Kompakt Düzen
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -343,7 +343,7 @@ Endpoint: `api/top-langs?username=mustafacagri`
|
|||||||
|
|
||||||
- Wakatime kart
|
- Wakatime kart
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Generated
+382
-15327
File diff suppressed because it is too large
Load Diff
+1
-2
@@ -49,8 +49,7 @@
|
|||||||
"lint-staged": "^13.0.3",
|
"lint-staged": "^13.0.3",
|
||||||
"lodash.snakecase": "^4.1.1",
|
"lodash.snakecase": "^4.1.1",
|
||||||
"parse-diff": "^0.7.0",
|
"parse-diff": "^0.7.0",
|
||||||
"prettier": "^2.1.2",
|
"prettier": "^2.1.2"
|
||||||
"vercel": "^29.4.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ You can provide multiple comma-separated values in the bg_color option to render
|
|||||||
|
|
||||||
- `hide` - Hide the languages specified from the card _(Comma-separated values)_. Default: `[] (blank array)`.
|
- `hide` - Hide the languages specified from the card _(Comma-separated values)_. Default: `[] (blank array)`.
|
||||||
- `hide_title` - _(boolean)_. Default: `false`.
|
- `hide_title` - _(boolean)_. Default: `false`.
|
||||||
- `layout` - Switch between five available layouts `normal` & `compact` & `donut` & `donut-vertical` & `pie`. Default: `normal`.
|
- `layout` - Switch between two available layouts `default` & `compact`. Default: `default`.
|
||||||
- `card_width` - Set the card's width manually _(number)_. Default `300`.
|
- `card_width` - Set the card's width manually _(number)_. Default `300`.
|
||||||
- `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`.
|
- `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`.
|
||||||
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
|
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
|
||||||
@@ -423,30 +423,6 @@ You can use the `&layout=compact` option to change the card design.
|
|||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Donut Chart Language Card Layout
|
|
||||||
|
|
||||||
You can use the `&layout=donut` option to change the card design.
|
|
||||||
|
|
||||||
```md
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Donut Vertical Chart Language Card Layout
|
|
||||||
|
|
||||||
You can use the `&layout=donut-vertical` option to change the card design.
|
|
||||||
|
|
||||||
```md
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Pie Chart Language Card Layout
|
|
||||||
|
|
||||||
You can use the `&layout=pie` option to change the card design.
|
|
||||||
|
|
||||||
```md
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Hide Progress Bars
|
### Hide Progress Bars
|
||||||
|
|
||||||
You can use the `&hide_progress=true` option to hide the percentages and the progress bars (layout will be automatically set to `compact`).
|
You can use the `&hide_progress=true` option to hide the percentages and the progress bars (layout will be automatically set to `compact`).
|
||||||
@@ -463,18 +439,6 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
|
|||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
- Donut Chart layout
|
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
|
||||||
|
|
||||||
- Donut Vertical Chart layout
|
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
|
||||||
|
|
||||||
- Pie Chart layout
|
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
|
||||||
|
|
||||||
- Hidden progress bars
|
- Hidden progress bars
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
@@ -484,7 +448,7 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
|
|||||||
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
|
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
|
||||||
|
|
||||||
```md
|
```md
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note**:
|
> **Note**:
|
||||||
@@ -492,13 +456,13 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
|
|||||||
|
|
||||||
### Demo
|
### Demo
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
- Compact layout
|
- Compact layout
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
* * *
|
* * *
|
||||||
|
|
||||||
@@ -556,7 +520,7 @@ Choose from any of the [default themes](#themes)
|
|||||||
|
|
||||||
- WakaTime card
|
- WakaTime card
|
||||||
|
|
||||||
[](https://github.com/anuraghazra/github-readme-stats)
|
[](https://github.com/anuraghazra/github-readme-stats)
|
||||||
|
|
||||||
* * *
|
* * *
|
||||||
|
|
||||||
|
|||||||
@@ -20,16 +20,14 @@ const RANK_CARD_DEFAULT_WIDTH = 450;
|
|||||||
/**
|
/**
|
||||||
* Create a stats card text item.
|
* Create a stats card text item.
|
||||||
*
|
*
|
||||||
* @param {object} createTextNodeParams Object that contains the createTextNode parameters.
|
* @param {object[]} createTextNodeParams Object that contains the createTextNode parameters.
|
||||||
* @param {string} createTextNodeParams.icon The icon to display.
|
|
||||||
* @param {string} createTextNodeParams.label The label to display.
|
* @param {string} createTextNodeParams.label The label to display.
|
||||||
* @param {number} createTextNodeParams.value The value to display.
|
* @param {string} createTextNodeParams.value The value to display.
|
||||||
* @param {string} createTextNodeParams.id The id of the stat.
|
* @param {string} createTextNodeParams.id The id of the stat.
|
||||||
* @param {number} createTextNodeParams.index The index of the stat.
|
* @param {number} createTextNodeParams.index The index of the stat.
|
||||||
* @param {boolean} createTextNodeParams.showIcons Whether to show icons.
|
* @param {boolean} createTextNodeParams.showIcons Whether to show icons.
|
||||||
* @param {number} createTextNodeParams.shiftValuePos Number of pixels the value has to be shifted to the right.
|
* @param {number} createTextNodeParams.shiftValuePos Number of pixels the value has to be shifted to the right.
|
||||||
* @param {boolean} createTextNodeParams.bold Whether to bold the label.
|
* @param {boolean} createTextNodeParams.bold Whether to bold the label.
|
||||||
* @param {string} createTextNodeParams.number_format The format of numbers on card.
|
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const createTextNode = ({
|
const createTextNode = ({
|
||||||
|
|||||||
+55
-469
@@ -36,164 +36,13 @@ const getLongestLang = (arr) =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert degrees to radians.
|
* Creates a node to display usage of a programming language in percentage
|
||||||
*
|
* using text and a horizontal progress bar.
|
||||||
* @param {number} angleInDegrees Angle in degrees.
|
|
||||||
* @returns Angle in radians.
|
|
||||||
*/
|
|
||||||
const degreesToRadians = (angleInDegrees) => angleInDegrees * (Math.PI / 180.0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert radians to degrees.
|
|
||||||
*
|
|
||||||
* @param {number} angleInRadians Angle in radians.
|
|
||||||
* @returns Angle in degrees.
|
|
||||||
*/
|
|
||||||
const radiansToDegrees = (angleInRadians) => angleInRadians / (Math.PI / 180.0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert polar coordinates to cartesian coordinates.
|
|
||||||
*
|
|
||||||
* @param {number} centerX Center x coordinate.
|
|
||||||
* @param {number} centerY Center y coordinate.
|
|
||||||
* @param {number} radius Radius of the circle.
|
|
||||||
* @param {number} angleInDegrees Angle in degrees.
|
|
||||||
* @returns {{x: number, y: number}} Cartesian coordinates.
|
|
||||||
*/
|
|
||||||
const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
|
|
||||||
const rads = degreesToRadians(angleInDegrees);
|
|
||||||
return {
|
|
||||||
x: centerX + radius * Math.cos(rads),
|
|
||||||
y: centerY + radius * Math.sin(rads),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert cartesian coordinates to polar coordinates.
|
|
||||||
*
|
|
||||||
* @param {number} centerX Center x coordinate.
|
|
||||||
* @param {number} centerY Center y coordinate.
|
|
||||||
* @param {number} x Point x coordinate.
|
|
||||||
* @param {number} y Point y coordinate.
|
|
||||||
* @returns {{radius: number, angleInDegrees: number}} Polar coordinates.
|
|
||||||
*/
|
|
||||||
const cartesianToPolar = (centerX, centerY, x, y) => {
|
|
||||||
const radius = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
|
|
||||||
let angleInDegrees = radiansToDegrees(Math.atan2(y - centerY, x - centerX));
|
|
||||||
if (angleInDegrees < 0) angleInDegrees += 360;
|
|
||||||
return { radius, angleInDegrees };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates length of circle.
|
|
||||||
*
|
|
||||||
* @param {number} radius Radius of the circle.
|
|
||||||
* @returns {number} The length of the circle.
|
|
||||||
*/
|
|
||||||
const getCircleLength = (radius) => {
|
|
||||||
return 2 * Math.PI * radius;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates height for the compact layout.
|
|
||||||
*
|
|
||||||
* @param {number} totalLangs Total number of languages.
|
|
||||||
* @returns {number} Card height.
|
|
||||||
*/
|
|
||||||
const calculateCompactLayoutHeight = (totalLangs) => {
|
|
||||||
return 90 + Math.round(totalLangs / 2) * 25;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates height for the normal layout.
|
|
||||||
*
|
|
||||||
* @param {number} totalLangs Total number of languages.
|
|
||||||
* @returns {number} Card height.
|
|
||||||
*/
|
|
||||||
const calculateNormalLayoutHeight = (totalLangs) => {
|
|
||||||
return 45 + (totalLangs + 1) * 40;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates height for the donut layout.
|
|
||||||
*
|
|
||||||
* @param {number} totalLangs Total number of languages.
|
|
||||||
* @returns {number} Card height.
|
|
||||||
*/
|
|
||||||
const calculateDonutLayoutHeight = (totalLangs) => {
|
|
||||||
return 215 + Math.max(totalLangs - 5, 0) * 32;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates height for the donut vertical layout.
|
|
||||||
*
|
|
||||||
* @param {number} totalLangs Total number of languages.
|
|
||||||
* @returns {number} Card height.
|
|
||||||
*/
|
|
||||||
const calculateDonutVerticalLayoutHeight = (totalLangs) => {
|
|
||||||
return 300 + Math.round(totalLangs / 2) * 25;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates height for the pie layout.
|
|
||||||
*
|
|
||||||
* @param {number} totalLangs Total number of languages.
|
|
||||||
* @returns {number} Card height.
|
|
||||||
*/
|
|
||||||
const calculatePieLayoutHeight = (totalLangs) => {
|
|
||||||
return 300 + Math.round(totalLangs / 2) * 25;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the center translation needed to keep the donut chart centred.
|
|
||||||
* @param {number} totalLangs Total number of languages.
|
|
||||||
* @returns {number} Donut center translation.
|
|
||||||
*/
|
|
||||||
const donutCenterTranslation = (totalLangs) => {
|
|
||||||
return -45 + Math.max(totalLangs - 5, 0) * 16;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trim top languages to lang_count while also hiding certain languages.
|
|
||||||
*
|
|
||||||
* @param {Record<string, Lang>} topLangs Top languages.
|
|
||||||
* @param {string[]} hide Languages to hide.
|
|
||||||
* @param {string} langs_count Number of languages to show.
|
|
||||||
* @returns {{topLangs: Record<string, Lang>, totalSize: number}} Trimmed top languages and total size.
|
|
||||||
*/
|
|
||||||
const trimTopLanguages = (topLangs, hide, langs_count) => {
|
|
||||||
let langs = Object.values(topLangs);
|
|
||||||
let langsToHide = {};
|
|
||||||
let langsCount = clampValue(parseInt(langs_count), 1, 10);
|
|
||||||
|
|
||||||
// populate langsToHide map for quick lookup
|
|
||||||
// while filtering out
|
|
||||||
if (hide) {
|
|
||||||
hide.forEach((langName) => {
|
|
||||||
langsToHide[lowercaseTrim(langName)] = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter out languages to be hidden
|
|
||||||
langs = langs
|
|
||||||
.sort((a, b) => b.size - a.size)
|
|
||||||
.filter((lang) => {
|
|
||||||
return !langsToHide[lowercaseTrim(lang.name)];
|
|
||||||
})
|
|
||||||
.slice(0, langsCount);
|
|
||||||
|
|
||||||
const totalLanguageSize = langs.reduce((acc, curr) => acc + curr.size, 0);
|
|
||||||
|
|
||||||
return { langs, totalLanguageSize };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create progress bar text item for a programming language.
|
|
||||||
*
|
*
|
||||||
* @param {object} props Function properties.
|
* @param {object} props Function properties.
|
||||||
* @param {number} props.width The card width
|
* @param {number} props.width The card width
|
||||||
* @param {string} props.color Color of the programming language.
|
|
||||||
* @param {string} props.name Name of the programming language.
|
* @param {string} props.name Name of the programming language.
|
||||||
|
* @param {string} props.color Color of the programming language.
|
||||||
* @param {string} props.progress Usage of the programming language in percentage.
|
* @param {string} props.progress Usage of the programming language in percentage.
|
||||||
* @param {number} props.index Index of the programming language.
|
* @param {number} props.index Index of the programming language.
|
||||||
* @returns {string} Programming language SVG node.
|
* @returns {string} Programming language SVG node.
|
||||||
@@ -222,7 +71,7 @@ const createProgressTextNode = ({ width, color, name, progress, index }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates compact text item for a programming language.
|
* Creates a text only node to display usage of a programming language in percentage.
|
||||||
*
|
*
|
||||||
* @param {object} props Function properties.
|
* @param {object} props Function properties.
|
||||||
* @param {Lang} props.lang Programming language object.
|
* @param {Lang} props.lang Programming language object.
|
||||||
@@ -247,9 +96,9 @@ const createCompactLangNode = ({ lang, totalSize, hideProgress, index }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create compact languages text items for all programming languages.
|
* Creates compact layout of text only language nodes.
|
||||||
*
|
*
|
||||||
* @param {object} props Function properties.
|
* @param {object[]} props Function properties.
|
||||||
* @param {Lang[]} props.langs Array of programming languages.
|
* @param {Lang[]} props.langs Array of programming languages.
|
||||||
* @param {number} props.totalSize Total size of all languages.
|
* @param {number} props.totalSize Total size of all languages.
|
||||||
* @param {boolean} props.hideProgress Whether to hide percentage.
|
* @param {boolean} props.hideProgress Whether to hide percentage.
|
||||||
@@ -285,30 +134,7 @@ const createLanguageTextNode = ({ langs, totalSize, hideProgress }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create donut languages text items for all programming languages.
|
* Renders layout to display user's most frequently used programming languages.
|
||||||
*
|
|
||||||
* @param {object} props Function properties.
|
|
||||||
* @param {Lang[]} props.langs Array of programming languages.
|
|
||||||
* @param {number} props.totalSize Total size of all languages.
|
|
||||||
* @returns {string} Donut layout programming language SVG node.
|
|
||||||
*/
|
|
||||||
const createDonutLanguagesNode = ({ langs, totalSize }) => {
|
|
||||||
return flexLayout({
|
|
||||||
items: langs.map((lang, index) => {
|
|
||||||
return createCompactLangNode({
|
|
||||||
lang,
|
|
||||||
totalSize,
|
|
||||||
hideProgress: false,
|
|
||||||
index,
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
gap: 32,
|
|
||||||
direction: "column",
|
|
||||||
}).join("");
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the default language card layout.
|
|
||||||
*
|
*
|
||||||
* @param {Lang[]} langs Array of programming languages.
|
* @param {Lang[]} langs Array of programming languages.
|
||||||
* @param {number} width Card width.
|
* @param {number} width Card width.
|
||||||
@@ -332,7 +158,7 @@ const renderNormalLayout = (langs, width, totalLanguageSize) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the compact language card layout.
|
* Renders compact layout to display user's most frequently used programming languages.
|
||||||
*
|
*
|
||||||
* @param {Lang[]} langs Array of programming languages.
|
* @param {Lang[]} langs Array of programming languages.
|
||||||
* @param {number} width Card width.
|
* @param {number} width Card width.
|
||||||
@@ -392,270 +218,60 @@ const renderCompactLayout = (langs, width, totalLanguageSize, hideProgress) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders donut vertical layout to display user's most frequently used programming languages.
|
* Calculates height for the compact layout.
|
||||||
*
|
*
|
||||||
* @param {Lang[]} langs Array of programming languages.
|
* @param {number} totalLangs Total number of languages.
|
||||||
* @param {number} totalLanguageSize Total size of all languages.
|
* @returns {number} Card height.
|
||||||
* @returns {string} Compact layout card SVG object.
|
|
||||||
*/
|
*/
|
||||||
const renderDonutVerticalLayout = (langs, totalLanguageSize) => {
|
const calculateCompactLayoutHeight = (totalLangs) => {
|
||||||
// Donut vertical chart radius and total length
|
return 90 + Math.round(totalLangs / 2) * 25;
|
||||||
const radius = 80;
|
};
|
||||||
const totalCircleLength = getCircleLength(radius);
|
|
||||||
|
|
||||||
// SVG circles
|
/**
|
||||||
let circles = [];
|
* Calculates height for the normal layout.
|
||||||
|
*
|
||||||
|
* @param {number} totalLangs Total number of languages.
|
||||||
|
* @returns {number} Card height.
|
||||||
|
*/
|
||||||
|
const calculateNormalLayoutHeight = (totalLangs) => {
|
||||||
|
return 45 + (totalLangs + 1) * 40;
|
||||||
|
};
|
||||||
|
|
||||||
// Start indent for donut vertical chart parts
|
/**
|
||||||
let indent = 0;
|
* Hides languages and trims the list to show only the top N languages.
|
||||||
|
*
|
||||||
|
* @param {Record<string, Lang>} topLangs Top languages.
|
||||||
|
* @param {string[]} hide Languages to hide.
|
||||||
|
* @param {string} langs_count Number of languages to show.
|
||||||
|
*/
|
||||||
|
const useLanguages = (topLangs, hide, langs_count) => {
|
||||||
|
let langs = Object.values(topLangs);
|
||||||
|
let langsToHide = {};
|
||||||
|
let langsCount = clampValue(parseInt(langs_count), 1, 10);
|
||||||
|
|
||||||
// Start delay coefficient for donut vertical chart parts
|
// populate langsToHide map for quick lookup
|
||||||
let startDelayCoefficient = 1;
|
// while filtering out
|
||||||
|
if (hide) {
|
||||||
// Generate each donut vertical chart part
|
hide.forEach((langName) => {
|
||||||
for (const lang of langs) {
|
langsToHide[lowercaseTrim(langName)] = true;
|
||||||
const percentage = (lang.size / totalLanguageSize) * 100;
|
});
|
||||||
const circleLength = totalCircleLength * (percentage / 100);
|
|
||||||
const delay = startDelayCoefficient * 100;
|
|
||||||
|
|
||||||
circles.push(`
|
|
||||||
<g class="stagger" style="animation-delay: ${delay}ms">
|
|
||||||
<circle
|
|
||||||
cx="150"
|
|
||||||
cy="100"
|
|
||||||
r="${radius}"
|
|
||||||
fill="transparent"
|
|
||||||
stroke="${lang.color}"
|
|
||||||
stroke-width="25"
|
|
||||||
stroke-dasharray="${totalCircleLength}"
|
|
||||||
stroke-dashoffset="${indent}"
|
|
||||||
size="${percentage}"
|
|
||||||
data-testid="lang-donut"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
`);
|
|
||||||
|
|
||||||
// Update the indent for the next part
|
|
||||||
indent += circleLength;
|
|
||||||
// Update the start delay coefficient for the next part
|
|
||||||
startDelayCoefficient += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return `
|
// filter out languages to be hidden
|
||||||
<svg data-testid="lang-items">
|
langs = langs
|
||||||
<g transform="translate(0, 0)">
|
.sort((a, b) => b.size - a.size)
|
||||||
<svg data-testid="donut">
|
.filter((lang) => {
|
||||||
${circles.join("")}
|
return !langsToHide[lowercaseTrim(lang.name)];
|
||||||
</svg>
|
})
|
||||||
</g>
|
.slice(0, langsCount);
|
||||||
<g transform="translate(0, 220)">
|
|
||||||
<svg data-testid="lang-names" x="${CARD_PADDING}">
|
const totalLanguageSize = langs.reduce((acc, curr) => acc + curr.size, 0);
|
||||||
${createLanguageTextNode({
|
|
||||||
langs,
|
return { langs, totalLanguageSize };
|
||||||
totalSize: totalLanguageSize,
|
|
||||||
hideProgress: false,
|
|
||||||
})}
|
|
||||||
</svg>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders pie layout to display user's most frequently used programming languages.
|
* Renders card to display user's most frequently used programming languages.
|
||||||
*
|
|
||||||
* @param {Lang[]} langs Array of programming languages.
|
|
||||||
* @param {number} totalLanguageSize Total size of all languages.
|
|
||||||
* @returns {string} Compact layout card SVG object.
|
|
||||||
*/
|
|
||||||
const renderPieLayout = (langs, totalLanguageSize) => {
|
|
||||||
// Pie chart radius and center coordinates
|
|
||||||
const radius = 90;
|
|
||||||
const centerX = 150;
|
|
||||||
const centerY = 100;
|
|
||||||
|
|
||||||
// Start angle for the pie chart parts
|
|
||||||
let startAngle = 0;
|
|
||||||
|
|
||||||
// Start delay coefficient for the pie chart parts
|
|
||||||
let startDelayCoefficient = 1;
|
|
||||||
|
|
||||||
// SVG paths
|
|
||||||
const paths = [];
|
|
||||||
|
|
||||||
// Generate each pie chart part
|
|
||||||
for (const lang of langs) {
|
|
||||||
if (langs.length === 1) {
|
|
||||||
paths.push(`
|
|
||||||
<circle
|
|
||||||
cx="${centerX}"
|
|
||||||
cy="${centerY}"
|
|
||||||
r="${radius}"
|
|
||||||
stroke="none"
|
|
||||||
fill="${lang.color}"
|
|
||||||
data-testid="lang-pie"
|
|
||||||
size="100"
|
|
||||||
/>
|
|
||||||
`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const langSizePart = lang.size / totalLanguageSize;
|
|
||||||
const percentage = langSizePart * 100;
|
|
||||||
// Calculate the angle for the current part
|
|
||||||
const angle = langSizePart * 360;
|
|
||||||
|
|
||||||
// Calculate the end angle
|
|
||||||
const endAngle = startAngle + angle;
|
|
||||||
|
|
||||||
// Calculate the coordinates of the start and end points of the arc
|
|
||||||
const startPoint = polarToCartesian(centerX, centerY, radius, startAngle);
|
|
||||||
const endPoint = polarToCartesian(centerX, centerY, radius, endAngle);
|
|
||||||
|
|
||||||
// Determine the large arc flag based on the angle
|
|
||||||
const largeArcFlag = angle > 180 ? 1 : 0;
|
|
||||||
|
|
||||||
// Calculate delay
|
|
||||||
const delay = startDelayCoefficient * 100;
|
|
||||||
|
|
||||||
// SVG arc markup
|
|
||||||
paths.push(`
|
|
||||||
<g class="stagger" style="animation-delay: ${delay}ms">
|
|
||||||
<path
|
|
||||||
data-testid="lang-pie"
|
|
||||||
size="${percentage}"
|
|
||||||
d="M ${centerX} ${centerY} L ${startPoint.x} ${startPoint.y} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${endPoint.x} ${endPoint.y} Z"
|
|
||||||
fill="${lang.color}"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
`);
|
|
||||||
|
|
||||||
// Update the start angle for the next part
|
|
||||||
startAngle = endAngle;
|
|
||||||
// Update the start delay coefficient for the next part
|
|
||||||
startDelayCoefficient += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `
|
|
||||||
<svg data-testid="lang-items">
|
|
||||||
<g transform="translate(0, 0)">
|
|
||||||
<svg data-testid="pie">
|
|
||||||
${paths.join("")}
|
|
||||||
</svg>
|
|
||||||
</g>
|
|
||||||
<g transform="translate(0, 220)">
|
|
||||||
<svg data-testid="lang-names" x="${CARD_PADDING}">
|
|
||||||
${createLanguageTextNode({
|
|
||||||
langs,
|
|
||||||
totalSize: totalLanguageSize,
|
|
||||||
hideProgress: false,
|
|
||||||
})}
|
|
||||||
</svg>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the SVG paths for the language donut chart.
|
|
||||||
*
|
|
||||||
* @param {number} cx Donut center x-position.
|
|
||||||
* @param {number} cy Donut center y-position.
|
|
||||||
* @param {number} radius Donut arc Radius.
|
|
||||||
* @param {number[]} percentages Array with donut section percentages.
|
|
||||||
* @returns {{d: string, percent: number}[]} Array of svg path elements
|
|
||||||
*/
|
|
||||||
const createDonutPaths = (cx, cy, radius, percentages) => {
|
|
||||||
const paths = [];
|
|
||||||
let startAngle = 0;
|
|
||||||
let endAngle = 0;
|
|
||||||
|
|
||||||
const totalPercent = percentages.reduce((acc, curr) => acc + curr, 0);
|
|
||||||
for (let i = 0; i < percentages.length; i++) {
|
|
||||||
const tmpPath = {};
|
|
||||||
|
|
||||||
let percent = parseFloat(
|
|
||||||
((percentages[i] / totalPercent) * 100).toFixed(2),
|
|
||||||
);
|
|
||||||
|
|
||||||
endAngle = 3.6 * percent + startAngle;
|
|
||||||
const startPoint = polarToCartesian(cx, cy, radius, endAngle - 90); // rotate donut 90 degrees counter-clockwise.
|
|
||||||
const endPoint = polarToCartesian(cx, cy, radius, startAngle - 90); // rotate donut 90 degrees counter-clockwise.
|
|
||||||
const largeArc = endAngle - startAngle <= 180 ? 0 : 1;
|
|
||||||
|
|
||||||
tmpPath.percent = percent;
|
|
||||||
tmpPath.d = `M ${startPoint.x} ${startPoint.y} A ${radius} ${radius} 0 ${largeArc} 0 ${endPoint.x} ${endPoint.y}`;
|
|
||||||
|
|
||||||
paths.push(tmpPath);
|
|
||||||
startAngle = endAngle;
|
|
||||||
}
|
|
||||||
|
|
||||||
return paths;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the donut language card layout.
|
|
||||||
*
|
|
||||||
* @param {Lang[]} langs Array of programming languages.
|
|
||||||
* @param {number} width Card width.
|
|
||||||
* @param {number} totalLanguageSize Total size of all languages.
|
|
||||||
* @returns {string} Donut layout card SVG object.
|
|
||||||
*/
|
|
||||||
const renderDonutLayout = (langs, width, totalLanguageSize) => {
|
|
||||||
const centerX = width / 3;
|
|
||||||
const centerY = width / 3;
|
|
||||||
const radius = centerX - 60;
|
|
||||||
const strokeWidth = 12;
|
|
||||||
|
|
||||||
const colors = langs.map((lang) => lang.color);
|
|
||||||
const langsPercents = langs.map((lang) =>
|
|
||||||
parseFloat(((lang.size / totalLanguageSize) * 100).toFixed(2)),
|
|
||||||
);
|
|
||||||
|
|
||||||
const langPaths = createDonutPaths(centerX, centerY, radius, langsPercents);
|
|
||||||
|
|
||||||
const donutPaths =
|
|
||||||
langs.length === 1
|
|
||||||
? `<circle cx="${centerX}" cy="${centerY}" r="${radius}" stroke="${colors[0]}" fill="none" stroke-width="${strokeWidth}" data-testid="lang-donut" size="100"/>`
|
|
||||||
: langPaths
|
|
||||||
.map((section, index) => {
|
|
||||||
const staggerDelay = (index + 3) * 100;
|
|
||||||
const delay = staggerDelay + 300;
|
|
||||||
|
|
||||||
const output = `
|
|
||||||
<g class="stagger" style="animation-delay: ${delay}ms">
|
|
||||||
<path
|
|
||||||
data-testid="lang-donut"
|
|
||||||
size="${section.percent}"
|
|
||||||
d="${section.d}"
|
|
||||||
stroke="${colors[index]}"
|
|
||||||
fill="none"
|
|
||||||
stroke-width="${strokeWidth}">
|
|
||||||
</path>
|
|
||||||
</g>
|
|
||||||
`;
|
|
||||||
|
|
||||||
return output;
|
|
||||||
})
|
|
||||||
.join("");
|
|
||||||
|
|
||||||
const donut = `<svg width="${width}" height="${width}">${donutPaths}</svg>`;
|
|
||||||
|
|
||||||
return `
|
|
||||||
<g transform="translate(0, 0)">
|
|
||||||
<g transform="translate(0, 0)">
|
|
||||||
${createDonutLanguagesNode({ langs, totalSize: totalLanguageSize })}
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g transform="translate(125, ${donutCenterTranslation(langs.length)})">
|
|
||||||
${donut}
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders card that display user's most frequently used programming languages.
|
|
||||||
*
|
*
|
||||||
* @param {import('../fetchers/types').TopLangData} topLangs User's most frequently used programming languages.
|
* @param {import('../fetchers/types').TopLangData} topLangs User's most frequently used programming languages.
|
||||||
* @param {Partial<import("./types").TopLangOptions>} options Card options.
|
* @param {Partial<import("./types").TopLangOptions>} options Card options.
|
||||||
@@ -686,7 +302,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|||||||
translations: langCardLocales,
|
translations: langCardLocales,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { langs, totalLanguageSize } = trimTopLanguages(
|
const { langs, totalLanguageSize } = useLanguages(
|
||||||
topLangs,
|
topLangs,
|
||||||
hide,
|
hide,
|
||||||
String(langs_count),
|
String(langs_count),
|
||||||
@@ -700,13 +316,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|||||||
let height = calculateNormalLayoutHeight(langs.length);
|
let height = calculateNormalLayoutHeight(langs.length);
|
||||||
|
|
||||||
let finalLayout = "";
|
let finalLayout = "";
|
||||||
if (layout === "pie") {
|
if (layout === "compact" || hide_progress == true) {
|
||||||
height = calculatePieLayoutHeight(langs.length);
|
|
||||||
finalLayout = renderPieLayout(langs, totalLanguageSize);
|
|
||||||
} else if (layout === "donut-vertical") {
|
|
||||||
height = calculateDonutVerticalLayoutHeight(langs.length);
|
|
||||||
finalLayout = renderDonutVerticalLayout(langs, totalLanguageSize);
|
|
||||||
} else if (layout === "compact" || hide_progress == true) {
|
|
||||||
height =
|
height =
|
||||||
calculateCompactLayoutHeight(langs.length) + (hide_progress ? -25 : 0);
|
calculateCompactLayoutHeight(langs.length) + (hide_progress ? -25 : 0);
|
||||||
|
|
||||||
@@ -716,10 +326,6 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|||||||
totalLanguageSize,
|
totalLanguageSize,
|
||||||
hide_progress,
|
hide_progress,
|
||||||
);
|
);
|
||||||
} else if (layout?.toLowerCase() === "donut") {
|
|
||||||
height = calculateDonutLayoutHeight(langs.length);
|
|
||||||
width = width + 50; // padding
|
|
||||||
finalLayout = renderDonutLayout(langs, width, totalLanguageSize);
|
|
||||||
} else {
|
} else {
|
||||||
finalLayout = renderNormalLayout(langs, width, totalLanguageSize);
|
finalLayout = renderNormalLayout(langs, width, totalLanguageSize);
|
||||||
}
|
}
|
||||||
@@ -781,10 +387,6 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|||||||
`,
|
`,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (layout === "pie" || layout === "donut-vertical") {
|
|
||||||
return card.render(finalLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
return card.render(`
|
return card.render(`
|
||||||
<svg data-testid="lang-items" x="${CARD_PADDING}">
|
<svg data-testid="lang-items" x="${CARD_PADDING}">
|
||||||
${finalLayout}
|
${finalLayout}
|
||||||
@@ -792,20 +394,4 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|||||||
`);
|
`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export { renderTopLanguages, MIN_CARD_WIDTH };
|
||||||
getLongestLang,
|
|
||||||
degreesToRadians,
|
|
||||||
radiansToDegrees,
|
|
||||||
polarToCartesian,
|
|
||||||
cartesianToPolar,
|
|
||||||
getCircleLength,
|
|
||||||
calculateCompactLayoutHeight,
|
|
||||||
calculateNormalLayoutHeight,
|
|
||||||
calculateDonutLayoutHeight,
|
|
||||||
calculateDonutVerticalLayoutHeight,
|
|
||||||
calculatePieLayoutHeight,
|
|
||||||
donutCenterTranslation,
|
|
||||||
trimTopLanguages,
|
|
||||||
renderTopLanguages,
|
|
||||||
MIN_CARD_WIDTH,
|
|
||||||
};
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -39,7 +39,7 @@ export type TopLangOptions = CommonOptions & {
|
|||||||
hide_border: boolean;
|
hide_border: boolean;
|
||||||
card_width: number;
|
card_width: number;
|
||||||
hide: string[];
|
hide: string[];
|
||||||
layout: "compact" | "normal" | "donut" | "donut-vertical" | "pie";
|
layout: "compact" | "normal";
|
||||||
custom_title: string;
|
custom_title: string;
|
||||||
langs_count: number;
|
langs_count: number;
|
||||||
disable_animations: boolean;
|
disable_animations: boolean;
|
||||||
|
|||||||
+25
-34
@@ -36,11 +36,11 @@ const noCodingActivityNode = ({ color, text }) => {
|
|||||||
/**
|
/**
|
||||||
* Create compact WakaTime layout.
|
* Create compact WakaTime layout.
|
||||||
*
|
*
|
||||||
* @param {Object} args The function arguments.
|
* @param {Object[]} args The function arguments.
|
||||||
* @param {import("../fetchers/types").WakaTimeLang} args.lang The languages array.
|
* @param {import("../fetchers/types").WakaTimeLang[]} languages The languages array.
|
||||||
* @param {number} args.totalSize The total size of the languages.
|
* @param {number} totalSize The total size of the languages.
|
||||||
* @param {number} args.x The x position of the language node.
|
* @param {number} x The x position of the language node.
|
||||||
* @param {number} args.y The y position of the language node.
|
* @param {number} y The y position of the language node.
|
||||||
*/
|
*/
|
||||||
const createCompactLangNode = ({ lang, totalSize, x, y }) => {
|
const createCompactLangNode = ({ lang, totalSize, x, y }) => {
|
||||||
const color = languageColors[lang.name] || "#858585";
|
const color = languageColors[lang.name] || "#858585";
|
||||||
@@ -58,11 +58,11 @@ const createCompactLangNode = ({ lang, totalSize, x, y }) => {
|
|||||||
/**
|
/**
|
||||||
* Create WakaTime language text node item.
|
* Create WakaTime language text node item.
|
||||||
*
|
*
|
||||||
* @param {Object} args The function arguments.
|
* @param {Object[]} args The function arguments.
|
||||||
* @param {import("../fetchers/types").WakaTimeLang[]} args.langs The language objects.
|
* @param {import("../fetchers/types").WakaTimeLang} lang The language object.
|
||||||
* @param {number} args.totalSize The total size of the languages.
|
* @param {number} totalSize The total size of the languages.
|
||||||
* @param {number} args.x The x position of the language node.
|
* @param {number} x The x position of the language node.
|
||||||
* @param {number} args.y The y position of the language node.
|
* @param {number} y The y position of the language node.
|
||||||
*/
|
*/
|
||||||
const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
|
const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
|
||||||
return langs.map((lang, index) => {
|
return langs.map((lang, index) => {
|
||||||
@@ -86,15 +86,14 @@ const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
|
|||||||
/**
|
/**
|
||||||
* Create WakaTime text item.
|
* Create WakaTime text item.
|
||||||
*
|
*
|
||||||
* @param {Object} args The function arguments.
|
* @param {Object[]} args The function arguments.
|
||||||
* @param {string} args.id The id of the text node item.
|
* @param {string} id The id of the text node item.
|
||||||
* @param {string} args.label The label of the text node item.
|
* @param {string} label The label of the text node item.
|
||||||
* @param {string} args.value The value of the text node item.
|
* @param {string} value The value of the text node item.
|
||||||
* @param {number} args.index The index of the text node item.
|
* @param {number} index The index of the text node item.
|
||||||
* @param {string} args.percent Percentage of the text node item.
|
* @param {percent} percent Percentage of the text node item.
|
||||||
* @param {boolean} args.hideProgress Whether to hide the progress bar.
|
* @param {boolean} hideProgress Whether to hide the progress bar.
|
||||||
* @param {string} args.progressBarColor The color of the progress bar.
|
* @param {string} progressBarBackgroundColor The color of the progress bar background.
|
||||||
* @param {string} args.progressBarBackgroundColor The color of the progress bar background.
|
|
||||||
*/
|
*/
|
||||||
const createTextNode = ({
|
const createTextNode = ({
|
||||||
id,
|
id,
|
||||||
@@ -140,7 +139,7 @@ const createTextNode = ({
|
|||||||
* hiding languages.
|
* hiding languages.
|
||||||
*
|
*
|
||||||
* @param {import("../fetchers/types").WakaTimeLang[]} languages The languages array.
|
* @param {import("../fetchers/types").WakaTimeLang[]} languages The languages array.
|
||||||
* @return {void} The recalculated languages array.
|
* @return {import("../fetchers/types").WakaTimeLang[]} The recalculated languages array.
|
||||||
*/
|
*/
|
||||||
const recalculatePercentages = (languages) => {
|
const recalculatePercentages = (languages) => {
|
||||||
const totalSum = languages.reduce(
|
const totalSum = languages.reduce(
|
||||||
@@ -268,20 +267,12 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
|
|||||||
<rect x="25" y="0" width="${width - 50}" height="8" fill="white" rx="5" />
|
<rect x="25" y="0" width="${width - 50}" height="8" fill="white" rx="5" />
|
||||||
</mask>
|
</mask>
|
||||||
${compactProgressBar}
|
${compactProgressBar}
|
||||||
${
|
${createLanguageTextNode({
|
||||||
filteredLanguages.length
|
x: 0,
|
||||||
? createLanguageTextNode({
|
y: 25,
|
||||||
x: 0,
|
langs: filteredLanguages,
|
||||||
y: 25,
|
totalSize: 100,
|
||||||
langs: filteredLanguages,
|
}).join("")}
|
||||||
totalSize: 100,
|
|
||||||
}).join("")
|
|
||||||
: noCodingActivityNode({
|
|
||||||
// @ts-ignore
|
|
||||||
color: textColor,
|
|
||||||
text: i18n.t("wakatimecard.nocodingactivity"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
} else {
|
} else {
|
||||||
finalLayout = flexLayout({
|
finalLayout = flexLayout({
|
||||||
|
|||||||
@@ -12,12 +12,6 @@ class Card {
|
|||||||
* @param {string?=} args.customTitle Card custom title.
|
* @param {string?=} args.customTitle Card custom title.
|
||||||
* @param {string?=} args.defaultTitle Card default title.
|
* @param {string?=} args.defaultTitle Card default title.
|
||||||
* @param {string?=} args.titlePrefixIcon Card title prefix icon.
|
* @param {string?=} args.titlePrefixIcon Card title prefix icon.
|
||||||
* @param {object?=} args.colors Card colors arguments.
|
|
||||||
* @param {string} args.colors.titleColor Card title color.
|
|
||||||
* @param {string} args.colors.textColor Card text color.
|
|
||||||
* @param {string} args.colors.iconColor Card icon color.
|
|
||||||
* @param {string|Array} args.colors.bgColor Card background color.
|
|
||||||
* @param {string} args.colors.borderColor Card border color.
|
|
||||||
* @returns {Card} Card instance.
|
* @returns {Card} Card instance.
|
||||||
*/
|
*/
|
||||||
constructor({
|
constructor({
|
||||||
|
|||||||
+2
-2
@@ -194,15 +194,15 @@ const flexLayout = ({ items, gap, direction, sizes = [] }) => {
|
|||||||
/**
|
/**
|
||||||
* Returns theme based colors with proper overrides and defaults.
|
* Returns theme based colors with proper overrides and defaults.
|
||||||
*
|
*
|
||||||
* @param {Object} args Function arguments.
|
* @param {Object[]} args Function arguments.
|
||||||
* @param {string} args.title_color Card title color.
|
* @param {string} args.title_color Card title color.
|
||||||
* @param {string} args.text_color Card text color.
|
* @param {string} args.text_color Card text color.
|
||||||
* @param {string} args.icon_color Card icon color.
|
* @param {string} args.icon_color Card icon color.
|
||||||
* @param {string} args.bg_color Card background color.
|
* @param {string} args.bg_color Card background color.
|
||||||
* @param {string} args.border_color Card border color.
|
* @param {string} args.border_color Card border color.
|
||||||
* @param {string} args.ring_color Card ring color.
|
|
||||||
* @param {string} args.theme Card theme.
|
* @param {string} args.theme Card theme.
|
||||||
* @param {string} args.fallbackTheme Fallback theme.
|
* @param {string} args.fallbackTheme Fallback theme.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
const getCardColors = ({
|
const getCardColors = ({
|
||||||
title_color,
|
title_color,
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { MissingParamError, request } from "../common/utils.js";
|
|||||||
/**
|
/**
|
||||||
* Repo data fetcher.
|
* Repo data fetcher.
|
||||||
*
|
*
|
||||||
* @param {import('axios').AxiosRequestHeaders} variables Fetcher variables.
|
* @param {import('Axios').AxiosRequestHeaders} variables Fetcher variables.
|
||||||
* @param {string} token GitHub token.
|
* @param {string} token GitHub token.
|
||||||
* @returns {Promise<import('axios').AxiosResponse>} The response.
|
* @returns {Promise<import('Axios').AxiosResponse>} The response.
|
||||||
*/
|
*/
|
||||||
const fetcher = (variables, token) => {
|
const fetcher = (variables, token) => {
|
||||||
return request(
|
return request(
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
/**
|
/**
|
||||||
* Top languages fetcher object.
|
* Top languages fetcher object.
|
||||||
*
|
*
|
||||||
* @param {import('axios').AxiosRequestHeaders} variables Fetcher variables.
|
* @param {import('Axios').AxiosRequestHeaders} variables Fetcher variables.
|
||||||
* @param {string} token GitHub token.
|
* @param {string} token GitHub token.
|
||||||
* @returns {Promise<import('../common/types').StatsFetcherResponse>} Languages fetcher response.
|
* @returns {Promise<import('../common/types').StatsFetcherResponse>} Languages fetcher response.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ const fetchWakatimeStats = async ({ username, api_domain, range }) => {
|
|||||||
const { data } = await axios.get(
|
const { data } = await axios.get(
|
||||||
`https://${
|
`https://${
|
||||||
api_domain ? api_domain.replace(/\/$/gi, "") : "wakatime.com"
|
api_domain ? api_domain.replace(/\/$/gi, "") : "wakatime.com"
|
||||||
}/api/v1/users/${username}/stats/${
|
}/api/v1/users/${username}/stats/${range || ""}?is_including_today=true`,
|
||||||
range || "all_time"
|
|
||||||
}?is_including_today=true`,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return data.data;
|
return data.data;
|
||||||
|
|||||||
+1
-2
@@ -65,11 +65,10 @@ const getAnimations = () => {
|
|||||||
/**
|
/**
|
||||||
* Retrieves CSS styles for a card.
|
* Retrieves CSS styles for a card.
|
||||||
*
|
*
|
||||||
* @param {Object} colors The colors to use for the card.
|
* @param {Object[]} colors The colors to use for the card.
|
||||||
* @param {string} colors.titleColor The title color.
|
* @param {string} colors.titleColor The title color.
|
||||||
* @param {string} colors.textColor The text color.
|
* @param {string} colors.textColor The text color.
|
||||||
* @param {string} colors.iconColor The icon color.
|
* @param {string} colors.iconColor The icon color.
|
||||||
* @param {string} colors.ringColor The ring color.
|
|
||||||
* @param {boolean} colors.show_icons Whether to show icons.
|
* @param {boolean} colors.show_icons Whether to show icons.
|
||||||
* @param {number} colors.progress The progress value to animate to.
|
* @param {number} colors.progress The progress value to animate to.
|
||||||
* @returns {string} Card CSS styles.
|
* @returns {string} Card CSS styles.
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ const data_stats = {
|
|||||||
nodes: [{ stargazers: { totalCount: 100 } }],
|
nodes: [{ stargazers: { totalCount: 100 } }],
|
||||||
pageInfo: {
|
pageInfo: {
|
||||||
hasNextPage: false,
|
hasNextPage: false,
|
||||||
endCursor: "cursor",
|
cursor: "cursor",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const data_stats = {
|
|||||||
],
|
],
|
||||||
pageInfo: {
|
pageInfo: {
|
||||||
hasNextPage: true,
|
hasNextPage: true,
|
||||||
endCursor: "cursor",
|
cursor: "cursor",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -44,7 +44,7 @@ const data_repo = {
|
|||||||
],
|
],
|
||||||
pageInfo: {
|
pageInfo: {
|
||||||
hasNextPage: false,
|
hasNextPage: false,
|
||||||
endCursor: "cursor",
|
cursor: "cursor",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -64,7 +64,7 @@ const data_repo_zero_stars = {
|
|||||||
],
|
],
|
||||||
pageInfo: {
|
pageInfo: {
|
||||||
hasNextPage: true,
|
hasNextPage: true,
|
||||||
endCursor: "cursor",
|
cursor: "cursor",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -86,12 +86,11 @@ const mock = new MockAdapter(axios);
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
process.env.FETCH_MULTI_PAGE_STARS = "false"; // Set to `false` to fetch only one page of stars.
|
process.env.FETCH_MULTI_PAGE_STARS = "false"; // Set to `false` to fetch only one page of stars.
|
||||||
mock.onPost("https://api.github.com/graphql").reply((cfg) => {
|
mock
|
||||||
return [
|
.onPost("https://api.github.com/graphql")
|
||||||
200,
|
.replyOnce(200, data_stats)
|
||||||
cfg.data.includes("contributionsCollection") ? data_stats : data_repo,
|
.onPost("https://api.github.com/graphql")
|
||||||
];
|
.replyOnce(200, data_repo);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ describe("Wakatime fetcher", () => {
|
|||||||
const username = "anuraghazra";
|
const username = "anuraghazra";
|
||||||
mock
|
mock
|
||||||
.onGet(
|
.onGet(
|
||||||
`https://wakatime.com/api/v1/users/${username}/stats/all_time?is_including_today=true`,
|
`https://wakatime.com/api/v1/users/${username}/stats/?is_including_today=true`,
|
||||||
)
|
)
|
||||||
.reply(200, wakaTimeData);
|
.reply(200, wakaTimeData);
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,9 @@
|
|||||||
import { queryAllByTestId, queryByTestId } from "@testing-library/dom";
|
import { queryAllByTestId, queryByTestId } from "@testing-library/dom";
|
||||||
import { cssToObject } from "@uppercod/css-to-object";
|
import { cssToObject } from "@uppercod/css-to-object";
|
||||||
import {
|
import {
|
||||||
getLongestLang,
|
|
||||||
degreesToRadians,
|
|
||||||
radiansToDegrees,
|
|
||||||
polarToCartesian,
|
|
||||||
cartesianToPolar,
|
|
||||||
getCircleLength,
|
|
||||||
calculateCompactLayoutHeight,
|
|
||||||
calculateNormalLayoutHeight,
|
|
||||||
calculateDonutLayoutHeight,
|
|
||||||
calculateDonutVerticalLayoutHeight,
|
|
||||||
calculatePieLayoutHeight,
|
|
||||||
donutCenterTranslation,
|
|
||||||
trimTopLanguages,
|
|
||||||
renderTopLanguages,
|
|
||||||
MIN_CARD_WIDTH,
|
MIN_CARD_WIDTH,
|
||||||
|
renderTopLanguages,
|
||||||
} from "../src/cards/top-languages-card.js";
|
} from "../src/cards/top-languages-card.js";
|
||||||
|
|
||||||
// adds special assertions like toHaveTextContent
|
// adds special assertions like toHaveTextContent
|
||||||
import "@testing-library/jest-dom";
|
import "@testing-library/jest-dom";
|
||||||
|
|
||||||
@@ -41,295 +27,6 @@ const langs = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve number array from SVG path definition string.
|
|
||||||
*
|
|
||||||
* @param {string} d SVG path definition string.
|
|
||||||
* @return {number[]} Resulting numbers array.
|
|
||||||
*/
|
|
||||||
const getNumbersFromSvgPathDefinitionAttribute = (d) => {
|
|
||||||
return d
|
|
||||||
.split(" ")
|
|
||||||
.filter((x) => !isNaN(x))
|
|
||||||
.map((x) => parseFloat(x));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the language percentage from the donut chart SVG.
|
|
||||||
*
|
|
||||||
* @param {string} d The SVG path element.
|
|
||||||
* @param {number} centerX The center X coordinate of the donut chart.
|
|
||||||
* @param {number} centerY The center Y coordinate of the donut chart.
|
|
||||||
* @returns {number} The percentage of the language.
|
|
||||||
*/
|
|
||||||
const langPercentFromDonutLayoutSvg = (d, centerX, centerY) => {
|
|
||||||
const dTmp = getNumbersFromSvgPathDefinitionAttribute(d);
|
|
||||||
const endAngle =
|
|
||||||
cartesianToPolar(centerX, centerY, dTmp[0], dTmp[1]).angleInDegrees + 90;
|
|
||||||
let startAngle =
|
|
||||||
cartesianToPolar(centerX, centerY, dTmp[7], dTmp[8]).angleInDegrees + 90;
|
|
||||||
if (startAngle > endAngle) startAngle -= 360;
|
|
||||||
return (endAngle - startAngle) / 3.6;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate language percentage for donut vertical chart SVG.
|
|
||||||
*
|
|
||||||
* @param {number} partLength Length of current chart part..
|
|
||||||
* @param {number} totalCircleLength Total length of circle.
|
|
||||||
* @return {number} Chart part percentage.
|
|
||||||
*/
|
|
||||||
const langPercentFromDonutVerticalLayoutSvg = (
|
|
||||||
partLength,
|
|
||||||
totalCircleLength,
|
|
||||||
) => {
|
|
||||||
return (partLength / totalCircleLength) * 100;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the language percentage from the pie chart SVG.
|
|
||||||
*
|
|
||||||
* @param {string} d The SVG path element.
|
|
||||||
* @param {number} centerX The center X coordinate of the pie chart.
|
|
||||||
* @param {number} centerY The center Y coordinate of the pie chart.
|
|
||||||
* @returns {number} The percentage of the language.
|
|
||||||
*/
|
|
||||||
const langPercentFromPieLayoutSvg = (d, centerX, centerY) => {
|
|
||||||
const dTmp = getNumbersFromSvgPathDefinitionAttribute(d);
|
|
||||||
const startAngle = cartesianToPolar(
|
|
||||||
centerX,
|
|
||||||
centerY,
|
|
||||||
dTmp[2],
|
|
||||||
dTmp[3],
|
|
||||||
).angleInDegrees;
|
|
||||||
let endAngle = cartesianToPolar(
|
|
||||||
centerX,
|
|
||||||
centerY,
|
|
||||||
dTmp[9],
|
|
||||||
dTmp[10],
|
|
||||||
).angleInDegrees;
|
|
||||||
return ((endAngle - startAngle) / 360) * 100;
|
|
||||||
};
|
|
||||||
|
|
||||||
describe("Test renderTopLanguages helper functions", () => {
|
|
||||||
it("getLongestLang", () => {
|
|
||||||
const langArray = Object.values(langs);
|
|
||||||
expect(getLongestLang(langArray)).toBe(langs.javascript);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("degreesToRadians", () => {
|
|
||||||
expect(degreesToRadians(0)).toBe(0);
|
|
||||||
expect(degreesToRadians(90)).toBe(Math.PI / 2);
|
|
||||||
expect(degreesToRadians(180)).toBe(Math.PI);
|
|
||||||
expect(degreesToRadians(270)).toBe((3 * Math.PI) / 2);
|
|
||||||
expect(degreesToRadians(360)).toBe(2 * Math.PI);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("radiansToDegrees", () => {
|
|
||||||
expect(radiansToDegrees(0)).toBe(0);
|
|
||||||
expect(radiansToDegrees(Math.PI / 2)).toBe(90);
|
|
||||||
expect(radiansToDegrees(Math.PI)).toBe(180);
|
|
||||||
expect(radiansToDegrees((3 * Math.PI) / 2)).toBe(270);
|
|
||||||
expect(radiansToDegrees(2 * Math.PI)).toBe(360);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("polarToCartesian", () => {
|
|
||||||
expect(polarToCartesian(100, 100, 60, 0)).toStrictEqual({ x: 160, y: 100 });
|
|
||||||
expect(polarToCartesian(100, 100, 60, 45)).toStrictEqual({
|
|
||||||
x: 142.42640687119285,
|
|
||||||
y: 142.42640687119285,
|
|
||||||
});
|
|
||||||
expect(polarToCartesian(100, 100, 60, 90)).toStrictEqual({
|
|
||||||
x: 100,
|
|
||||||
y: 160,
|
|
||||||
});
|
|
||||||
expect(polarToCartesian(100, 100, 60, 135)).toStrictEqual({
|
|
||||||
x: 57.573593128807154,
|
|
||||||
y: 142.42640687119285,
|
|
||||||
});
|
|
||||||
expect(polarToCartesian(100, 100, 60, 180)).toStrictEqual({
|
|
||||||
x: 40,
|
|
||||||
y: 100.00000000000001,
|
|
||||||
});
|
|
||||||
expect(polarToCartesian(100, 100, 60, 225)).toStrictEqual({
|
|
||||||
x: 57.57359312880714,
|
|
||||||
y: 57.573593128807154,
|
|
||||||
});
|
|
||||||
expect(polarToCartesian(100, 100, 60, 270)).toStrictEqual({
|
|
||||||
x: 99.99999999999999,
|
|
||||||
y: 40,
|
|
||||||
});
|
|
||||||
expect(polarToCartesian(100, 100, 60, 315)).toStrictEqual({
|
|
||||||
x: 142.42640687119285,
|
|
||||||
y: 57.57359312880714,
|
|
||||||
});
|
|
||||||
expect(polarToCartesian(100, 100, 60, 360)).toStrictEqual({
|
|
||||||
x: 160,
|
|
||||||
y: 99.99999999999999,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("cartesianToPolar", () => {
|
|
||||||
expect(cartesianToPolar(100, 100, 160, 100)).toStrictEqual({
|
|
||||||
radius: 60,
|
|
||||||
angleInDegrees: 0,
|
|
||||||
});
|
|
||||||
expect(
|
|
||||||
cartesianToPolar(100, 100, 142.42640687119285, 142.42640687119285),
|
|
||||||
).toStrictEqual({ radius: 60.00000000000001, angleInDegrees: 45 });
|
|
||||||
expect(cartesianToPolar(100, 100, 100, 160)).toStrictEqual({
|
|
||||||
radius: 60,
|
|
||||||
angleInDegrees: 90,
|
|
||||||
});
|
|
||||||
expect(
|
|
||||||
cartesianToPolar(100, 100, 57.573593128807154, 142.42640687119285),
|
|
||||||
).toStrictEqual({ radius: 60, angleInDegrees: 135 });
|
|
||||||
expect(cartesianToPolar(100, 100, 40, 100.00000000000001)).toStrictEqual({
|
|
||||||
radius: 60,
|
|
||||||
angleInDegrees: 180,
|
|
||||||
});
|
|
||||||
expect(
|
|
||||||
cartesianToPolar(100, 100, 57.57359312880714, 57.573593128807154),
|
|
||||||
).toStrictEqual({ radius: 60, angleInDegrees: 225 });
|
|
||||||
expect(cartesianToPolar(100, 100, 99.99999999999999, 40)).toStrictEqual({
|
|
||||||
radius: 60,
|
|
||||||
angleInDegrees: 270,
|
|
||||||
});
|
|
||||||
expect(
|
|
||||||
cartesianToPolar(100, 100, 142.42640687119285, 57.57359312880714),
|
|
||||||
).toStrictEqual({ radius: 60.00000000000001, angleInDegrees: 315 });
|
|
||||||
expect(cartesianToPolar(100, 100, 160, 99.99999999999999)).toStrictEqual({
|
|
||||||
radius: 60,
|
|
||||||
angleInDegrees: 360,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("calculateCompactLayoutHeight", () => {
|
|
||||||
expect(calculateCompactLayoutHeight(0)).toBe(90);
|
|
||||||
expect(calculateCompactLayoutHeight(1)).toBe(115);
|
|
||||||
expect(calculateCompactLayoutHeight(2)).toBe(115);
|
|
||||||
expect(calculateCompactLayoutHeight(3)).toBe(140);
|
|
||||||
expect(calculateCompactLayoutHeight(4)).toBe(140);
|
|
||||||
expect(calculateCompactLayoutHeight(5)).toBe(165);
|
|
||||||
expect(calculateCompactLayoutHeight(6)).toBe(165);
|
|
||||||
expect(calculateCompactLayoutHeight(7)).toBe(190);
|
|
||||||
expect(calculateCompactLayoutHeight(8)).toBe(190);
|
|
||||||
expect(calculateCompactLayoutHeight(9)).toBe(215);
|
|
||||||
expect(calculateCompactLayoutHeight(10)).toBe(215);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("calculateNormalLayoutHeight", () => {
|
|
||||||
expect(calculateNormalLayoutHeight(0)).toBe(85);
|
|
||||||
expect(calculateNormalLayoutHeight(1)).toBe(125);
|
|
||||||
expect(calculateNormalLayoutHeight(2)).toBe(165);
|
|
||||||
expect(calculateNormalLayoutHeight(3)).toBe(205);
|
|
||||||
expect(calculateNormalLayoutHeight(4)).toBe(245);
|
|
||||||
expect(calculateNormalLayoutHeight(5)).toBe(285);
|
|
||||||
expect(calculateNormalLayoutHeight(6)).toBe(325);
|
|
||||||
expect(calculateNormalLayoutHeight(7)).toBe(365);
|
|
||||||
expect(calculateNormalLayoutHeight(8)).toBe(405);
|
|
||||||
expect(calculateNormalLayoutHeight(9)).toBe(445);
|
|
||||||
expect(calculateNormalLayoutHeight(10)).toBe(485);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("calculateDonutLayoutHeight", () => {
|
|
||||||
expect(calculateDonutLayoutHeight(0)).toBe(215);
|
|
||||||
expect(calculateDonutLayoutHeight(1)).toBe(215);
|
|
||||||
expect(calculateDonutLayoutHeight(2)).toBe(215);
|
|
||||||
expect(calculateDonutLayoutHeight(3)).toBe(215);
|
|
||||||
expect(calculateDonutLayoutHeight(4)).toBe(215);
|
|
||||||
expect(calculateDonutLayoutHeight(5)).toBe(215);
|
|
||||||
expect(calculateDonutLayoutHeight(6)).toBe(247);
|
|
||||||
expect(calculateDonutLayoutHeight(7)).toBe(279);
|
|
||||||
expect(calculateDonutLayoutHeight(8)).toBe(311);
|
|
||||||
expect(calculateDonutLayoutHeight(9)).toBe(343);
|
|
||||||
expect(calculateDonutLayoutHeight(10)).toBe(375);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("calculateDonutVerticalLayoutHeight", () => {
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(0)).toBe(300);
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(1)).toBe(325);
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(2)).toBe(325);
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(3)).toBe(350);
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(4)).toBe(350);
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(5)).toBe(375);
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(6)).toBe(375);
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(7)).toBe(400);
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(8)).toBe(400);
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(9)).toBe(425);
|
|
||||||
expect(calculateDonutVerticalLayoutHeight(10)).toBe(425);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("calculatePieLayoutHeight", () => {
|
|
||||||
expect(calculatePieLayoutHeight(0)).toBe(300);
|
|
||||||
expect(calculatePieLayoutHeight(1)).toBe(325);
|
|
||||||
expect(calculatePieLayoutHeight(2)).toBe(325);
|
|
||||||
expect(calculatePieLayoutHeight(3)).toBe(350);
|
|
||||||
expect(calculatePieLayoutHeight(4)).toBe(350);
|
|
||||||
expect(calculatePieLayoutHeight(5)).toBe(375);
|
|
||||||
expect(calculatePieLayoutHeight(6)).toBe(375);
|
|
||||||
expect(calculatePieLayoutHeight(7)).toBe(400);
|
|
||||||
expect(calculatePieLayoutHeight(8)).toBe(400);
|
|
||||||
expect(calculatePieLayoutHeight(9)).toBe(425);
|
|
||||||
expect(calculatePieLayoutHeight(10)).toBe(425);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("donutCenterTranslation", () => {
|
|
||||||
expect(donutCenterTranslation(0)).toBe(-45);
|
|
||||||
expect(donutCenterTranslation(1)).toBe(-45);
|
|
||||||
expect(donutCenterTranslation(2)).toBe(-45);
|
|
||||||
expect(donutCenterTranslation(3)).toBe(-45);
|
|
||||||
expect(donutCenterTranslation(4)).toBe(-45);
|
|
||||||
expect(donutCenterTranslation(5)).toBe(-45);
|
|
||||||
expect(donutCenterTranslation(6)).toBe(-29);
|
|
||||||
expect(donutCenterTranslation(7)).toBe(-13);
|
|
||||||
expect(donutCenterTranslation(8)).toBe(3);
|
|
||||||
expect(donutCenterTranslation(9)).toBe(19);
|
|
||||||
expect(donutCenterTranslation(10)).toBe(35);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("getCircleLength", () => {
|
|
||||||
expect(getCircleLength(20)).toBeCloseTo(125.663);
|
|
||||||
expect(getCircleLength(30)).toBeCloseTo(188.495);
|
|
||||||
expect(getCircleLength(40)).toBeCloseTo(251.327);
|
|
||||||
expect(getCircleLength(50)).toBeCloseTo(314.159);
|
|
||||||
expect(getCircleLength(60)).toBeCloseTo(376.991);
|
|
||||||
expect(getCircleLength(70)).toBeCloseTo(439.822);
|
|
||||||
expect(getCircleLength(80)).toBeCloseTo(502.654);
|
|
||||||
expect(getCircleLength(90)).toBeCloseTo(565.486);
|
|
||||||
expect(getCircleLength(100)).toBeCloseTo(628.318);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("trimTopLanguages", () => {
|
|
||||||
expect(trimTopLanguages([])).toStrictEqual({
|
|
||||||
langs: [],
|
|
||||||
totalLanguageSize: 0,
|
|
||||||
});
|
|
||||||
expect(trimTopLanguages([langs.javascript])).toStrictEqual({
|
|
||||||
langs: [langs.javascript],
|
|
||||||
totalLanguageSize: 200,
|
|
||||||
});
|
|
||||||
expect(
|
|
||||||
trimTopLanguages([langs.javascript, langs.HTML], [], 5),
|
|
||||||
).toStrictEqual({
|
|
||||||
langs: [langs.javascript, langs.HTML],
|
|
||||||
totalLanguageSize: 400,
|
|
||||||
});
|
|
||||||
expect(trimTopLanguages(langs, [], 5)).toStrictEqual({
|
|
||||||
langs: Object.values(langs),
|
|
||||||
totalLanguageSize: 500,
|
|
||||||
});
|
|
||||||
expect(trimTopLanguages(langs, [], 2)).toStrictEqual({
|
|
||||||
langs: Object.values(langs).slice(0, 2),
|
|
||||||
totalLanguageSize: 400,
|
|
||||||
});
|
|
||||||
expect(trimTopLanguages(langs, ["javascript"], 5)).toStrictEqual({
|
|
||||||
langs: [langs.HTML, langs.css],
|
|
||||||
totalLanguageSize: 300,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Test renderTopLanguages", () => {
|
describe("Test renderTopLanguages", () => {
|
||||||
it("should render correctly", () => {
|
it("should render correctly", () => {
|
||||||
document.body.innerHTML = renderTopLanguages(langs);
|
document.body.innerHTML = renderTopLanguages(langs);
|
||||||
@@ -539,250 +236,6 @@ describe("Test renderTopLanguages", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render with layout donut", () => {
|
|
||||||
document.body.innerHTML = renderTopLanguages(langs, { layout: "donut" });
|
|
||||||
|
|
||||||
expect(queryByTestId(document.body, "header")).toHaveTextContent(
|
|
||||||
"Most Used Languages",
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
|
|
||||||
"HTML 40.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-donut")[0]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"40",
|
|
||||||
);
|
|
||||||
const d = getNumbersFromSvgPathDefinitionAttribute(
|
|
||||||
queryAllByTestId(document.body, "lang-donut")[0].getAttribute("d"),
|
|
||||||
);
|
|
||||||
const center = { x: d[7], y: d[7] };
|
|
||||||
const HTMLLangPercent = langPercentFromDonutLayoutSvg(
|
|
||||||
queryAllByTestId(document.body, "lang-donut")[0].getAttribute("d"),
|
|
||||||
center.x,
|
|
||||||
center.y,
|
|
||||||
);
|
|
||||||
expect(HTMLLangPercent).toBeCloseTo(40);
|
|
||||||
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent(
|
|
||||||
"javascript 40.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-donut")[1]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"40",
|
|
||||||
);
|
|
||||||
const javascriptLangPercent = langPercentFromDonutLayoutSvg(
|
|
||||||
queryAllByTestId(document.body, "lang-donut")[1].getAttribute("d"),
|
|
||||||
center.x,
|
|
||||||
center.y,
|
|
||||||
);
|
|
||||||
expect(javascriptLangPercent).toBeCloseTo(40);
|
|
||||||
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent(
|
|
||||||
"css 20.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-donut")[2]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"20",
|
|
||||||
);
|
|
||||||
const cssLangPercent = langPercentFromDonutLayoutSvg(
|
|
||||||
queryAllByTestId(document.body, "lang-donut")[2].getAttribute("d"),
|
|
||||||
center.x,
|
|
||||||
center.y,
|
|
||||||
);
|
|
||||||
expect(cssLangPercent).toBeCloseTo(20);
|
|
||||||
|
|
||||||
expect(HTMLLangPercent + javascriptLangPercent + cssLangPercent).toBe(100);
|
|
||||||
|
|
||||||
// Should render full donut (circle) if one language is 100%.
|
|
||||||
document.body.innerHTML = renderTopLanguages(
|
|
||||||
{ HTML: langs.HTML },
|
|
||||||
{ layout: "donut" },
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
|
|
||||||
"HTML 100.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-donut")[0]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"100",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-donut")).toHaveLength(1);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-donut")[0].tagName).toBe(
|
|
||||||
"circle",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should render with layout donut vertical", () => {
|
|
||||||
document.body.innerHTML = renderTopLanguages(langs, {
|
|
||||||
layout: "donut-vertical",
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(queryByTestId(document.body, "header")).toHaveTextContent(
|
|
||||||
"Most Used Languages",
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
|
|
||||||
"HTML 40.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-donut")[0]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"40",
|
|
||||||
);
|
|
||||||
|
|
||||||
const totalCircleLength = queryAllByTestId(
|
|
||||||
document.body,
|
|
||||||
"lang-donut",
|
|
||||||
)[0].getAttribute("stroke-dasharray");
|
|
||||||
|
|
||||||
const HTMLLangPercent = langPercentFromDonutVerticalLayoutSvg(
|
|
||||||
queryAllByTestId(document.body, "lang-donut")[1].getAttribute(
|
|
||||||
"stroke-dashoffset",
|
|
||||||
) -
|
|
||||||
queryAllByTestId(document.body, "lang-donut")[0].getAttribute(
|
|
||||||
"stroke-dashoffset",
|
|
||||||
),
|
|
||||||
totalCircleLength,
|
|
||||||
);
|
|
||||||
expect(HTMLLangPercent).toBeCloseTo(40);
|
|
||||||
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent(
|
|
||||||
"javascript 40.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-donut")[1]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"40",
|
|
||||||
);
|
|
||||||
const javascriptLangPercent = langPercentFromDonutVerticalLayoutSvg(
|
|
||||||
queryAllByTestId(document.body, "lang-donut")[2].getAttribute(
|
|
||||||
"stroke-dashoffset",
|
|
||||||
) -
|
|
||||||
queryAllByTestId(document.body, "lang-donut")[1].getAttribute(
|
|
||||||
"stroke-dashoffset",
|
|
||||||
),
|
|
||||||
totalCircleLength,
|
|
||||||
);
|
|
||||||
expect(javascriptLangPercent).toBeCloseTo(40);
|
|
||||||
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent(
|
|
||||||
"css 20.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-donut")[2]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"20",
|
|
||||||
);
|
|
||||||
const cssLangPercent = langPercentFromDonutVerticalLayoutSvg(
|
|
||||||
totalCircleLength -
|
|
||||||
queryAllByTestId(document.body, "lang-donut")[2].getAttribute(
|
|
||||||
"stroke-dashoffset",
|
|
||||||
),
|
|
||||||
totalCircleLength,
|
|
||||||
);
|
|
||||||
expect(cssLangPercent).toBeCloseTo(20);
|
|
||||||
|
|
||||||
expect(HTMLLangPercent + javascriptLangPercent + cssLangPercent).toBe(100);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should render with layout donut vertical full donut circle of one language is 100%", () => {
|
|
||||||
document.body.innerHTML = renderTopLanguages(
|
|
||||||
{ HTML: langs.HTML },
|
|
||||||
{ layout: "donut-vertical" },
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
|
|
||||||
"HTML 100.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-donut")[0]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"100",
|
|
||||||
);
|
|
||||||
const totalCircleLength = queryAllByTestId(
|
|
||||||
document.body,
|
|
||||||
"lang-donut",
|
|
||||||
)[0].getAttribute("stroke-dasharray");
|
|
||||||
|
|
||||||
const HTMLLangPercent = langPercentFromDonutVerticalLayoutSvg(
|
|
||||||
totalCircleLength -
|
|
||||||
queryAllByTestId(document.body, "lang-donut")[0].getAttribute(
|
|
||||||
"stroke-dashoffset",
|
|
||||||
),
|
|
||||||
totalCircleLength,
|
|
||||||
);
|
|
||||||
expect(HTMLLangPercent).toBeCloseTo(100);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should render with layout pie", () => {
|
|
||||||
document.body.innerHTML = renderTopLanguages(langs, { layout: "pie" });
|
|
||||||
|
|
||||||
expect(queryByTestId(document.body, "header")).toHaveTextContent(
|
|
||||||
"Most Used Languages",
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
|
|
||||||
"HTML 40.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-pie")[0]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"40",
|
|
||||||
);
|
|
||||||
|
|
||||||
const d = getNumbersFromSvgPathDefinitionAttribute(
|
|
||||||
queryAllByTestId(document.body, "lang-pie")[0].getAttribute("d"),
|
|
||||||
);
|
|
||||||
const center = { x: d[0], y: d[1] };
|
|
||||||
const HTMLLangPercent = langPercentFromPieLayoutSvg(
|
|
||||||
queryAllByTestId(document.body, "lang-pie")[0].getAttribute("d"),
|
|
||||||
center.x,
|
|
||||||
center.y,
|
|
||||||
);
|
|
||||||
expect(HTMLLangPercent).toBeCloseTo(40);
|
|
||||||
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[1]).toHaveTextContent(
|
|
||||||
"javascript 40.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-pie")[1]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"40",
|
|
||||||
);
|
|
||||||
const javascriptLangPercent = langPercentFromPieLayoutSvg(
|
|
||||||
queryAllByTestId(document.body, "lang-pie")[1].getAttribute("d"),
|
|
||||||
center.x,
|
|
||||||
center.y,
|
|
||||||
);
|
|
||||||
expect(javascriptLangPercent).toBeCloseTo(40);
|
|
||||||
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[2]).toHaveTextContent(
|
|
||||||
"css 20.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-pie")[2]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"20",
|
|
||||||
);
|
|
||||||
const cssLangPercent = langPercentFromPieLayoutSvg(
|
|
||||||
queryAllByTestId(document.body, "lang-pie")[2].getAttribute("d"),
|
|
||||||
center.x,
|
|
||||||
center.y,
|
|
||||||
);
|
|
||||||
expect(cssLangPercent).toBeCloseTo(20);
|
|
||||||
|
|
||||||
expect(HTMLLangPercent + javascriptLangPercent + cssLangPercent).toBe(100);
|
|
||||||
|
|
||||||
// Should render full pie (circle) if one language is 100%.
|
|
||||||
document.body.innerHTML = renderTopLanguages(
|
|
||||||
{ HTML: langs.HTML },
|
|
||||||
{ layout: "pie" },
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-name")[0]).toHaveTextContent(
|
|
||||||
"HTML 100.00%",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-pie")[0]).toHaveAttribute(
|
|
||||||
"size",
|
|
||||||
"100",
|
|
||||||
);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-pie")).toHaveLength(1);
|
|
||||||
expect(queryAllByTestId(document.body, "lang-pie")[0].tagName).toBe(
|
|
||||||
"circle",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should render a translated title", () => {
|
it("should render a translated title", () => {
|
||||||
document.body.innerHTML = renderTopLanguages(langs, { locale: "cn" });
|
document.body.innerHTML = renderTopLanguages(langs, { locale: "cn" });
|
||||||
expect(document.getElementsByClassName("header")[0].textContent).toBe(
|
expect(document.getElementsByClassName("header")[0].textContent).toBe(
|
||||||
|
|||||||
@@ -67,19 +67,4 @@ describe("Test Render Wakatime Card", () => {
|
|||||||
"No coding activity this week",
|
"No coding activity this week",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show "no coding activity this week" message when using compact layout and there has not been activity', () => {
|
|
||||||
document.body.innerHTML = renderWakatimeCard(
|
|
||||||
{
|
|
||||||
...wakaTimeData.data,
|
|
||||||
languages: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
layout: "compact",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(document.querySelector(".stat").textContent).toBe(
|
|
||||||
"No coding activity this week",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user