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