@stats-organization/github-readme-stats-core 2.1.4 → 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.
Files changed (182) hide show
  1. package/build/api/gist.d.ts +2 -7
  2. package/build/api/gist.d.ts.map +1 -1
  3. package/build/api/gist.js +28 -26
  4. package/build/api/index.d.ts +3 -8
  5. package/build/api/index.d.ts.map +1 -1
  6. package/build/api/index.js +32 -36
  7. package/build/api/pin.d.ts +2 -7
  8. package/build/api/pin.d.ts.map +1 -1
  9. package/build/api/pin.js +18 -33
  10. package/build/api/top-langs.d.ts +2 -7
  11. package/build/api/top-langs.d.ts.map +1 -1
  12. package/build/api/top-langs.js +32 -44
  13. package/build/api/wakatime.d.ts +2 -7
  14. package/build/api/wakatime.d.ts.map +1 -1
  15. package/build/api/wakatime.js +28 -26
  16. package/build/calculateRank.d.ts +12 -11
  17. package/build/calculateRank.d.ts.map +1 -1
  18. package/build/calculateRank.js +18 -18
  19. package/build/cards/common-options.d.ts +13 -0
  20. package/build/cards/common-options.d.ts.map +1 -0
  21. package/build/cards/common-options.js +1 -0
  22. package/build/cards/gist.d.ts +11 -16
  23. package/build/cards/gist.d.ts.map +1 -1
  24. package/build/cards/gist.js +26 -31
  25. package/build/cards/repo.d.ts +19 -16
  26. package/build/cards/repo.d.ts.map +1 -1
  27. package/build/cards/repo.js +79 -72
  28. package/build/cards/stats.d.ts +29 -44
  29. package/build/cards/stats.d.ts.map +1 -1
  30. package/build/cards/stats.js +118 -173
  31. package/build/cards/top-languages.d.ts +81 -77
  32. package/build/cards/top-languages.d.ts.map +1 -1
  33. package/build/cards/top-languages.js +186 -184
  34. package/build/cards/wakatime.d.ts +21 -11
  35. package/build/cards/wakatime.d.ts.map +1 -1
  36. package/build/cards/wakatime.js +92 -109
  37. package/build/common/Card.d.ts +41 -14
  38. package/build/common/Card.d.ts.map +1 -1
  39. package/build/common/Card.js +92 -31
  40. package/build/common/I18n.d.ts +4 -2
  41. package/build/common/I18n.d.ts.map +1 -1
  42. package/build/common/color.d.ts +91 -15
  43. package/build/common/color.d.ts.map +1 -1
  44. package/build/common/color.js +163 -17
  45. package/build/common/config.d.ts +2 -1
  46. package/build/common/config.d.ts.map +1 -1
  47. package/build/common/config.js +16 -26
  48. package/build/common/constants.d.ts +2 -1
  49. package/build/common/constants.d.ts.map +1 -1
  50. package/build/common/date.d.ts +37 -0
  51. package/build/common/date.d.ts.map +1 -0
  52. package/build/common/date.js +31 -0
  53. package/build/common/html.js +1 -1
  54. package/build/common/http.d.ts +37 -5
  55. package/build/common/http.d.ts.map +1 -1
  56. package/build/common/http.js +29 -6
  57. package/build/common/icons.d.ts +1 -0
  58. package/build/common/icons.d.ts.map +1 -1
  59. package/build/common/icons.js +1 -0
  60. package/build/common/languageColors.d.ts +11 -0
  61. package/build/common/languageColors.d.ts.map +1 -0
  62. package/build/common/languageColors.js +15 -0
  63. package/build/common/languageColors.json +10 -1
  64. package/build/common/ops.d.ts +27 -33
  65. package/build/common/ops.d.ts.map +1 -1
  66. package/build/common/ops.js +31 -48
  67. package/build/common/render.d.ts +154 -113
  68. package/build/common/render.d.ts.map +1 -1
  69. package/build/common/render.js +209 -92
  70. package/build/common/retryer.d.ts +15 -6
  71. package/build/common/retryer.d.ts.map +1 -1
  72. package/build/common/retryer.js +2 -0
  73. package/build/fetchers/gist.d.ts +6 -21
  74. package/build/fetchers/gist.d.ts.map +1 -1
  75. package/build/fetchers/gist.js +28 -64
  76. package/build/fetchers/repo.d.ts +12 -11
  77. package/build/fetchers/repo.d.ts.map +1 -1
  78. package/build/fetchers/repo.js +27 -68
  79. package/build/fetchers/stats.d.ts +24 -17
  80. package/build/fetchers/stats.d.ts.map +1 -1
  81. package/build/fetchers/stats.js +302 -184
  82. package/build/fetchers/top-languages.d.ts +10 -15
  83. package/build/fetchers/top-languages.d.ts.map +1 -1
  84. package/build/fetchers/top-languages.js +52 -103
  85. package/build/fetchers/types.d.ts +130 -0
  86. package/build/fetchers/types.d.ts.map +1 -0
  87. package/build/fetchers/types.js +1 -0
  88. package/build/fetchers/wakatime.d.ts +9 -5
  89. package/build/fetchers/wakatime.d.ts.map +1 -1
  90. package/build/fetchers/wakatime.js +8 -4
  91. package/build/graphql/contributionsDocument.d.ts +18 -0
  92. package/build/graphql/contributionsDocument.d.ts.map +1 -0
  93. package/build/graphql/contributionsDocument.js +30 -0
  94. package/build/graphql/generated/common.d.ts +42 -0
  95. package/build/graphql/generated/common.d.ts.map +1 -0
  96. package/build/graphql/generated/common.js +2 -0
  97. package/build/graphql/generated/gist.d.ts +44 -0
  98. package/build/graphql/generated/gist.d.ts.map +1 -0
  99. package/build/graphql/generated/gist.js +27 -0
  100. package/build/graphql/generated/repo.d.ts +67 -0
  101. package/build/graphql/generated/repo.d.ts.map +1 -0
  102. package/build/graphql/generated/repo.js +30 -0
  103. package/build/graphql/generated/stats.d.ts +150 -0
  104. package/build/graphql/generated/stats.d.ts.map +1 -0
  105. package/build/graphql/generated/stats.js +95 -0
  106. package/build/graphql/generated/top-languages.d.ts +54 -0
  107. package/build/graphql/generated/top-languages.d.ts.map +1 -0
  108. package/build/graphql/generated/top-languages.js +27 -0
  109. package/build/graphql/graphqlDocument.d.ts +22 -0
  110. package/build/graphql/graphqlDocument.d.ts.map +1 -0
  111. package/build/graphql/graphqlDocument.js +8 -0
  112. package/build/graphql/reposContributedToDocument.d.ts +27 -0
  113. package/build/graphql/reposContributedToDocument.d.ts.map +1 -0
  114. package/build/graphql/reposContributedToDocument.js +59 -0
  115. package/build/index.d.ts +3 -1
  116. package/build/index.d.ts.map +1 -1
  117. package/build/index.js +2 -1
  118. package/build/themes/index.d.ts +32 -0
  119. package/build/themes/index.d.ts.map +1 -1
  120. package/build/themes/index.js +28 -0
  121. package/build/translations.d.ts +17 -0
  122. package/build/translations.d.ts.map +1 -1
  123. package/build/translations.js +17 -0
  124. package/package.json +14 -8
  125. package/src/_emoji-name-map.d.ts +10 -0
  126. package/src/_github-username-regex.d.ts +4 -0
  127. package/src/api/gist.js +31 -31
  128. package/src/api/index.js +40 -42
  129. package/src/api/pin.js +20 -38
  130. package/src/api/top-langs.js +36 -49
  131. package/src/api/wakatime.js +31 -31
  132. package/src/{calculateRank.js → calculateRank.ts} +29 -19
  133. package/src/cards/common-options.ts +13 -0
  134. package/src/cards/{gist.js → gist.ts} +37 -37
  135. package/src/cards/{repo.js → repo.ts} +107 -79
  136. package/src/cards/{stats.js → stats.ts} +173 -210
  137. package/src/cards/{top-languages.js → top-languages.ts} +325 -243
  138. package/src/cards/{wakatime.js → wakatime.ts} +158 -127
  139. package/src/common/Card.ts +123 -43
  140. package/src/common/I18n.ts +6 -2
  141. package/src/common/color.ts +240 -28
  142. package/src/common/config.ts +22 -29
  143. package/src/common/constants.ts +3 -1
  144. package/src/common/date.ts +45 -0
  145. package/src/common/html.ts +1 -1
  146. package/src/common/http.ts +71 -0
  147. package/src/common/icons.ts +1 -0
  148. package/src/common/languageColors.json +10 -1
  149. package/src/common/languageColors.ts +19 -0
  150. package/src/common/ops.ts +158 -0
  151. package/src/common/render.ts +652 -0
  152. package/src/common/retryer.ts +21 -12
  153. package/src/fetchers/gist.ts +79 -0
  154. package/src/fetchers/repo.ts +114 -0
  155. package/src/fetchers/stats.ts +743 -0
  156. package/src/fetchers/top-languages.ts +135 -0
  157. package/src/fetchers/{types.d.ts → types.ts} +28 -20
  158. package/src/fetchers/{wakatime.js → wakatime.ts} +19 -5
  159. package/src/graphql/contributionsDocument.ts +44 -0
  160. package/src/graphql/generated/common.ts +26 -0
  161. package/src/graphql/generated/gist.ts +59 -0
  162. package/src/graphql/generated/repo.ts +90 -0
  163. package/src/graphql/generated/stats.ts +194 -0
  164. package/src/graphql/generated/top-languages.ts +75 -0
  165. package/src/graphql/graphqlDocument.ts +25 -0
  166. package/src/graphql/queries/gist.graphql +25 -0
  167. package/src/graphql/queries/repo.graphql +28 -0
  168. package/src/graphql/queries/stats.graphql +120 -0
  169. package/src/graphql/queries/top-languages.graphql +34 -0
  170. package/src/graphql/reposContributedToDocument.ts +86 -0
  171. package/src/index.ts +3 -1
  172. package/src/themes/index.ts +33 -0
  173. package/src/translations.ts +17 -0
  174. package/src/cards/types.d.ts +0 -78
  175. package/src/common/http.js +0 -19
  176. package/src/common/ops.js +0 -170
  177. package/src/common/render.js +0 -440
  178. package/src/fetchers/gist.js +0 -112
  179. package/src/fetchers/repo.js +0 -161
  180. package/src/fetchers/stats.js +0 -474
  181. package/src/fetchers/top-languages.js +0 -175
  182. package/src/themes/README.md +0 -229
