@stats-organization/github-readme-stats-core 2.1.5 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/api/gist.d.ts +2 -7
- package/build/api/gist.d.ts.map +1 -1
- package/build/api/gist.js +9 -41
- package/build/api/index.d.ts +3 -8
- package/build/api/index.d.ts.map +1 -1
- package/build/api/index.js +23 -45
- package/build/api/pin.d.ts +2 -7
- package/build/api/pin.d.ts.map +1 -1
- package/build/api/pin.js +9 -41
- package/build/api/top-langs.d.ts +2 -7
- package/build/api/top-langs.d.ts.map +1 -1
- package/build/api/top-langs.js +11 -55
- package/build/api/wakatime.d.ts +2 -7
- package/build/api/wakatime.d.ts.map +1 -1
- package/build/api/wakatime.js +9 -41
- package/build/cards/common-options.d.ts +13 -0
- package/build/cards/common-options.d.ts.map +1 -0
- package/build/cards/common-options.js +1 -0
- package/build/cards/gist.d.ts +11 -16
- package/build/cards/gist.d.ts.map +1 -1
- package/build/cards/gist.js +26 -31
- package/build/cards/repo.d.ts +19 -16
- package/build/cards/repo.d.ts.map +1 -1
- package/build/cards/repo.js +58 -60
- package/build/cards/stats.d.ts +29 -46
- package/build/cards/stats.d.ts.map +1 -1
- package/build/cards/stats.js +113 -181
- package/build/cards/top-languages.d.ts +81 -77
- package/build/cards/top-languages.d.ts.map +1 -1
- package/build/cards/top-languages.js +174 -200
- package/build/cards/wakatime.d.ts +21 -11
- package/build/cards/wakatime.d.ts.map +1 -1
- package/build/cards/wakatime.js +73 -111
- package/build/common/Card.d.ts +34 -13
- package/build/common/Card.d.ts.map +1 -1
- package/build/common/Card.js +73 -40
- package/build/common/I18n.d.ts +4 -2
- package/build/common/I18n.d.ts.map +1 -1
- package/build/common/color.d.ts +60 -18
- package/build/common/color.d.ts.map +1 -1
- package/build/common/color.js +102 -5
- package/build/common/config.d.ts +2 -1
- package/build/common/config.d.ts.map +1 -1
- package/build/common/config.js +16 -26
- package/build/common/constants.d.ts +2 -1
- package/build/common/constants.d.ts.map +1 -1
- package/build/common/date.d.ts +37 -0
- package/build/common/date.d.ts.map +1 -0
- package/build/common/date.js +31 -0
- package/build/common/http.d.ts +25 -2
- package/build/common/http.d.ts.map +1 -1
- package/build/common/http.js +26 -3
- package/build/common/icons.d.ts +1 -0
- package/build/common/icons.d.ts.map +1 -1
- package/build/common/icons.js +1 -0
- package/build/common/languageColors.d.ts +11 -0
- package/build/common/languageColors.d.ts.map +1 -0
- package/build/common/languageColors.js +15 -0
- package/build/common/languageColors.json +1 -0
- package/build/common/ops.d.ts +3 -10
- package/build/common/ops.d.ts.map +1 -1
- package/build/common/ops.js +3 -15
- package/build/common/render.d.ts +43 -6
- package/build/common/render.d.ts.map +1 -1
- package/build/common/render.js +77 -11
- package/build/common/retryer.d.ts +3 -2
- package/build/common/retryer.d.ts.map +1 -1
- package/build/common/retryer.js +1 -0
- package/build/fetchers/gist.d.ts.map +1 -1
- package/build/fetchers/gist.js +8 -39
- package/build/fetchers/repo.d.ts +12 -11
- package/build/fetchers/repo.d.ts.map +1 -1
- package/build/fetchers/repo.js +26 -67
- package/build/fetchers/stats.d.ts +24 -17
- package/build/fetchers/stats.d.ts.map +1 -1
- package/build/fetchers/stats.js +302 -183
- package/build/fetchers/top-languages.d.ts +10 -15
- package/build/fetchers/top-languages.d.ts.map +1 -1
- package/build/fetchers/top-languages.js +52 -103
- package/build/fetchers/types.d.ts +24 -20
- package/build/fetchers/types.d.ts.map +1 -1
- package/build/fetchers/wakatime.d.ts +9 -5
- package/build/fetchers/wakatime.d.ts.map +1 -1
- package/build/fetchers/wakatime.js +8 -4
- package/build/graphql/contributionsDocument.d.ts +18 -0
- package/build/graphql/contributionsDocument.d.ts.map +1 -0
- package/build/graphql/contributionsDocument.js +30 -0
- package/build/graphql/generated/common.d.ts +42 -0
- package/build/graphql/generated/common.d.ts.map +1 -0
- package/build/graphql/generated/common.js +2 -0
- package/build/graphql/generated/gist.d.ts +44 -0
- package/build/graphql/generated/gist.d.ts.map +1 -0
- package/build/graphql/generated/gist.js +27 -0
- package/build/graphql/generated/repo.d.ts +67 -0
- package/build/graphql/generated/repo.d.ts.map +1 -0
- package/build/graphql/generated/repo.js +30 -0
- package/build/graphql/generated/stats.d.ts +150 -0
- package/build/graphql/generated/stats.d.ts.map +1 -0
- package/build/graphql/generated/stats.js +95 -0
- package/build/graphql/generated/top-languages.d.ts +54 -0
- package/build/graphql/generated/top-languages.d.ts.map +1 -0
- package/build/graphql/generated/top-languages.js +27 -0
- package/build/graphql/graphqlDocument.d.ts +22 -0
- package/build/graphql/graphqlDocument.d.ts.map +1 -0
- package/build/graphql/graphqlDocument.js +8 -0
- package/build/graphql/reposContributedToDocument.d.ts +27 -0
- package/build/graphql/reposContributedToDocument.d.ts.map +1 -0
- package/build/graphql/reposContributedToDocument.js +59 -0
- package/build/index.d.ts +3 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -1
- package/build/themes/index.d.ts +32 -0
- package/build/themes/index.d.ts.map +1 -1
- package/build/themes/index.js +28 -0
- package/build/translations.d.ts +17 -0
- package/build/translations.d.ts.map +1 -1
- package/build/translations.js +17 -0
- package/package.json +13 -7
- package/src/_github-username-regex.d.ts +4 -0
- package/src/api/gist.js +10 -46
- package/src/api/index.js +30 -51
- package/src/api/pin.js +10 -46
- package/src/api/top-langs.js +13 -60
- package/src/api/wakatime.js +10 -46
- package/src/cards/common-options.ts +13 -0
- package/src/cards/{gist.js → gist.ts} +37 -37
- package/src/cards/{repo.js → repo.ts} +86 -68
- package/src/cards/{stats.js → stats.ts} +168 -219
- package/src/cards/{top-languages.js → top-languages.ts} +309 -265
- package/src/cards/{wakatime.js → wakatime.ts} +136 -130
- package/src/common/Card.ts +94 -49
- package/src/common/I18n.ts +6 -2
- package/src/common/color.ts +163 -14
- package/src/common/config.ts +22 -29
- package/src/common/constants.ts +3 -1
- package/src/common/date.ts +45 -0
- package/src/common/http.ts +43 -3
- package/src/common/icons.ts +1 -0
- package/src/common/languageColors.json +1 -0
- package/src/common/languageColors.ts +19 -0
- package/src/common/ops.ts +8 -18
- package/src/common/render.ts +114 -14
- package/src/common/retryer.ts +6 -5
- package/src/fetchers/gist.ts +15 -72
- package/src/fetchers/repo.ts +114 -0
- package/src/fetchers/stats.ts +743 -0
- package/src/fetchers/top-languages.ts +135 -0
- package/src/fetchers/types.ts +28 -20
- package/src/fetchers/{wakatime.js → wakatime.ts} +19 -5
- package/src/graphql/contributionsDocument.ts +44 -0
- package/src/graphql/generated/common.ts +26 -0
- package/src/graphql/generated/gist.ts +59 -0
- package/src/graphql/generated/repo.ts +90 -0
- package/src/graphql/generated/stats.ts +194 -0
- package/src/graphql/generated/top-languages.ts +75 -0
- package/src/graphql/graphqlDocument.ts +25 -0
- package/src/graphql/queries/gist.graphql +25 -0
- package/src/graphql/queries/repo.graphql +28 -0
- package/src/graphql/queries/stats.graphql +120 -0
- package/src/graphql/queries/top-languages.graphql +34 -0
- package/src/graphql/reposContributedToDocument.ts +86 -0
- package/src/index.ts +3 -1
- package/src/themes/index.ts +33 -0
- package/src/translations.ts +17 -0
- package/src/cards/types.d.ts +0 -78
- package/src/fetchers/repo.js +0 -161
- package/src/fetchers/stats.js +0 -473
- package/src/fetchers/top-languages.js +0 -175
- package/src/themes/README.md +0 -229
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { Card } from "../common/Card.js";
|
|
2
2
|
import { I18n } from "../common/I18n.js";
|
|
3
|
-
import {
|
|
4
|
-
fallbackColor,
|
|
5
|
-
getCardColors,
|
|
6
|
-
isPrefixedHexColor,
|
|
7
|
-
} from "../common/color.js";
|
|
3
|
+
import { getLightDarkColors, isPrefixedHexColor } from "../common/color.js";
|
|
8
4
|
import { formatBytes } from "../common/fmt.js";
|
|
9
5
|
import { encodeHTML } from "../common/html.js";
|
|
6
|
+
import { DEFAULT_LANG_COLOR } from "../common/languageColors.js";
|
|
10
7
|
import { chunkArray, clampValue, lowercaseTrim } from "../common/ops.js";
|
|
11
8
|
import {
|
|
12
9
|
createProgressNode,
|
|
13
10
|
flexLayout,
|
|
14
11
|
measureText,
|
|
15
12
|
} from "../common/render.js";
|
|
13
|
+
import type { Lang, TopLangData } from "../fetchers/types.js";
|
|
16
14
|
import { langCardLocales } from "../translations.js";
|
|
17
15
|
|
|
16
|
+
import type { CommonOptions } from "./common-options.js";
|
|
17
|
+
|
|
18
18
|
const DEFAULT_CARD_WIDTH = 300;
|
|
19
19
|
const MIN_CARD_WIDTH = 280;
|
|
20
|
-
const DEFAULT_LANG_COLOR = "#858585";
|
|
21
20
|
const CARD_PADDING = 25;
|
|
22
21
|
const COMPACT_LAYOUT_BASE_HEIGHT = 90;
|
|
23
22
|
const MAXIMUM_LANGS_COUNT = 20;
|
|
@@ -28,18 +27,32 @@ const DONUT_LAYOUT_DEFAULT_LANGS_COUNT = 5;
|
|
|
28
27
|
const PIE_LAYOUT_DEFAULT_LANGS_COUNT = 6;
|
|
29
28
|
const DONUT_VERTICAL_LAYOUT_DEFAULT_LANGS_COUNT = 6;
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
type TopLangLayout = "compact" | "normal" | "donut" | "donut-vertical" | "pie";
|
|
31
|
+
|
|
32
|
+
interface TopLangOptions extends CommonOptions {
|
|
33
|
+
hide_title: boolean;
|
|
34
|
+
card_width: number;
|
|
35
|
+
hide: Array<string>;
|
|
36
|
+
layout: TopLangLayout;
|
|
37
|
+
custom_title: string;
|
|
38
|
+
langs_count: number;
|
|
39
|
+
disable_animations: boolean;
|
|
40
|
+
hide_progress: boolean;
|
|
41
|
+
hide_values: boolean;
|
|
42
|
+
prog_bar_bg_color: string;
|
|
43
|
+
stats_format: "percentages" | "bytes";
|
|
44
|
+
}
|
|
34
45
|
|
|
35
46
|
/**
|
|
36
47
|
* Retrieves the programming language whose name is the longest.
|
|
37
48
|
*
|
|
38
|
-
* @param
|
|
39
|
-
* @returns
|
|
49
|
+
* @param arr Array of programming languages.
|
|
50
|
+
* @returns Longest programming language object.
|
|
40
51
|
*/
|
|
41
|
-
const getLongestLang = (
|
|
42
|
-
arr
|
|
52
|
+
const getLongestLang = (
|
|
53
|
+
arr: Array<Lang>,
|
|
54
|
+
): Pick<Lang, "name" | "size" | "color"> =>
|
|
55
|
+
arr.reduce<Pick<Lang, "name" | "size" | "color">>(
|
|
43
56
|
(savedLang, lang) =>
|
|
44
57
|
lang.name.length > savedLang.name.length ? lang : savedLang,
|
|
45
58
|
{ name: "", size: 0, color: "" },
|
|
@@ -48,29 +61,36 @@ const getLongestLang = (arr) =>
|
|
|
48
61
|
/**
|
|
49
62
|
* Convert degrees to radians.
|
|
50
63
|
*
|
|
51
|
-
* @param
|
|
52
|
-
* @returns
|
|
64
|
+
* @param angleInDegrees Angle in degrees.
|
|
65
|
+
* @returns Angle in radians.
|
|
53
66
|
*/
|
|
54
|
-
const degreesToRadians = (angleInDegrees) =>
|
|
67
|
+
const degreesToRadians = (angleInDegrees: number): number =>
|
|
68
|
+
angleInDegrees * (Math.PI / 180.0);
|
|
55
69
|
|
|
56
70
|
/**
|
|
57
71
|
* Convert radians to degrees.
|
|
58
72
|
*
|
|
59
|
-
* @param
|
|
60
|
-
* @returns
|
|
73
|
+
* @param angleInRadians Angle in radians.
|
|
74
|
+
* @returns Angle in degrees.
|
|
61
75
|
*/
|
|
62
|
-
const radiansToDegrees = (angleInRadians) =>
|
|
76
|
+
const radiansToDegrees = (angleInRadians: number): number =>
|
|
77
|
+
angleInRadians / (Math.PI / 180.0);
|
|
63
78
|
|
|
64
79
|
/**
|
|
65
80
|
* Convert polar coordinates to cartesian coordinates.
|
|
66
81
|
*
|
|
67
|
-
* @param
|
|
68
|
-
* @param
|
|
69
|
-
* @param
|
|
70
|
-
* @param
|
|
71
|
-
* @returns
|
|
82
|
+
* @param centerX Center x coordinate.
|
|
83
|
+
* @param centerY Center y coordinate.
|
|
84
|
+
* @param radius Radius of the circle.
|
|
85
|
+
* @param angleInDegrees Angle in degrees.
|
|
86
|
+
* @returns Cartesian coordinates.
|
|
72
87
|
*/
|
|
73
|
-
const polarToCartesian = (
|
|
88
|
+
const polarToCartesian = (
|
|
89
|
+
centerX: number,
|
|
90
|
+
centerY: number,
|
|
91
|
+
radius: number,
|
|
92
|
+
angleInDegrees: number,
|
|
93
|
+
): { x: number; y: number } => {
|
|
74
94
|
const rads = degreesToRadians(angleInDegrees);
|
|
75
95
|
return {
|
|
76
96
|
x: centerX + radius * Math.cos(rads),
|
|
@@ -81,13 +101,18 @@ const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
|
|
|
81
101
|
/**
|
|
82
102
|
* Convert cartesian coordinates to polar coordinates.
|
|
83
103
|
*
|
|
84
|
-
* @param
|
|
85
|
-
* @param
|
|
86
|
-
* @param
|
|
87
|
-
* @param
|
|
88
|
-
* @returns
|
|
104
|
+
* @param centerX Center x coordinate.
|
|
105
|
+
* @param centerY Center y coordinate.
|
|
106
|
+
* @param x Point x coordinate.
|
|
107
|
+
* @param y Point y coordinate.
|
|
108
|
+
* @returns Polar coordinates.
|
|
89
109
|
*/
|
|
90
|
-
const cartesianToPolar = (
|
|
110
|
+
const cartesianToPolar = (
|
|
111
|
+
centerX: number,
|
|
112
|
+
centerY: number,
|
|
113
|
+
x: number,
|
|
114
|
+
y: number,
|
|
115
|
+
): { radius: number; angleInDegrees: number } => {
|
|
91
116
|
const radius = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
|
|
92
117
|
let angleInDegrees = radiansToDegrees(Math.atan2(y - centerY, x - centerX));
|
|
93
118
|
if (angleInDegrees < 0) {
|
|
@@ -99,90 +124,93 @@ const cartesianToPolar = (centerX, centerY, x, y) => {
|
|
|
99
124
|
/**
|
|
100
125
|
* Calculates length of circle.
|
|
101
126
|
*
|
|
102
|
-
* @param
|
|
103
|
-
* @returns
|
|
127
|
+
* @param radius Radius of the circle.
|
|
128
|
+
* @returns The length of the circle.
|
|
104
129
|
*/
|
|
105
|
-
const getCircleLength = (radius) => {
|
|
130
|
+
const getCircleLength = (radius: number): number => {
|
|
106
131
|
return 2 * Math.PI * radius;
|
|
107
132
|
};
|
|
108
133
|
|
|
109
134
|
/**
|
|
110
135
|
* Calculates height for the compact layout.
|
|
111
136
|
*
|
|
112
|
-
* @param
|
|
113
|
-
* @returns
|
|
137
|
+
* @param totalLangs Total number of languages.
|
|
138
|
+
* @returns Card height.
|
|
114
139
|
*/
|
|
115
|
-
const calculateCompactLayoutHeight = (totalLangs) => {
|
|
140
|
+
const calculateCompactLayoutHeight = (totalLangs: number): number => {
|
|
116
141
|
return COMPACT_LAYOUT_BASE_HEIGHT + Math.round(totalLangs / 2) * 25;
|
|
117
142
|
};
|
|
118
143
|
|
|
119
144
|
/**
|
|
120
145
|
* Calculates height for the normal layout.
|
|
121
146
|
*
|
|
122
|
-
* @param
|
|
123
|
-
* @returns
|
|
147
|
+
* @param totalLangs Total number of languages.
|
|
148
|
+
* @returns Card height.
|
|
124
149
|
*/
|
|
125
|
-
const calculateNormalLayoutHeight = (totalLangs) => {
|
|
150
|
+
const calculateNormalLayoutHeight = (totalLangs: number): number => {
|
|
126
151
|
return 45 + (totalLangs + 1) * 40;
|
|
127
152
|
};
|
|
128
153
|
|
|
129
154
|
/**
|
|
130
155
|
* Calculates height for the donut layout.
|
|
131
156
|
*
|
|
132
|
-
* @param
|
|
133
|
-
* @returns
|
|
157
|
+
* @param totalLangs Total number of languages.
|
|
158
|
+
* @returns Card height.
|
|
134
159
|
*/
|
|
135
|
-
const calculateDonutLayoutHeight = (totalLangs) => {
|
|
160
|
+
const calculateDonutLayoutHeight = (totalLangs: number): number => {
|
|
136
161
|
return 215 + Math.max(totalLangs - 5, 0) * 32;
|
|
137
162
|
};
|
|
138
163
|
|
|
139
164
|
/**
|
|
140
165
|
* Calculates height for the donut vertical layout.
|
|
141
166
|
*
|
|
142
|
-
* @param
|
|
143
|
-
* @returns
|
|
167
|
+
* @param totalLangs Total number of languages.
|
|
168
|
+
* @returns Card height.
|
|
144
169
|
*/
|
|
145
|
-
const calculateDonutVerticalLayoutHeight = (totalLangs) => {
|
|
170
|
+
const calculateDonutVerticalLayoutHeight = (totalLangs: number): number => {
|
|
146
171
|
return 300 + Math.round(totalLangs / 2) * 25;
|
|
147
172
|
};
|
|
148
173
|
|
|
149
174
|
/**
|
|
150
175
|
* Calculates height for the pie layout.
|
|
151
176
|
*
|
|
152
|
-
* @param
|
|
153
|
-
* @returns
|
|
177
|
+
* @param totalLangs Total number of languages.
|
|
178
|
+
* @returns Card height.
|
|
154
179
|
*/
|
|
155
|
-
const calculatePieLayoutHeight = (totalLangs) => {
|
|
180
|
+
const calculatePieLayoutHeight = (totalLangs: number): number => {
|
|
156
181
|
return 300 + Math.round(totalLangs / 2) * 25;
|
|
157
182
|
};
|
|
158
183
|
|
|
159
184
|
/**
|
|
160
185
|
* Calculates the center translation needed to keep the donut chart centred.
|
|
161
|
-
*
|
|
162
|
-
* @
|
|
186
|
+
*
|
|
187
|
+
* @param totalLangs Total number of languages.
|
|
188
|
+
* @returns Donut center translation.
|
|
163
189
|
*/
|
|
164
|
-
const donutCenterTranslation = (totalLangs) => {
|
|
190
|
+
const donutCenterTranslation = (totalLangs: number): number => {
|
|
165
191
|
return -45 + Math.max(totalLangs - 5, 0) * 16;
|
|
166
192
|
};
|
|
167
193
|
|
|
168
194
|
/**
|
|
169
195
|
* Trim top languages to lang_count while also hiding certain languages.
|
|
170
196
|
*
|
|
171
|
-
* @param
|
|
172
|
-
* @param
|
|
173
|
-
* @param
|
|
174
|
-
* @returns
|
|
197
|
+
* @param topLangs Top languages.
|
|
198
|
+
* @param langs_count Number of languages to show.
|
|
199
|
+
* @param hide Languages to hide.
|
|
200
|
+
* @returns Trimmed top languages and total size.
|
|
175
201
|
*/
|
|
176
|
-
const trimTopLanguages = (
|
|
202
|
+
const trimTopLanguages = (
|
|
203
|
+
topLangs: TopLangData,
|
|
204
|
+
langs_count: number,
|
|
205
|
+
hide?: Array<string>,
|
|
206
|
+
): { langs: Array<Lang>; totalLanguageSize: number } => {
|
|
177
207
|
let langs = Object.values(topLangs);
|
|
178
|
-
|
|
179
|
-
|
|
208
|
+
const langsToHide: Record<string, boolean> = {};
|
|
209
|
+
const langsCount = clampValue(langs_count, 1, MAXIMUM_LANGS_COUNT);
|
|
180
210
|
|
|
181
|
-
// populate langsToHide map for quick lookup
|
|
182
|
-
// while filtering out
|
|
211
|
+
// populate langsToHide map for quick lookup while filtering out
|
|
183
212
|
if (hide) {
|
|
184
213
|
hide.forEach((langName) => {
|
|
185
|
-
// @ts-ignore
|
|
186
214
|
langsToHide[lowercaseTrim(langName)] = true;
|
|
187
215
|
});
|
|
188
216
|
}
|
|
@@ -190,10 +218,7 @@ const trimTopLanguages = (topLangs, langs_count, hide) => {
|
|
|
190
218
|
// filter out languages to be hidden
|
|
191
219
|
langs = langs
|
|
192
220
|
.sort((a, b) => b.size - a.size)
|
|
193
|
-
.filter((lang) =>
|
|
194
|
-
// @ts-ignore
|
|
195
|
-
return !langsToHide[lowercaseTrim(lang.name)];
|
|
196
|
-
})
|
|
221
|
+
.filter((lang) => !langsToHide[lowercaseTrim(lang.name)])
|
|
197
222
|
.slice(0, langsCount);
|
|
198
223
|
|
|
199
224
|
const totalLanguageSize = langs.reduce((acc, curr) => acc + curr.size, 0);
|
|
@@ -204,41 +229,67 @@ const trimTopLanguages = (topLangs, langs_count, hide) => {
|
|
|
204
229
|
/**
|
|
205
230
|
* Get display value corresponding to the format.
|
|
206
231
|
*
|
|
207
|
-
* @param
|
|
208
|
-
* @param
|
|
209
|
-
* @param
|
|
210
|
-
* @returns
|
|
232
|
+
* @param size Bytes size.
|
|
233
|
+
* @param percentages Percentage value.
|
|
234
|
+
* @param format Format of the stats.
|
|
235
|
+
* @returns Display value.
|
|
211
236
|
*/
|
|
212
|
-
const getDisplayValue = (
|
|
237
|
+
const getDisplayValue = (
|
|
238
|
+
size: number,
|
|
239
|
+
percentages: number,
|
|
240
|
+
format: string,
|
|
241
|
+
): string => {
|
|
213
242
|
return format === "bytes" ? formatBytes(size) : `${percentages.toFixed(2)}%`;
|
|
214
243
|
};
|
|
215
244
|
|
|
245
|
+
/**
|
|
246
|
+
* Resolves a language's display color, falling back to the default, and
|
|
247
|
+
* validates it is a prefixed hex color.
|
|
248
|
+
*
|
|
249
|
+
* @param lang Programming language object.
|
|
250
|
+
* @returns Validated language color.
|
|
251
|
+
*/
|
|
252
|
+
const resolveLangColor = (lang: Lang): string => {
|
|
253
|
+
const color = lang.color || DEFAULT_LANG_COLOR;
|
|
254
|
+
if (!isPrefixedHexColor(color)) {
|
|
255
|
+
throw new Error(`Invalid language color: "${color}"`);
|
|
256
|
+
}
|
|
257
|
+
return color;
|
|
258
|
+
};
|
|
259
|
+
|
|
216
260
|
/**
|
|
217
261
|
* Create progress bar text item for a programming language.
|
|
218
262
|
*
|
|
219
|
-
* @param
|
|
220
|
-
* @param
|
|
221
|
-
* @param
|
|
222
|
-
* @param
|
|
223
|
-
* @param
|
|
224
|
-
* @param
|
|
225
|
-
* @param
|
|
226
|
-
* @param
|
|
227
|
-
* @param
|
|
228
|
-
* @
|
|
229
|
-
* @returns {string} Programming language SVG node.
|
|
263
|
+
* @param props Function properties.
|
|
264
|
+
* @param props.width The card width
|
|
265
|
+
* @param props.color Color of the programming language.
|
|
266
|
+
* @param props.name Name of the programming language.
|
|
267
|
+
* @param props.size Size of the programming language.
|
|
268
|
+
* @param props.totalSize Total size of all languages.
|
|
269
|
+
* @param props.statsFormat Stats format.
|
|
270
|
+
* @param props.hideValues Whether to hide stats values.
|
|
271
|
+
* @param props.index Index of the programming language.
|
|
272
|
+
* @returns Programming language SVG node.
|
|
230
273
|
*/
|
|
231
274
|
const createProgressTextNode = ({
|
|
232
275
|
width,
|
|
233
276
|
color,
|
|
234
|
-
progBarBgColor,
|
|
235
277
|
name,
|
|
236
278
|
size,
|
|
237
279
|
totalSize,
|
|
238
280
|
statsFormat,
|
|
239
281
|
hideValues,
|
|
240
282
|
index,
|
|
241
|
-
}
|
|
283
|
+
}: {
|
|
284
|
+
width: number;
|
|
285
|
+
color: string;
|
|
286
|
+
name: string;
|
|
287
|
+
size: number;
|
|
288
|
+
totalSize: number;
|
|
289
|
+
statsFormat: string;
|
|
290
|
+
hideValues?: boolean | undefined;
|
|
291
|
+
index: number;
|
|
292
|
+
}): string => {
|
|
242
293
|
const staggerDelay = (index + 3) * 150;
|
|
243
294
|
const paddingRight = hideValues ? CARD_PADDING * 2 : 95;
|
|
244
295
|
const progressTextX = width - paddingRight + 10;
|
|
@@ -257,7 +308,6 @@ const createProgressTextNode = ({
|
|
|
257
308
|
color,
|
|
258
309
|
width: progressWidth,
|
|
259
310
|
progress,
|
|
260
|
-
progressBarBackgroundColor: progBarBgColor,
|
|
261
311
|
delay: staggerDelay + 300,
|
|
262
312
|
})}
|
|
263
313
|
</g>
|
|
@@ -267,14 +317,14 @@ const createProgressTextNode = ({
|
|
|
267
317
|
/**
|
|
268
318
|
* Creates compact text item for a programming language.
|
|
269
319
|
*
|
|
270
|
-
* @param
|
|
271
|
-
* @param
|
|
272
|
-
* @param
|
|
273
|
-
* @param
|
|
274
|
-
* @param
|
|
275
|
-
* @param
|
|
276
|
-
* @param
|
|
277
|
-
* @returns
|
|
320
|
+
* @param props Function properties.
|
|
321
|
+
* @param props.lang Programming language object.
|
|
322
|
+
* @param props.totalSize Total size of all languages.
|
|
323
|
+
* @param props.hideProgress Whether to hide percentage.
|
|
324
|
+
* @param props.hideValues Whether to hide stats values (percentages/bytes).
|
|
325
|
+
* @param props.statsFormat Stats format
|
|
326
|
+
* @param props.index Index of the programming language.
|
|
327
|
+
* @returns Compact layout programming language SVG node.
|
|
278
328
|
*/
|
|
279
329
|
const createCompactLangNode = ({
|
|
280
330
|
lang,
|
|
@@ -283,16 +333,19 @@ const createCompactLangNode = ({
|
|
|
283
333
|
hideValues,
|
|
284
334
|
statsFormat = "percentages",
|
|
285
335
|
index,
|
|
286
|
-
}
|
|
336
|
+
}: {
|
|
337
|
+
lang: Lang;
|
|
338
|
+
totalSize: number;
|
|
339
|
+
hideProgress?: boolean | undefined;
|
|
340
|
+
hideValues?: boolean | undefined;
|
|
341
|
+
statsFormat?: string | undefined;
|
|
342
|
+
index: number;
|
|
343
|
+
}): string => {
|
|
287
344
|
const percentages = (lang.size / totalSize) * 100;
|
|
288
345
|
const displayValue = getDisplayValue(lang.size, percentages, statsFormat);
|
|
289
346
|
|
|
290
347
|
const staggerDelay = (index + 3) * 150;
|
|
291
|
-
const color = lang
|
|
292
|
-
|
|
293
|
-
if (!isPrefixedHexColor(color)) {
|
|
294
|
-
throw new Error(`Invalid language color: "${color}"`);
|
|
295
|
-
}
|
|
348
|
+
const color = resolveLangColor(lang);
|
|
296
349
|
|
|
297
350
|
return `
|
|
298
351
|
<g class="stagger" style="animation-delay: ${staggerDelay}ms">
|
|
@@ -307,13 +360,13 @@ const createCompactLangNode = ({
|
|
|
307
360
|
/**
|
|
308
361
|
* Create compact languages text items for all programming languages.
|
|
309
362
|
*
|
|
310
|
-
* @param
|
|
311
|
-
* @param
|
|
312
|
-
* @param
|
|
313
|
-
* @param
|
|
314
|
-
* @param
|
|
315
|
-
* @param
|
|
316
|
-
* @returns
|
|
363
|
+
* @param props Function properties.
|
|
364
|
+
* @param props.langs Array of programming languages.
|
|
365
|
+
* @param props.totalSize Total size of all languages.
|
|
366
|
+
* @param props.hideProgress Whether to hide percentage.
|
|
367
|
+
* @param props.hideValues Whether to hide stats values.
|
|
368
|
+
* @param props.statsFormat Stats format
|
|
369
|
+
* @returns Programming languages SVG node.
|
|
317
370
|
*/
|
|
318
371
|
const createLanguageTextNode = ({
|
|
319
372
|
langs,
|
|
@@ -321,11 +374,16 @@ const createLanguageTextNode = ({
|
|
|
321
374
|
hideProgress,
|
|
322
375
|
hideValues,
|
|
323
376
|
statsFormat,
|
|
324
|
-
}
|
|
377
|
+
}: {
|
|
378
|
+
langs: Array<Lang>;
|
|
379
|
+
totalSize: number;
|
|
380
|
+
hideProgress?: boolean | undefined;
|
|
381
|
+
hideValues?: boolean | undefined;
|
|
382
|
+
statsFormat?: string | undefined;
|
|
383
|
+
}): string => {
|
|
325
384
|
const longestLang = getLongestLang(langs);
|
|
326
385
|
const chunked = chunkArray(langs, langs.length / 2);
|
|
327
386
|
const layouts = chunked.map((array) => {
|
|
328
|
-
// @ts-ignore
|
|
329
387
|
const items = array.map((lang, index) =>
|
|
330
388
|
createCompactLangNode({
|
|
331
389
|
lang,
|
|
@@ -355,19 +413,24 @@ const createLanguageTextNode = ({
|
|
|
355
413
|
/**
|
|
356
414
|
* Create donut languages text items for all programming languages.
|
|
357
415
|
*
|
|
358
|
-
* @param
|
|
359
|
-
* @param
|
|
360
|
-
* @param
|
|
361
|
-
* @param
|
|
362
|
-
* @param
|
|
363
|
-
* @returns
|
|
416
|
+
* @param props Function properties.
|
|
417
|
+
* @param props.langs Array of programming languages.
|
|
418
|
+
* @param props.totalSize Total size of all languages.
|
|
419
|
+
* @param props.hideValues Whether to hide stats values.
|
|
420
|
+
* @param props.statsFormat Stats format
|
|
421
|
+
* @returns Donut layout programming language SVG node.
|
|
364
422
|
*/
|
|
365
423
|
const createDonutLanguagesNode = ({
|
|
366
424
|
langs,
|
|
367
425
|
totalSize,
|
|
368
426
|
hideValues,
|
|
369
427
|
statsFormat,
|
|
370
|
-
}
|
|
428
|
+
}: {
|
|
429
|
+
langs: Array<Lang>;
|
|
430
|
+
totalSize: number;
|
|
431
|
+
hideValues?: boolean | undefined;
|
|
432
|
+
statsFormat?: string | undefined;
|
|
433
|
+
}): string => {
|
|
371
434
|
return flexLayout({
|
|
372
435
|
items: langs.map((lang, index) => {
|
|
373
436
|
return createCompactLangNode({
|
|
@@ -387,22 +450,20 @@ const createDonutLanguagesNode = ({
|
|
|
387
450
|
/**
|
|
388
451
|
* Renders the default language card layout.
|
|
389
452
|
*
|
|
390
|
-
* @param
|
|
391
|
-
* @param
|
|
392
|
-
* @param
|
|
393
|
-
* @param
|
|
394
|
-
* @param
|
|
395
|
-
* @
|
|
396
|
-
* @returns {string} Normal layout card SVG object.
|
|
453
|
+
* @param langs Array of programming languages.
|
|
454
|
+
* @param width Card width.
|
|
455
|
+
* @param totalLanguageSize Total size of all languages.
|
|
456
|
+
* @param statsFormat Stats format.
|
|
457
|
+
* @param hideValues Whether to hide stats values.
|
|
458
|
+
* @returns Normal layout card SVG object.
|
|
397
459
|
*/
|
|
398
460
|
const renderNormalLayout = (
|
|
399
|
-
langs
|
|
400
|
-
width,
|
|
401
|
-
totalLanguageSize,
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
) => {
|
|
461
|
+
langs: Array<Lang>,
|
|
462
|
+
width: number,
|
|
463
|
+
totalLanguageSize: number,
|
|
464
|
+
statsFormat: string,
|
|
465
|
+
hideValues?: boolean,
|
|
466
|
+
): string => {
|
|
406
467
|
return flexLayout({
|
|
407
468
|
items: langs.map((lang, index) => {
|
|
408
469
|
return createProgressTextNode({
|
|
@@ -414,7 +475,6 @@ const renderNormalLayout = (
|
|
|
414
475
|
statsFormat,
|
|
415
476
|
hideValues,
|
|
416
477
|
index,
|
|
417
|
-
progBarBgColor,
|
|
418
478
|
});
|
|
419
479
|
}),
|
|
420
480
|
gap: 40,
|
|
@@ -425,22 +485,22 @@ const renderNormalLayout = (
|
|
|
425
485
|
/**
|
|
426
486
|
* Renders the compact language card layout.
|
|
427
487
|
*
|
|
428
|
-
* @param
|
|
429
|
-
* @param
|
|
430
|
-
* @param
|
|
431
|
-
* @param
|
|
432
|
-
* @param
|
|
433
|
-
* @param
|
|
434
|
-
* @returns
|
|
488
|
+
* @param langs Array of programming languages.
|
|
489
|
+
* @param width Card width.
|
|
490
|
+
* @param totalLanguageSize Total size of all languages.
|
|
491
|
+
* @param hideProgress Whether to hide progress bar.
|
|
492
|
+
* @param statsFormat Stats format.
|
|
493
|
+
* @param hideValues Whether to hide stats values.
|
|
494
|
+
* @returns Compact layout card SVG object.
|
|
435
495
|
*/
|
|
436
496
|
const renderCompactLayout = (
|
|
437
|
-
langs
|
|
438
|
-
width,
|
|
439
|
-
totalLanguageSize,
|
|
440
|
-
hideProgress,
|
|
497
|
+
langs: Array<Lang>,
|
|
498
|
+
width: number,
|
|
499
|
+
totalLanguageSize: number,
|
|
500
|
+
hideProgress?: boolean,
|
|
441
501
|
statsFormat = "percentages",
|
|
442
|
-
hideValues,
|
|
443
|
-
) => {
|
|
502
|
+
hideValues?: boolean,
|
|
503
|
+
): string => {
|
|
444
504
|
const paddingRight = 50;
|
|
445
505
|
const offsetWidth = width - paddingRight;
|
|
446
506
|
// progressOffset holds the previous language's width and used to offset the next language
|
|
@@ -448,10 +508,7 @@ const renderCompactLayout = (
|
|
|
448
508
|
let progressOffset = 0;
|
|
449
509
|
const compactProgressBar = langs
|
|
450
510
|
.map((lang) => {
|
|
451
|
-
const langColor = lang
|
|
452
|
-
if (!isPrefixedHexColor(langColor)) {
|
|
453
|
-
throw new Error(`Invalid language color: "${langColor}"`);
|
|
454
|
-
}
|
|
511
|
+
const langColor = resolveLangColor(lang);
|
|
455
512
|
|
|
456
513
|
const percentage = parseFloat(
|
|
457
514
|
((lang.size / totalLanguageSize) * offsetWidth).toFixed(2),
|
|
@@ -501,24 +558,24 @@ const renderCompactLayout = (
|
|
|
501
558
|
/**
|
|
502
559
|
* Renders donut vertical layout to display user's most frequently used programming languages.
|
|
503
560
|
*
|
|
504
|
-
* @param
|
|
505
|
-
* @param
|
|
506
|
-
* @param
|
|
507
|
-
* @param
|
|
508
|
-
* @returns
|
|
561
|
+
* @param langs Array of programming languages.
|
|
562
|
+
* @param totalLanguageSize Total size of all languages.
|
|
563
|
+
* @param statsFormat Stats format.
|
|
564
|
+
* @param hideValues Whether to hide stats values.
|
|
565
|
+
* @returns Compact layout card SVG object.
|
|
509
566
|
*/
|
|
510
567
|
const renderDonutVerticalLayout = (
|
|
511
|
-
langs
|
|
512
|
-
totalLanguageSize,
|
|
513
|
-
statsFormat,
|
|
514
|
-
hideValues,
|
|
515
|
-
) => {
|
|
568
|
+
langs: Array<Lang>,
|
|
569
|
+
totalLanguageSize: number,
|
|
570
|
+
statsFormat: string,
|
|
571
|
+
hideValues?: boolean,
|
|
572
|
+
): string => {
|
|
516
573
|
// Donut vertical chart radius and total length
|
|
517
574
|
const radius = 80;
|
|
518
575
|
const totalCircleLength = getCircleLength(radius);
|
|
519
576
|
|
|
520
577
|
// SVG circles
|
|
521
|
-
|
|
578
|
+
const circles = [];
|
|
522
579
|
|
|
523
580
|
// Start indent for donut vertical chart parts
|
|
524
581
|
let indent = 0;
|
|
@@ -528,10 +585,7 @@ const renderDonutVerticalLayout = (
|
|
|
528
585
|
|
|
529
586
|
// Generate each donut vertical chart part
|
|
530
587
|
for (const lang of langs) {
|
|
531
|
-
const langColor = lang
|
|
532
|
-
if (!isPrefixedHexColor(langColor)) {
|
|
533
|
-
throw new Error(`Invalid language color: "${langColor}"`);
|
|
534
|
-
}
|
|
588
|
+
const langColor = resolveLangColor(lang);
|
|
535
589
|
|
|
536
590
|
const percentage = (lang.size / totalLanguageSize) * 100;
|
|
537
591
|
const circleLength = totalCircleLength * (percentage / 100);
|
|
@@ -585,13 +639,18 @@ const renderDonutVerticalLayout = (
|
|
|
585
639
|
/**
|
|
586
640
|
* Renders pie layout to display user's most frequently used programming languages.
|
|
587
641
|
*
|
|
588
|
-
* @param
|
|
589
|
-
* @param
|
|
590
|
-
* @param
|
|
591
|
-
* @param
|
|
592
|
-
* @returns
|
|
642
|
+
* @param langs Array of programming languages.
|
|
643
|
+
* @param totalLanguageSize Total size of all languages.
|
|
644
|
+
* @param statsFormat Stats format.
|
|
645
|
+
* @param hideValues Whether to hide stats values.
|
|
646
|
+
* @returns Compact layout card SVG object.
|
|
593
647
|
*/
|
|
594
|
-
const renderPieLayout = (
|
|
648
|
+
const renderPieLayout = (
|
|
649
|
+
langs: Array<Lang>,
|
|
650
|
+
totalLanguageSize: number,
|
|
651
|
+
statsFormat: string,
|
|
652
|
+
hideValues?: boolean,
|
|
653
|
+
): string => {
|
|
595
654
|
// Pie chart radius and center coordinates
|
|
596
655
|
const radius = 90;
|
|
597
656
|
const centerX = 150;
|
|
@@ -608,10 +667,7 @@ const renderPieLayout = (langs, totalLanguageSize, statsFormat, hideValues) => {
|
|
|
608
667
|
|
|
609
668
|
// Generate each pie chart part
|
|
610
669
|
for (const lang of langs) {
|
|
611
|
-
const langColor = lang
|
|
612
|
-
if (!isPrefixedHexColor(langColor)) {
|
|
613
|
-
throw new Error(`Invalid language color: "${langColor}"`);
|
|
614
|
-
}
|
|
670
|
+
const langColor = resolveLangColor(lang);
|
|
615
671
|
|
|
616
672
|
if (langs.length === 1) {
|
|
617
673
|
paths.push(`
|
|
@@ -689,34 +745,34 @@ const renderPieLayout = (langs, totalLanguageSize, statsFormat, hideValues) => {
|
|
|
689
745
|
/**
|
|
690
746
|
* Creates the SVG paths for the language donut chart.
|
|
691
747
|
*
|
|
692
|
-
* @param
|
|
693
|
-
* @param
|
|
694
|
-
* @param
|
|
695
|
-
* @param
|
|
696
|
-
* @returns
|
|
748
|
+
* @param cx Donut center x-position.
|
|
749
|
+
* @param cy Donut center y-position.
|
|
750
|
+
* @param radius Donut arc Radius.
|
|
751
|
+
* @param percentages Array with donut section percentages.
|
|
752
|
+
* @returns Array of svg path elements
|
|
697
753
|
*/
|
|
698
|
-
const createDonutPaths = (
|
|
699
|
-
|
|
754
|
+
const createDonutPaths = (
|
|
755
|
+
cx: number,
|
|
756
|
+
cy: number,
|
|
757
|
+
radius: number,
|
|
758
|
+
percentages: Array<number>,
|
|
759
|
+
): Array<{ d: string; percent: number }> => {
|
|
760
|
+
const paths: Array<{ d: string; percent: number }> = [];
|
|
700
761
|
let startAngle = 0;
|
|
701
|
-
let endAngle;
|
|
702
762
|
|
|
703
763
|
const totalPercent = percentages.reduce((acc, curr) => acc + curr, 0);
|
|
704
|
-
for (
|
|
705
|
-
const
|
|
764
|
+
for (const rawPercent of percentages) {
|
|
765
|
+
const percent = parseFloat(((rawPercent / totalPercent) * 100).toFixed(2));
|
|
706
766
|
|
|
707
|
-
|
|
708
|
-
((percentages[i] / totalPercent) * 100).toFixed(2),
|
|
709
|
-
);
|
|
710
|
-
|
|
711
|
-
endAngle = 3.6 * percent + startAngle;
|
|
767
|
+
const endAngle = 3.6 * percent + startAngle;
|
|
712
768
|
const startPoint = polarToCartesian(cx, cy, radius, endAngle - 90); // rotate donut 90 degrees counter-clockwise.
|
|
713
769
|
const endPoint = polarToCartesian(cx, cy, radius, startAngle - 90); // rotate donut 90 degrees counter-clockwise.
|
|
714
770
|
const largeArc = endAngle - startAngle <= 180 ? 0 : 1;
|
|
715
771
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
772
|
+
paths.push({
|
|
773
|
+
percent,
|
|
774
|
+
d: `M ${startPoint.x} ${startPoint.y} A ${radius} ${radius} 0 ${largeArc} 0 ${endPoint.x} ${endPoint.y}`,
|
|
775
|
+
});
|
|
720
776
|
startAngle = endAngle;
|
|
721
777
|
}
|
|
722
778
|
|
|
@@ -726,20 +782,20 @@ const createDonutPaths = (cx, cy, radius, percentages) => {
|
|
|
726
782
|
/**
|
|
727
783
|
* Renders the donut language card layout.
|
|
728
784
|
*
|
|
729
|
-
* @param
|
|
730
|
-
* @param
|
|
731
|
-
* @param
|
|
732
|
-
* @param
|
|
733
|
-
* @param
|
|
734
|
-
* @returns
|
|
785
|
+
* @param langs Array of programming languages.
|
|
786
|
+
* @param width Card width.
|
|
787
|
+
* @param totalLanguageSize Total size of all languages.
|
|
788
|
+
* @param statsFormat Stats format.
|
|
789
|
+
* @param hideValues Whether to hide stats values.
|
|
790
|
+
* @returns Donut layout card SVG object.
|
|
735
791
|
*/
|
|
736
792
|
const renderDonutLayout = (
|
|
737
|
-
langs
|
|
738
|
-
width,
|
|
739
|
-
totalLanguageSize,
|
|
740
|
-
statsFormat,
|
|
741
|
-
hideValues,
|
|
742
|
-
) => {
|
|
793
|
+
langs: Array<Lang>,
|
|
794
|
+
width: number,
|
|
795
|
+
totalLanguageSize: number,
|
|
796
|
+
statsFormat: string,
|
|
797
|
+
hideValues?: boolean,
|
|
798
|
+
): string => {
|
|
743
799
|
if (!Number.isFinite(width)) {
|
|
744
800
|
throw new Error(`Invalid width: "${width}"`);
|
|
745
801
|
}
|
|
@@ -749,13 +805,7 @@ const renderDonutLayout = (
|
|
|
749
805
|
const radius = centerX - 60;
|
|
750
806
|
const strokeWidth = 12;
|
|
751
807
|
|
|
752
|
-
const colors = langs.map(
|
|
753
|
-
const langColor = lang.color || DEFAULT_LANG_COLOR;
|
|
754
|
-
if (!isPrefixedHexColor(langColor)) {
|
|
755
|
-
throw new Error(`Invalid language color: "${langColor}"`);
|
|
756
|
-
}
|
|
757
|
-
return langColor;
|
|
758
|
-
});
|
|
808
|
+
const colors = langs.map(resolveLangColor);
|
|
759
809
|
const langsPercents = langs.map((lang) =>
|
|
760
810
|
parseFloat(((lang.size / totalLanguageSize) * 100).toFixed(2)),
|
|
761
811
|
);
|
|
@@ -764,7 +814,7 @@ const renderDonutLayout = (
|
|
|
764
814
|
|
|
765
815
|
const donutPaths =
|
|
766
816
|
langs.length === 1
|
|
767
|
-
? `<circle cx="${centerX}" cy="${centerY}" r="${radius}" stroke="${colors[0]}" fill="none" stroke-width="${strokeWidth}" data-testid="lang-donut" size="100"/>`
|
|
817
|
+
? `<circle cx="${centerX}" cy="${centerY}" r="${radius}" stroke="${colors[0] ?? DEFAULT_LANG_COLOR}" fill="none" stroke-width="${strokeWidth}" data-testid="lang-donut" size="100"/>`
|
|
768
818
|
: langPaths
|
|
769
819
|
.map((section, index) => {
|
|
770
820
|
const staggerDelay = (index + 3) * 100;
|
|
@@ -776,7 +826,7 @@ const renderDonutLayout = (
|
|
|
776
826
|
data-testid="lang-donut"
|
|
777
827
|
size="${section.percent}"
|
|
778
828
|
d="${section.d}"
|
|
779
|
-
stroke="${colors[index]}"
|
|
829
|
+
stroke="${colors[index] ?? DEFAULT_LANG_COLOR}"
|
|
780
830
|
fill="none"
|
|
781
831
|
stroke-width="${strokeWidth}">
|
|
782
832
|
</path>
|
|
@@ -802,41 +852,43 @@ const renderDonutLayout = (
|
|
|
802
852
|
`;
|
|
803
853
|
};
|
|
804
854
|
|
|
805
|
-
/**
|
|
806
|
-
* @typedef {import("./types").TopLangOptions} TopLangOptions
|
|
807
|
-
* @typedef {TopLangOptions["layout"]} Layout
|
|
808
|
-
*/
|
|
809
|
-
|
|
810
855
|
/**
|
|
811
856
|
* Creates the no languages data SVG node.
|
|
812
857
|
*
|
|
813
|
-
* @param
|
|
814
|
-
* @param
|
|
815
|
-
* @param
|
|
816
|
-
* @
|
|
817
|
-
* @returns {string} No languages data SVG node string.
|
|
858
|
+
* @param props Object with function properties.
|
|
859
|
+
* @param props.text No languages data translated text.
|
|
860
|
+
* @param props.layout Card layout.
|
|
861
|
+
* @returns No languages data SVG node string.
|
|
818
862
|
*/
|
|
819
|
-
const noLanguagesDataNode = ({
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
863
|
+
const noLanguagesDataNode = ({
|
|
864
|
+
text,
|
|
865
|
+
layout,
|
|
866
|
+
}: {
|
|
867
|
+
text: string;
|
|
868
|
+
layout: TopLangLayout | undefined;
|
|
869
|
+
}): string => {
|
|
824
870
|
return `
|
|
825
871
|
<text x="${
|
|
826
872
|
layout === "pie" || layout === "donut-vertical" ? CARD_PADDING : 0
|
|
827
|
-
}" y="11" class="stat bold"
|
|
873
|
+
}" y="11" class="stat bold">${encodeHTML(text)}</text>
|
|
828
874
|
`;
|
|
829
875
|
};
|
|
830
876
|
|
|
831
877
|
/**
|
|
832
878
|
* Get default languages count for provided card layout.
|
|
833
879
|
*
|
|
834
|
-
* @param
|
|
835
|
-
* @param
|
|
836
|
-
* @param
|
|
837
|
-
* @returns
|
|
880
|
+
* @param props Function properties.
|
|
881
|
+
* @param props.layout Input layout string.
|
|
882
|
+
* @param props.hide_progress Input hide_progress parameter value.
|
|
883
|
+
* @returns Default languages count for input layout.
|
|
838
884
|
*/
|
|
839
|
-
const getDefaultLanguagesCountByLayout = ({
|
|
885
|
+
const getDefaultLanguagesCountByLayout = ({
|
|
886
|
+
layout,
|
|
887
|
+
hide_progress,
|
|
888
|
+
}: {
|
|
889
|
+
layout?: TopLangLayout | undefined;
|
|
890
|
+
hide_progress?: boolean | undefined;
|
|
891
|
+
}): number => {
|
|
840
892
|
if (layout === "compact" || hide_progress === true) {
|
|
841
893
|
return COMPACT_LAYOUT_DEFAULT_LANGS_COUNT;
|
|
842
894
|
} else if (layout === "donut") {
|
|
@@ -850,36 +902,29 @@ const getDefaultLanguagesCountByLayout = ({ layout, hide_progress }) => {
|
|
|
850
902
|
}
|
|
851
903
|
};
|
|
852
904
|
|
|
853
|
-
/**
|
|
854
|
-
* @typedef {import('../fetchers/types').TopLangData} TopLangData
|
|
855
|
-
*/
|
|
856
|
-
|
|
857
905
|
/**
|
|
858
906
|
* Renders card that display user's most frequently used programming languages.
|
|
859
907
|
*
|
|
860
|
-
* @param
|
|
861
|
-
* @param
|
|
862
|
-
* @returns
|
|
908
|
+
* @param topLangs User's most frequently used programming languages.
|
|
909
|
+
* @param options Card options.
|
|
910
|
+
* @returns Language card SVG object.
|
|
863
911
|
*/
|
|
864
|
-
const renderTopLanguages = (
|
|
912
|
+
const renderTopLanguages = (
|
|
913
|
+
topLangs: TopLangData,
|
|
914
|
+
options: Partial<TopLangOptions> = {},
|
|
915
|
+
): string => {
|
|
865
916
|
const {
|
|
866
917
|
hide_title = false,
|
|
867
918
|
hide_border = false,
|
|
868
919
|
card_width,
|
|
869
|
-
title_color,
|
|
870
|
-
text_color,
|
|
871
|
-
bg_color,
|
|
872
|
-
prog_bar_bg_color,
|
|
873
920
|
hide,
|
|
874
921
|
hide_progress,
|
|
875
922
|
hide_values,
|
|
876
|
-
theme,
|
|
877
923
|
layout,
|
|
878
924
|
custom_title,
|
|
879
925
|
locale,
|
|
880
926
|
langs_count = getDefaultLanguagesCountByLayout({ layout, hide_progress }),
|
|
881
927
|
border_radius,
|
|
882
|
-
border_color,
|
|
883
928
|
disable_animations,
|
|
884
929
|
stats_format = "percentages",
|
|
885
930
|
} = options;
|
|
@@ -904,20 +949,12 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
904
949
|
: DEFAULT_CARD_WIDTH;
|
|
905
950
|
let height = calculateNormalLayoutHeight(langs.length);
|
|
906
951
|
|
|
907
|
-
|
|
908
|
-
const colors = getCardColors({
|
|
909
|
-
title_color,
|
|
910
|
-
text_color,
|
|
911
|
-
bg_color,
|
|
912
|
-
border_color,
|
|
913
|
-
theme,
|
|
914
|
-
});
|
|
952
|
+
const { lightColors, darkColors } = getLightDarkColors(options);
|
|
915
953
|
|
|
916
|
-
let finalLayout;
|
|
954
|
+
let finalLayout: string;
|
|
917
955
|
if (langs.length === 0) {
|
|
918
956
|
height = COMPACT_LAYOUT_BASE_HEIGHT;
|
|
919
957
|
finalLayout = noLanguagesDataNode({
|
|
920
|
-
color: colors.textColor,
|
|
921
958
|
text: i18n.t("langcard.nodata"),
|
|
922
959
|
layout,
|
|
923
960
|
});
|
|
@@ -937,7 +974,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
937
974
|
stats_format,
|
|
938
975
|
hide_values,
|
|
939
976
|
);
|
|
940
|
-
} else if (layout === "compact" || hide_progress
|
|
977
|
+
} else if (layout === "compact" || hide_progress === true) {
|
|
941
978
|
height =
|
|
942
979
|
calculateCompactLayoutHeight(langs.length) + (hide_progress ? -25 : 0);
|
|
943
980
|
|
|
@@ -964,7 +1001,6 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
964
1001
|
langs,
|
|
965
1002
|
width,
|
|
966
1003
|
totalLanguageSize,
|
|
967
|
-
fallbackColor(prog_bar_bg_color, "#ddd"),
|
|
968
1004
|
stats_format,
|
|
969
1005
|
hide_values,
|
|
970
1006
|
);
|
|
@@ -976,7 +1012,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
976
1012
|
width,
|
|
977
1013
|
height,
|
|
978
1014
|
border_radius,
|
|
979
|
-
colors,
|
|
1015
|
+
colors: { light: lightColors, dark: darkColors },
|
|
980
1016
|
});
|
|
981
1017
|
|
|
982
1018
|
if (disable_animations) {
|
|
@@ -985,8 +1021,8 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
985
1021
|
|
|
986
1022
|
card.setHideBorder(hide_border);
|
|
987
1023
|
card.setHideTitle(hide_title);
|
|
988
|
-
card.setCSS(
|
|
989
|
-
`
|
|
1024
|
+
card.setCSS({
|
|
1025
|
+
light: `
|
|
990
1026
|
@keyframes slideInAnimation {
|
|
991
1027
|
from {
|
|
992
1028
|
width: 0;
|
|
@@ -1004,7 +1040,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
1004
1040
|
}
|
|
1005
1041
|
}
|
|
1006
1042
|
.stat {
|
|
1007
|
-
font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${
|
|
1043
|
+
font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${lightColors.textColor};
|
|
1008
1044
|
}
|
|
1009
1045
|
@supports(-moz-appearance: auto) {
|
|
1010
1046
|
/* Selector detects Firefox */
|
|
@@ -1013,7 +1049,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
1013
1049
|
.bold { font-weight: 700 }
|
|
1014
1050
|
.lang-name {
|
|
1015
1051
|
font: 400 11px "Segoe UI", Ubuntu, Sans-Serif;
|
|
1016
|
-
fill: ${
|
|
1052
|
+
fill: ${lightColors.textColor};
|
|
1017
1053
|
}
|
|
1018
1054
|
.stagger {
|
|
1019
1055
|
opacity: 0;
|
|
@@ -1025,8 +1061,16 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
1025
1061
|
.lang-progress{
|
|
1026
1062
|
animation: growWidthAnimation 0.6s ease-in-out forwards;
|
|
1027
1063
|
}
|
|
1064
|
+
.progress-background { fill: ${lightColors.progBarBgColor}; }
|
|
1028
1065
|
`,
|
|
1029
|
-
|
|
1066
|
+
dark: darkColors
|
|
1067
|
+
? `
|
|
1068
|
+
.stat { fill: ${darkColors.textColor}; }
|
|
1069
|
+
.lang-name { fill: ${darkColors.textColor}; }
|
|
1070
|
+
.progress-background { fill: ${darkColors.progBarBgColor}; }
|
|
1071
|
+
`
|
|
1072
|
+
: null,
|
|
1073
|
+
});
|
|
1030
1074
|
|
|
1031
1075
|
if (layout === "pie" || layout === "donut-vertical") {
|
|
1032
1076
|
return card.render(finalLayout);
|