@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,15 @@
1
1
  import { Card } from "../common/Card.js";
2
2
  import { I18n } from "../common/I18n.js";
3
- import { getCardColors } from "../common/color.js";
4
- import languageColors from "../common/languageColors.json" with { type: "json" };
3
+ import { getLightDarkColors, isPrefixedHexColor } from "../common/color.js";
4
+ import { encodeHTML } from "../common/html.js";
5
+ import { getLanguageColor } from "../common/languageColors.js";
5
6
  import { clampValue, lowercaseTrim } from "../common/ops.js";
6
7
  import { createProgressNode, flexLayout } from "../common/render.js";
8
+ import type { WakaTimeData, WakaTimeLang } from "../fetchers/types.js";
7
9
  import { wakatimeCardLocales } from "../translations.js";
8
10
 
11
+ import type { CommonOptions } from "./common-options.js";
12
+
9
13
  const DEFAULT_CARD_WIDTH = 495;
10
14
  const MIN_CARD_WIDTH = 250;
11
15
  const COMPACT_LAYOUT_MIN_WIDTH = 400;
@@ -15,58 +19,91 @@ const HIDDEN_PROGRESSBAR_PADDING = 170;
15
19
  const COMPACT_LAYOUT_PROGRESSBAR_PADDING = 25;
16
20
  const TOTAL_TEXT_WIDTH = 275;
17
21
 
22
+ type WakaTimeLayout = "compact" | "normal";
23
+ type DisplayFormat = "time" | "percent";
24
+
25
+ interface WakaTimeOptions extends CommonOptions {
26
+ hide_title: boolean;
27
+ hide: Array<string>;
28
+ card_width: number;
29
+ line_height: number | string;
30
+ hide_progress: boolean;
31
+ custom_title: string;
32
+ layout: WakaTimeLayout;
33
+ langs_count: number;
34
+ display_format: DisplayFormat;
35
+ disable_animations: boolean;
36
+ }
37
+
18
38
  /**
19
39
  * Creates the no coding activity SVG node.
20
40
  *
21
- * @param {object} props The function properties.
22
- * @param {string} props.color No coding activity text color.
23
- * @param {string} props.text No coding activity translated text.
24
- * @returns {string} No coding activity SVG node string.
41
+ * @param props The function properties.
42
+ * @param props.text No coding activity translated text.
43
+ * @returns No coding activity SVG node string.
25
44
  */