@@ -1,11 +1,10 @@
1
1
  import { Card } from "../common/Card.js";
2
2
  import { I18n } from "../common/I18n.js";
3
- import { getCardColors } from "../common/color.js";
3
+ import { getLightDarkColors } from "../common/color.js";
4
4
  import { CustomError } from "../common/error.js";
5
- import { kFormatter } from "../common/fmt.js";
6
5
  import { icons, rankIcon } from "../common/icons.js";
7
6
  import { buildSearchFilter, clampValue } from "../common/ops.js";
8
- import { flexLayout, measureText } from "../common/render.js";
7
+ import { createTextNode, flexLayout, measureText } from "../common/render.js";
9
8
  import { statCardLocales, wakatimeCardLocales } from "../translations.js";
10
9
  const CARD_MIN_WIDTH = 287;
11
10
  const CARD_DEFAULT_WIDTH = 287;
@@ -13,11 +12,7 @@ const RANK_CARD_MIN_WIDTH = 420;
13
12
  const RANK_CARD_DEFAULT_WIDTH = 450;
14
13
  const RANK_ONLY_CARD_MIN_WIDTH = 290;
15
14
  const RANK_ONLY_CARD_DEFAULT_WIDTH = 290;
16
- /**
17
- * Long locales that need more space for text. Keep sorted alphabetically.
18
- *
19
- * @type {(keyof typeof wakatimeCardLocales["wakatimecard.title"])[]}
20
- */
15
+ /** Long locales that need more space for text. Keep sorted alphabetically. */
21
16
  const LONG_LOCALES = [
22
17
  "az",
23
18
  "bg",
@@ -46,63 +41,11 @@ const LONG_LOCALES = [
46
41
  "uz",
47
42
  "zh-tw",
48
43
  ];
49
- /**
50
- * Create a stats card text item.
51
- *
52
- * @param {object} params Object that contains the createTextNode parameters.
53
- * @param {string} params.icon The icon to display.
54
- * @param {string} params.label The label to display.
55
- * @param {number} params.value The value to display.
56
- * @param {string} params.id The id of the stat.
57
- * @param {string=} params.unitSymbol The unit symbol of the stat.
58
- * @param {number} params.index The index of the stat.
59
- * @param {boolean} params.showIcons Whether to show icons.
60
- * @param {number} params.shiftValuePos Number of pixels the value has to be shifted to the right.
61
- * @param {boolean} params.bold Whether to bold the label.
62
- * @param {string} params.numberFormat The format of numbers on card.
63
- * @param {number=} params.numberPrecision The precision of numbers on card.
64
- * @param {string} params.link Url to link to.
65
- * @param {number} params.labelXOffset horizontal offset for label.
66
- * @returns {string} The stats card text item SVG object.
67
- */
68
- const createTextNode = ({ icon, label, value, id, unitSymbol, index, showIcons, shiftValuePos, bold, numberFormat, numberPrecision, link, labelXOffset = 25, }) => {
69
- const precision = typeof numberPrecision === "number" && !isNaN(numberPrecision)
70
- ? clampValue(numberPrecision, 0, 2)
71
- : undefined;
72
- const kValue = numberFormat.toLowerCase() === "long" || id === "prs_merged_percentage"
73
- ? value
74
- : kFormatter(value, precision);
75
- const staggerDelay = (index + 3) * 150;
76
- const labelOffset = showIcons ? `x="${labelXOffset}"` : "";
77
- const iconSvg = showIcons
78
- ? `
79
- <svg data-testid="icon" class="icon" viewBox="0 0 16 16" version="1.1" width="16" height="16">
80
- ${icon}
81
- </svg>
82
- `
83
- : "";
84
- return (`
85
- <g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">` +
86
- (link ? `<a href="${link}">` : "") +
87
- `
88
- ${iconSvg}
89
- <text class="stat ${bold ? " bold" : "not_bold"}" ${labelOffset} y="12.5">${label}:</text>
90
- <text
91
- class="stat ${bold ? " bold" : "not_bold"}"
92
- x="${(showIcons ? 140 : 120) + (bold ? 5 : 0) + shiftValuePos}"
93
- y="12.5"
94
- data-testid="${id}"
95
- >${kValue}${unitSymbol ? ` ${unitSymbol}` : ""}</text>` +
96
- (link ? "</a>" : "") +
97
- `
98
- </g>
99
- `);
100
- };
101
44
  /**
102
45
  * Calculates progress along the boundary of the circle, i.e. its circumference.
103
46
  *
104
- * @param {number} value The rank value to calculate progress for.
105
- * @returns {number} Progress value.
47
+ * @param value The rank value to calculate progress for.
48
+ * @returns Progress value.
106
49
  */
107
50
  const calculateCircleProgress = (value) => {
108
51
  const radius = 40;
@@ -119,8 +62,9 @@ const calculateCircleProgress = (value) => {
119
62
  * Retrieves the animation to display progress along the circumference of circle
120
63
  * from the beginning to the given value in a clockwise direction.
121
64
  *
122
- * @param {{progress: number}} progress The progress value to animate to.
123
- * @returns {string} Progress animation css.
65
+ * @param props The props object.
66
+ * @param props.progress The progress value to animate to.
67
+ * @returns Progress animation css.
124
68
  */
125
69
  const getProgressAnimation = ({ progress }) => {
126
70
  return `
@@ -137,18 +81,15 @@ const getProgressAnimation = ({ progress }) => {
137
81
  /**
138
82
  * Retrieves CSS styles for a card.
139
83
  *
140
- * @param {Object} colors The colors to use for the card.
141
- * @param {string} colors.titleColor The title color.
142
- * @param {string} colors.textColor The text color.
143
- * @param {string} colors.iconColor The icon color.
144
- * @param {string} colors.ringColor The ring color.
145
- * @param {boolean} colors.show_icons Whether to show icons.
146
- * @param {number} colors.progress The progress value to animate to.
147
- * @returns {string} Card CSS styles.
84
+ * @param colors The colors to use for the card.
85
+ * @param colors.textColor The text color.
86
+ * @param colors.iconColor The icon color.
87
+ * @param colors.ringColor The ring color.
88
+ * @param colors.show_icons Whether to show icons.
89
+ * @param colors.progress The progress value to animate to.
90
+ * @returns Card CSS styles.
148
91
  */
149
- const getStyles = ({
150
- // eslint-disable-next-line no-unused-vars
151
- titleColor, textColor, iconColor, ringColor, show_icons, progress, }) => {
92
+ const getStyles = ({ textColor, iconColor, ringColor, show_icons, progress, }) => {
152
93
  return `
153
94
  .stat {
154
95
  font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${textColor};
@@ -202,41 +143,32 @@ titleColor, textColor, iconColor, ringColor, show_icons, progress, }) => {
202
143
  /**
203
144
  * Return the label for commits according to the selected options
204
145
  *
205
- * @param {boolean} include_all_commits Option to include all years
206
- * @param {number|undefined} commits_year Option to include only selected year
207
- * @param {I18n} i18n The I18n instance.
208
- * @returns {string} The label corresponding to the options.
146
+ * @param include_all_commits Option to include all years
147
+ * @param commits_year Option to include only selected year
148
+ * @param i18n The I18n instance.
149
+ * @returns The label corresponding to the options.
209
150
  */
210
151
  const getTotalCommitsYearLabel = (include_all_commits, commits_year, i18n) => include_all_commits
211
152
  ? ""
212
153
  : commits_year
213
154
  ? ` (${commits_year})`
214
155
  : ` (${i18n.t("wakatimecard.lastyear")})`;
215
- /**
216
- * @typedef {import('../fetchers/types').StatsData} StatsData
217
- * @typedef {import('./types').StatCardOptions} StatCardOptions
218
- */
219
156
  /**
220
157
  * Renders the stats card.
221
158
  *
222
- * @param {StatsData} stats The stats data.
223
- * @param {Partial<StatCardOptions>} options The card options.
224
- * @returns {string} The stats card SVG object.
159
+ * @param stats The stats data.
160
+ * @param options The card options.
161
+ * @param username GitHub username, used to build stat search links.
162
+ * @param repo Repositories to scope the search links to.
163
+ * @param owner Owners to scope the search links to.
164
+ * @returns The stats card SVG object.
225
165
  */
226
166
  const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) => {
227
- const { name, totalStars, totalCommits, totalIssues, totalPRs, totalPRsMerged, mergedPRsPercentage, totalReviews, totalDiscussionsStarted, totalDiscussionsAnswered, contributedTo, totalPRsAuthored, totalPRsCommented, totalPRsReviewed, totalIssuesAuthored, totalIssuesCommented, rank, } = stats;
228
- const { hide = [], show_icons = false, hide_title = false, hide_border = false, card_width, hide_rank = false, include_all_commits = false, commits_year, line_height = 25, title_color, ring_color, icon_color, text_color, text_bold = true, bg_color, theme = "default", custom_title, border_radius, border_color, number_format = "short", number_precision, locale, disable_animations = false, rank_icon = "default", show = [], } = options;
167
+ const { name, totalStars, totalCommits, totalIssues, totalPRs, totalPRsMerged, mergedPRsPercentage, totalReviews, totalDiscussionsStarted, totalDiscussionsAnswered, contributedTo, allTimeContributedTo, totalPRsAuthored, totalPRsCommented, totalPRsReviewed, totalIssuesAuthored, totalIssuesCommented, totalContributions, rank, } = stats;
168
+ const { hide = [], show_icons = false, hide_title = false, hide_border = false, card_width, hide_rank = false, include_all_commits = false, commits_year, line_height = 25, text_bold = true, custom_title, border_radius, number_format = "short", number_precision, locale, disable_animations = false, rank_icon = "default", show = [], } = options;
229
169
  const lheight = parseInt(String(line_height), 10);
230
- // returns theme based colors with proper overrides and defaults
231
- const { titleColor, iconColor, textColor, bgColor, borderColor, ringColor } = getCardColors({
232
- title_color,
233
- text_color,
234
- icon_color,
235
- bg_color,
236
- border_color,
237
- ring_color,
238
- theme,
239
- });
170
+ const { lightColors, darkColors } = getLightDarkColors(options);
171
+ const { iconColor, textColor, ringColor } = lightColors;
240
172
  const apostrophe = /s$/i.test(name.trim()) ? "" : "s";
241
173
  const i18n = new I18n({
242
174
  locale,
@@ -247,26 +179,34 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
247
179
  });
248
180
  // Meta data for creating text nodes with createTextNode function
249
181
  const STATS = {};
250
- STATS.stars = {
182
+ STATS["stars"] = {
251
183
  icon: icons.star,
252
184
  label: i18n.t("statcard.totalstars"),
253
185
  value: totalStars,
254
186
  id: "stars",
255
187
  };
256
- STATS.commits = {
188
+ if (show.includes("contributions")) {
189
+ STATS["contributions"] = {
190
+ icon: icons.contributions,
191
+ label: i18n.t("statcard.contributions"),
192
+ value: totalContributions,
193
+ id: "contributions",
194
+ };
195
+ }
196
+ STATS["commits"] = {
257
197
  icon: icons.commits,
258
198
  label: `${i18n.t("statcard.commits")}${getTotalCommitsYearLabel(include_all_commits, commits_year, i18n)}`,
259
199
  value: totalCommits,
260
200
  id: "commits",
261
201
  };
262
- STATS.prs = {
202
+ STATS["prs"] = {
263
203
  icon: icons.prs,
264
204
  label: i18n.t("statcard.prs"),
265
205
  value: totalPRs,
266
206
  id: "prs",
267
207
  };
268
208
  if (show.includes("prs_merged")) {
269
- STATS.prs_merged = {
209
+ STATS["prs_merged"] = {
270
210
  icon: icons.prs_merged,
271
211
  label: i18n.t("statcard.prs-merged"),
272
212
  value: totalPRsMerged,
@@ -274,10 +214,10 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
274
214
  };
275
215
  }
276
216
  if (show.includes("prs_merged_percentage")) {
277
- STATS.prs_merged_percentage = {
217
+ STATS["prs_merged_percentage"] = {
278
218
  icon: icons.prs_merged_percentage,
279
219
  label: i18n.t("statcard.prs-merged-percentage"),
280
- value: mergedPRsPercentage.toFixed(typeof number_precision === "number" && !isNaN(number_precision)
220
+ value: mergedPRsPercentage.toFixed(number_precision !== undefined && Number.isFinite(number_precision)
281
221
  ? clampValue(number_precision, 0, 2)
282
222
  : 2),
283
223
  id: "prs_merged_percentage",
@@ -285,21 +225,21 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
285
225
  };
286
226
  }
287
227
  if (show.includes("reviews")) {
288
- STATS.reviews = {
228
+ STATS["reviews"] = {
289
229
  icon: icons.reviews,
290
230
  label: i18n.t("statcard.reviews"),
291
231
  value: totalReviews,
292
232
  id: "reviews",
293
233
  };
294
234
  }
295
- STATS.issues = {
235
+ STATS["issues"] = {
296
236
  icon: icons.issues,
297
237
  label: i18n.t("statcard.issues"),
298
238
  value: totalIssues,
299
239
  id: "issues",
300
240
  };
301
241
  if (show.includes("discussions_started")) {
302
- STATS.discussions_started = {
242
+ STATS["discussions_started"] = {
303
243
  icon: icons.discussions_started,
304
244
  label: i18n.t("statcard.discussions-started"),
305
245
  value: totalDiscussionsStarted,
@@ -307,109 +247,105 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
307
247
  };
308
248
  }
309
249
  if (show.includes("discussions_answered")) {
310
- STATS.discussions_answered = {
250
+ STATS["discussions_answered"] = {
311
251
  icon: icons.discussions_answered,
312
252
  label: i18n.t("statcard.discussions-answered"),
313
253
  value: totalDiscussionsAnswered,
314
254
  id: "discussions_answered",
315
255
  };
316
256
  }
317
- let repoFilter = encodeURIComponent(buildSearchFilter(repo, owner));
257
+ const repoFilter = encodeURIComponent(buildSearchFilter(repo, owner));
258
+ const encodedUsername = encodeURIComponent(username ?? "");
318
259
  if (show.includes("prs_authored")) {
319
- STATS.prs_authored = {
260
+ STATS["prs_authored"] = {
320
261
  icon: icons.prs,
321
262
  label: i18n.t("statcard.prs-authored"),
322
263
  value: totalPRsAuthored,
323
264
  id: "prs_authored",
324
- link: `https://github.com/search?q=${repoFilter}author%3A${username}&amp;type=pullrequests`,
265
+ link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&amp;type=pullrequests`,
325
266
  };
326
267
  }
327
268
  if (show.includes("prs_commented")) {
328
- STATS.prs_commented = {
269
+ STATS["prs_commented"] = {
329
270
  icon: icons.comments,
330
271
  label: i18n.t("statcard.prs-commented"),
331
272
  value: totalPRsCommented,
332
273
  id: "prs_commented",
333
- link: `https://github.com/search?q=${repoFilter}commenter%3A${username}+-author%3A${username}&amp;type=pullrequests`,
274
+ link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=pullrequests`,
334
275
  };
335
276
  }
336
277
  if (show.includes("prs_reviewed")) {
337
- STATS.prs_reviewed = {
278
+ STATS["prs_reviewed"] = {
338
279
  icon: icons.reviews,
339
280
  label: i18n.t("statcard.prs-reviewed"),
340
281
  value: totalPRsReviewed,
341
282
  id: "prs_reviewed",
342
- link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${username}+-author%3A${username}&amp;type=pullrequests`,
283
+ link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=pullrequests`,
343
284
  };
344
285
  }
345
286
  if (show.includes("issues_authored")) {
346
- STATS.issues_authored = {
287
+ STATS["issues_authored"] = {
347
288
  icon: icons.issues,
348
289
  label: i18n.t("statcard.issues-authored"),
349
290
  value: totalIssuesAuthored,
350
291
  id: "issues_authored",
351
- link: `https://github.com/search?q=${repoFilter}author%3A${username}&amp;type=issues`,
292
+ link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&amp;type=issues`,
352
293
  };
353
294
  }
354
295
  if (show.includes("issues_commented")) {
355
- STATS.issues_commented = {
296
+ STATS["issues_commented"] = {
356
297
  icon: icons.discussions_started,
357
298
  label: i18n.t("statcard.issues-commented"),
358
299
  value: totalIssuesCommented,
359
300
  id: "issues_commented",
360
- link: `https://github.com/search?q=${repoFilter}commenter%3A${username}+-author%3A${username}&amp;type=issues`,
301
+ link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=issues`,
361
302
  };
362
303
  }
363
- STATS.contribs = {
304
+ STATS["contribs"] = {
364
305
  icon: icons.contribs,
365
306
  label: i18n.t("statcard.contribs"),
366
307
  value: contributedTo,
367
308
  id: "contribs",
368
309
  };
369
- // @ts-ignore
310
+ if (show.includes("all_time_contribs")) {
311
+ STATS["all_time_contribs"] = {
312
+ icon: icons.contribs,
313
+ label: i18n.t("statcard.all-time-contribs"),
314
+ value: allTimeContributedTo,
315
+ id: "all_time_contribs",
316
+ };
317
+ }
370
318
  const isLongLocale = locale ? LONG_LOCALES.includes(locale) : false;
371
319
  // check if all used labels are short
372
- const longLabels = Object.keys(STATS)
373
- .filter((key) => !hide.includes(key))
374
- .filter((key) => STATS[key].label.length > 18).length > 0;
320
+ const longLabels = Object.entries(STATS)
321
+ .filter(([key]) => !hide.includes(key))
322
+ .some(([, stat]) => stat.label.length > 18);
375
323
  // filter out hidden stats defined by user & create the text nodes
376
- const statItems = Object.keys(STATS)
377
- .filter((key) => !hide.includes(key))
378
- .map((key, index) => {
379
- // @ts-ignore
380
- const stats = STATS[key];
381
- // create the text nodes, and pass index so that we can calculate the line spacing
382
- return createTextNode({
383
- icon: stats.icon,
384
- label: stats.label,
385
- value: stats.value,
386
- id: stats.id,
387
- unitSymbol: stats.unitSymbol,
388
- index,
389
- showIcons: show_icons,
390
- shiftValuePos: 29.01 + (longLabels ? 50 : 0) + (isLongLocale ? 50 : 0),
391
- bold: text_bold,
392
- numberFormat: number_format,
393
- numberPrecision: number_precision,
394
- link: STATS[key].link,
395
- });
396
- });
324
+ const statItems = Object.entries(STATS)
325
+ .filter(([key]) => !hide.includes(key))
326
+ // pass index so that we can calculate the line spacing
327
+ .map(([, stat], index) => createTextNode({
328
+ icon: stat.icon,
329
+ label: stat.label,
330
+ value: stat.value,
331
+ id: stat.id,
332
+ unitSymbol: stat.unitSymbol,
333
+ index,
334
+ showIcons: show_icons,
335
+ shiftValuePos: 29.01 + (longLabels ? 50 : 0) + (isLongLocale ? 50 : 0),
336
+ bold: text_bold,
337
+ numberFormat: number_format,
338
+ numberPrecision: number_precision,
339
+ link: stat.link,
340
+ }));
397
341
  if (statItems.length === 0 && hide_rank) {
398
342
  throw new CustomError("Could not render stats card.", "Either stats or rank are required.");
399
343
  }
400
344
  // Calculate the card height depending on how many items there are
401
345
  // but if rank circle is visible clamp the minimum height to `150`
402
- let height = Math.max(45 + (statItems.length + 1) * lheight, hide_rank ? 0 : statItems.length ? 150 : 180);
346
+ const height = Math.max(45 + (statItems.length + 1) * lheight, hide_rank ? 0 : statItems.length ? 150 : 180);
403
347
  // the lower the user's percentile the better
404
348
  const progress = 100 - rank.percentile;
405
- const cssStyles = getStyles({
406
- titleColor,
407
- ringColor,
408
- textColor,
409
- iconColor,
410
- show_icons,
411
- progress,
412
- });
413
349
  const calculateTextWidth = () => {
414
350
  return measureText(custom_title
415
351
  ? custom_title
@@ -433,7 +369,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
433
369
  : statItems.length
434
370
  ? RANK_CARD_DEFAULT_WIDTH
435
371
  : RANK_ONLY_CARD_DEFAULT_WIDTH) + iconWidth;
436
- let width = card_width
372
+ const width = card_width
437
373
  ? isNaN(card_width)
438
374
  ? Math.max(defaultCardWidth, minCardWidth)
439
375
  : card_width
@@ -446,17 +382,28 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
446
382
  width,
447
383
  height,
448
384
  border_radius,
449
- colors: {
450
- titleColor,
451
- textColor,
452
- iconColor,
453
- bgColor,
454
- borderColor,
455
- },
385
+ colors: { light: lightColors, dark: darkColors },
456
386
  });
457
387
  card.setHideBorder(hide_border);
458
388
  card.setHideTitle(hide_title);
459
- card.setCSS(cssStyles);
389
+ card.setCSS({
390
+ light: getStyles({
391
+ ringColor,
392
+ textColor,
393
+ iconColor,
394
+ show_icons,
395
+ progress,
396
+ }),
397
+ dark: darkColors
398
+ ? getStyles({
399
+ ringColor: darkColors.ringColor,
400
+ textColor: darkColors.textColor,
401
+ iconColor: darkColors.iconColor,
402
+ show_icons,
403
+ progress,
404
+ })
405
+ : null,
406
+ });
460
407
  if (disable_animations) {
461
408
  card.disableAnimations();
462
409
  }
@@ -468,7 +415,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
468
415
  * width < RANK_CARD_DEFAULT_WIDTH: The left and right padding will be enlarged
469
416
  * equally from a certain minimum at RANK_CARD_MIN_WIDTH.
470
417
  *
471
- * @returns {number} - Rank circle translation value.
418
+ * @returns Rank circle translation value.
472
419
  */
473
420
  const calculateRankXTranslation = () => {
474
421
  if (statItems.length) {
@@ -493,19 +440,17 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
493
440
  <circle class="rank-circle-rim" cx="-10" cy="8" r="40" />
494
441
  <circle class="rank-circle" cx="-10" cy="8" r="40" />
495
442
  <g class="rank-text">
496
- ${rankIcon(rank_icon, rank?.level, rank?.percentile)}
443
+ ${rankIcon(rank_icon, rank.level, rank.percentile)}
497
444
  </g>
498
445
  </g>`;
499
446
  // Accessibility Labels
500
- const labels = Object.keys(STATS)
501
- .filter((key) => !hide.includes(key))
502
- .map((key) => {
503
- // @ts-ignore
504
- const stats = STATS[key];
447
+ const labels = Object.entries(STATS)
448
+ .filter(([key]) => !hide.includes(key))
449
+ .map(([key, stat]) => {
505
450
  if (key === "commits") {
506
- return `${i18n.t("statcard.commits")} ${getTotalCommitsYearLabel(include_all_commits, commits_year, i18n)} : ${stats.value}`;
451
+ return `${i18n.t("statcard.commits")} ${getTotalCommitsYearLabel(include_all_commits, commits_year, i18n)} : ${stat.value}`;
507
452
  }
508
- return `${stats.label}: ${stats.value}`;
453
+ return `${stat.label}: ${stat.value}`;
509
454
  })
510
455
  .join(", ");
511
456
  card.setAccessibilityLabel({
@@ -523,4 +468,4 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
523
468
  </svg>
524
469
  `);
525
470
  };
526
- export { renderStatsCard, createTextNode };
471
+ export { renderStatsCard };