26
- const noCodingActivityNode = ({ color, text }) => {
45
+ const noCodingActivityNode = ({ text }: { text: string }): string => {
27
46
  return `
28
- <text x="25" y="11" class="stat bold" fill="${color}">${text}</text>
47
+ <text x="25" y="11" class="stat bold">${encodeHTML(text)}</text>
29
48
  `;
30
49
  };
31
50
 
32
- /**
33
- * @typedef {import('../fetchers/types').WakaTimeLang} WakaTimeLang
34
- */
35
-
36
51
  /**
37
52
  * Format language value.
38
53
  *
39
- * @param {Object} args The function arguments.
40
- * @param {WakaTimeLang} args.lang The language object.
41
- * @param {"time" | "percent"} args.display_format The display format of the language node.
42
- * @returns {string} The formatted language value.
54
+ * @param args The function arguments.
55
+ * @param args.lang The language object.
56
+ * @param args.display_format The display format of the language node.
57
+ * @returns The formatted language value.
43
58
  */
44
- const formatLanguageValue = ({ display_format, lang }) => {
59
+ const formatLanguageValue = ({
60
+ display_format,
61
+ lang,
62
+ }: {
63
+ display_format: DisplayFormat;
64
+ lang: WakaTimeLang;
65
+ }): string => {
45
66
  return display_format === "percent"
46
- ? `${lang.percent.toFixed(2).toString()} %`
67
+ ? `${lang.percent.toFixed(2)} %`
47
68
  : lang.text;
48
69
  };
49
70
 
50
71
  /**
51
72
  * Create compact WakaTime layout.
52
73
  *
53
- * @param {Object} args The function arguments.
54
- * @param {WakaTimeLang} args.lang The languages array.
55
- * @param {number} args.x The x position of the language node.
56
- * @param {number} args.y The y position of the language node.
57
- * @param {"time" | "percent"} args.display_format The display format of the language node.
58
- * @returns {string} The compact layout language SVG node.
74
+ * @param args The function arguments.
75
+ * @param args.lang The languages array.
76
+ * @param args.x The x position of the language node.
77
+ * @param args.y The y position of the language node.
78
+ * @param args.display_format The display format of the language node.
79
+ * @returns The compact layout language SVG node.
59
80
  */
60
- const createCompactLangNode = ({ lang, x, y, display_format }) => {
61
- // @ts-ignore
62
- const color = languageColors[lang.name] || "#858585";
81
+ const createCompactLangNode = ({
82
+ lang,
83
+ x,
84
+ y,
85
+ display_format,
86
+ }: {
87
+ lang: WakaTimeLang;
88
+ x: number;
89
+ y: number;
90
+ display_format: DisplayFormat;
91
+ }): string => {
92
+ if (!Number.isFinite(x)) {
93
+ throw new Error(`Invalid x: "${x}"`);
94
+ }
95
+ if (!Number.isFinite(y)) {
96
+ throw new Error(`Invalid y: "${y}"`);
97
+ }
98
+
99
+ const color = getLanguageColor(lang.name);
63
100
  const value = formatLanguageValue({ display_format, lang });
64
101
 
65
102
  return `
66
103
  <g transform="translate(${x}, ${y})">
67
104
  <circle cx="5" cy="6" r="5" fill="${color}" />
68
105
  <text data-testid="lang-name" x="15" y="10" class='lang-name'>
69
- ${lang.name} - ${value}
106
+ ${encodeHTML(lang.name)} - ${encodeHTML(value)}
70
107
  </text>
71
108
  </g>
72
109
  `;
@@ -75,14 +112,24 @@ const createCompactLangNode = ({ lang, x, y, display_format }) => {
75
112
  /**
76
113
  * Create WakaTime language text node item.
77
114
  *
78
- * @param {Object} args The function arguments.
79
- * @param {WakaTimeLang[]} args.langs The language objects.
80
- * @param {number} args.y The y position of the language node.
81
- * @param {"time" | "percent"} args.display_format The display format of the language node.
82
- * @param {number} args.card_width Width in px of the card.
83
- * @returns {string[]} The language text node items.
115
+ * @param args The function arguments.
116
+ * @param args.langs The language objects.
117
+ * @param args.y The y position of the language node.
118
+ * @param args.display_format The display format of the language node.
119
+ * @param args.card_width Width in px of the card.
120
+ * @returns The language text node items.
84
121
  */
85
- const createLanguageTextNode = ({ langs, y, display_format, card_width }) => {
122
+ const createLanguageTextNode = ({
123
+ langs,
124
+ y,
125
+ display_format,
126
+ card_width,
127
+ }: {
128
+ langs: Array<WakaTimeLang>;
129
+ y: number;
130
+ display_format: DisplayFormat;
131
+ card_width: number;
132
+ }): Array<string> => {
86
133
  const LEFT_X = 25;
87
134
  const RIGHT_X_BASE = 230;
88
135
  const rightOffset = (card_width - DEFAULT_CARD_WIDTH) / 2;
@@ -102,17 +149,15 @@ const createLanguageTextNode = ({ langs, y, display_format, card_width }) => {
102
149
  /**
103
150
  * Create WakaTime text item.
104
151
  *
105
- * @param {Object} args The function arguments.
106
- * @param {string} args.id The id of the text node item.
107
- * @param {string} args.label The label of the text node item.
108
- * @param {string} args.value The value of the text node item.
109
- * @param {number} args.index The index of the text node item.
110
- * @param {number} args.percent Percentage of the text node item.
111
- * @param {boolean=} args.hideProgress Whether to hide the progress bar.
112
- * @param {string} args.progressBarColor The color of the progress bar.
113
- * @param {string} args.progressBarBackgroundColor The color of the progress bar background.
114
- * @param {number} args.progressBarWidth The width of the progress bar.
115
- * @returns {string} The text SVG node.
152
+ * @param args The function arguments.
153
+ * @param args.id The id of the text node item.
154
+ * @param args.label The label of the text node item.
155
+ * @param args.value The value of the text node item.
156
+ * @param args.index The index of the text node item.
157
+ * @param args.percent Percentage of the text node item.
158
+ * @param args.hideProgress Whether to hide the progress bar.
159
+ * @param args.progressBarWidth The width of the progress bar.
160
+ * @returns The text SVG node.
116
161
  */
117
162
  const createTextNode = ({
118
163
  id,
@@ -121,10 +166,23 @@ const createTextNode = ({
121
166
  index,
122
167
  percent,
123
168
  hideProgress,
124
- progressBarColor,
125
- progressBarBackgroundColor,
126
169
  progressBarWidth,
127
- }) => {
170
+ }: {
171
+ id: string;
172
+ label: string;
173
+ value: string;
174
+ index: number;
175
+ percent: number;
176
+ hideProgress?: boolean | undefined;
177
+ progressBarWidth: number;
178
+ }): string => {
179
+ if (!Number.isFinite(index)) {
180
+ throw new Error(`Invalid index: "${index}"`);
181
+ }
182
+ if (!Number.isFinite(progressBarWidth)) {
183
+ throw new Error(`Invalid progressBarWidth: "${progressBarWidth}"`);
184
+ }
185
+
128
186
  const staggerDelay = (index + 3) * 150;
129
187
  const cardProgress = hideProgress
130
188
  ? null
@@ -132,23 +190,19 @@ const createTextNode = ({
132
190
  x: 110,
133
191
  y: 4,
134
192
  progress: percent,
135
- color: progressBarColor,
136
193
  width: progressBarWidth,
137
- // @ts-ignore
138
- name: label,
139
- progressBarBackgroundColor,
140
194
  delay: staggerDelay + 300,
141
195
  });
142
196
 
143
197
  return `
144
198
  <g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">
145
- <text class="stat bold" y="12.5" data-testid="${id}">${label}:</text>
199
+ <text class="stat bold" y="12.5" data-testid="${encodeHTML(id)}">${encodeHTML(label)}:</text>
146
200
  <text
147
201
  class="stat"
148
202
  x="${hideProgress ? HIDDEN_PROGRESSBAR_PADDING : PROGRESSBAR_PADDING + progressBarWidth}"
149
203
  y="12.5"
150
- >${value}</text>
151
- ${cardProgress}
204
+ >${encodeHTML(value)}</text>
205
+ ${String(cardProgress)}
152
206
  </g>
153
207
  `;
154
208
  };
@@ -157,10 +211,9 @@ const createTextNode = ({
157
211
  * Recalculating percentages so that, compact layout's progress bar does not break when
158
212
  * hiding languages.
159
213
  *
160
- * @param {WakaTimeLang[]} languages The languages array.
161
- * @returns {void} The recalculated languages array.
214
+ * @param languages The languages array.
162
215
  */
163
- const recalculatePercentages = (languages) => {
216
+ const recalculatePercentages = (languages: Array<WakaTimeLang>): void => {
164
217
  const totalSum = languages.reduce(
165
218
  (totalSum, language) => totalSum + language.percent,
166
219
  0,
@@ -174,16 +227,15 @@ const recalculatePercentages = (languages) => {
174
227
  /**
175
228
  * Retrieves CSS styles for a card.
176
229
  *
177
- * @param {Object} colors The colors to use for the card.
178
- * @param {string} colors.titleColor The title color.
179
- * @param {string} colors.textColor The text color.
180
- * @returns {string} Card CSS styles.
230
+ * @param colors The colors to use for the card.
231
+ * @param colors.textColor The text color.
232
+ * @returns Card CSS styles.
181
233
  */
182
- const getStyles = ({
183
- // eslint-disable-next-line no-unused-vars
184
- titleColor,
185
- textColor,
186
- }) => {
234
+ const getStyles = ({ textColor }: { textColor: string }): string => {
235
+ if (!isPrefixedHexColor(textColor)) {
236
+ throw new Error(`Invalid text color: "${textColor}"`);
237
+ }
238
+
187
239
  return `
188
240
  .stat {
189
241
  font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${textColor};
@@ -204,13 +256,19 @@ const getStyles = ({
204
256
  /**
205
257
  * Normalize incoming width (string or number) and clamp to minimum.
206
258
  *
207
- * @param {Object} args The function arguments.
208
- * @param {WakaTimeOptions["layout"] | undefined} args.layout The incoming layout value.
209
- * @param {number|undefined} args.value The incoming width value.
210
- * @returns {number} The normalized width value.
259
+ * @param args The function arguments.
260
+ * @param args.layout The incoming layout value.
261
+ * @param args.value The incoming width value.
262
+ * @returns The normalized width value.
211
263
  */
212
- const normalizeCardWidth = ({ value, layout }) => {
213
- if (value === undefined || value === null || isNaN(value)) {
264
+ const normalizeCardWidth = ({
265
+ value,
266
+ layout,
267
+ }: {
268
+ value?: number | undefined;
269
+ layout?: WakaTimeLayout | undefined;
270
+ }): number => {
271
+ if (value === undefined || isNaN(value)) {
214
272
  return DEFAULT_CARD_WIDTH;
215
273
  }
216
274
  return Math.max(
@@ -219,19 +277,17 @@ const normalizeCardWidth = ({ value, layout }) => {
219
277
  );
220
278
  };
221
279
 
222
- /**
223
- * @typedef {import('../fetchers/types').WakaTimeData} WakaTimeData
224
- * @typedef {import('./types').WakaTimeOptions} WakaTimeOptions
225
- */
226
-
227
280
  /**
228
281
  * Renders WakaTime card.
229
282
  *
230
- * @param {Partial<WakaTimeData>} stats WakaTime stats.
231
- * @param {Partial<WakaTimeOptions>} options Card options.
232
- * @returns {string} WakaTime card SVG.
283
+ * @param stats WakaTime stats.
284
+ * @param options Card options.
285
+ * @returns WakaTime card SVG.
233
286
  */
234
- const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
287
+ const renderWakatimeCard = (
288
+ stats: Partial<WakaTimeData> = {},
289
+ options: Partial<WakaTimeOptions> = { hide: [] },
290
+ ): string => {
235
291
  let { languages = [] } = stats;
236
292
  const {
237
293
  hide_title = false,
@@ -239,18 +295,12 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
239
295
  card_width,
240
296
  hide,
241
297
  line_height = DEFAULT_LINE_HEIGHT,
242
- title_color,
243
- icon_color,
244
- text_color,
245
- bg_color,
246
- theme = "default",
247
298
  hide_progress,
248
299
  custom_title,
249
300
  locale,
250
301
  layout,
251
302
  langs_count = languages.length,
252
303
  border_radius,
253
- border_color,
254
304
  display_format = "time",
255
305
  disable_animations,
256
306
  } = options;
@@ -279,16 +329,8 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
279
329
 
280
330
  const langsCount = clampValue(langs_count, 1, langs_count);
281
331
 
282
- // returns theme based colors with proper overrides and defaults
283
- const { titleColor, textColor, iconColor, bgColor, borderColor } =
284
- getCardColors({
285
- title_color,
286
- icon_color,
287
- text_color,
288
- bg_color,
289
- border_color,
290
- theme,
291
- });
332
+ const { lightColors, darkColors } = getLightDarkColors(options);
333
+ const { titleColor, textColor } = lightColors;
292
334
 
293
335
  const filteredLanguages = languages
294
336
  .filter((language) => language.hours || language.minutes)
@@ -298,12 +340,7 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
298
340
  // but if rank circle is visible clamp the minimum height to `150`
299
341
  let height = Math.max(45 + (filteredLanguages.length + 1) * lheight, 150);
300
342
 
301
- const cssStyles = getStyles({
302
- titleColor,
303
- textColor,
304
- });
305
-
306
- let finalLayout;
343
+ let finalLayout: string;
307
344
 
308
345
  // RENDER COMPACT LAYOUT
309
346
  if (layout === "compact") {
@@ -320,8 +357,7 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
320
357
  ((width - COMPACT_LAYOUT_PROGRESSBAR_PADDING) * language.percent) /
321
358
  100;
322
359
 
323
- // @ts-ignore
324
- const languageColor = languageColors[language.name] || "#858585";
360
+ const languageColor = getLanguageColor(language.name);
325
361
 
326
362
  const output = `
327
363
  <rect
@@ -353,8 +389,6 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
353
389
  card_width: normalizedWidth,
354
390
  }).join("")
355
391
  : noCodingActivityNode({
356
- // @ts-ignore
357
- color: textColor,
358
392
  text: stats.is_coding_activity_visible
359
393
  ? stats.is_other_usage_visible
360
394
  ? i18n.t("wakatimecard.nocodingactivity")
@@ -373,19 +407,12 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
373
407
  value: formatLanguageValue({ display_format, lang: language }),
374
408
  index,
375
409
  percent: language.percent,
376
- // @ts-ignore
377
- progressBarColor: titleColor,
378
- // @ts-ignore
379
- progressBarBackgroundColor:
380
- textColor === titleColor ? bgColor : textColor,
381
410
  hideProgress: hide_progress,
382
411
  progressBarWidth: normalizedWidth - TOTAL_TEXT_WIDTH,
383
412
  });
384
413
  })
385
414
  : [
386
415
  noCodingActivityNode({
387
- // @ts-ignore
388
- color: textColor,
389
416
  text: stats.is_coding_activity_visible
390
417
  ? stats.is_other_usage_visible
391
418
  ? i18n.t("wakatimecard.nocodingactivity")
@@ -415,13 +442,7 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
415
442
  width: normalizedWidth,
416
443
  height,
417
444
  border_radius,
418
- colors: {
419
- titleColor,
420
- textColor,
421
- iconColor,
422
- bgColor,
423
- borderColor,
424
- },
445
+ colors: { light: lightColors, dark: darkColors },
425
446
  });
426
447
 
427
448
  if (disable_animations) {
@@ -430,9 +451,9 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
430
451
 
431
452
  card.setHideBorder(hide_border);
432
453
  card.setHideTitle(hide_title);
433
- card.setCSS(
434
- `
435
- ${cssStyles}
454
+ card.setCSS({
455
+ light: `
456
+ ${getStyles({ textColor })}
436
457
  @keyframes slideInAnimation {
437
458
  from {
438
459
  width: 0;
@@ -455,9 +476,19 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
455
476
  }
456
477
  .lang-progress{
457
478
  animation: growWidthAnimation 0.6s ease-in-out forwards;
479
+ fill: ${titleColor};
458
480
  }
481
+ .progress-background { fill: ${textColor === titleColor ? "#fff0" /* transparent */ : textColor}; }
459
482
  `,
460
- );
483
+ dark: darkColors
484
+ ? `
485
+ ${getStyles({ textColor: darkColors.textColor })}
486
+ .lang-name { fill: ${darkColors.textColor} }
487
+ .lang-progress { fill: ${darkColors.titleColor}; }
488
+ .progress-background { fill: ${darkColors.textColor === darkColors.titleColor ? "#fff0" /* transparent */ : darkColors.textColor}; }
489
+ `
490
+ : null,
491
+ });
461
492
 
462
493
  return card.render(`
463
494
  <svg x="0" y="0" width="100%">