@stats-forge/github-stats-forge-core 0.0.2 → 0.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 (249) hide show
  1. package/README.md +0 -10
  2. package/build/api/api-result.d.ts +6 -7
  3. package/build/api/api-result.d.ts.map +1 -1
  4. package/build/api/api-result.js +4 -5
  5. package/build/api/contributed-to.d.ts +23 -0
  6. package/build/api/contributed-to.d.ts.map +1 -0
  7. package/build/api/contributed-to.js +43 -0
  8. package/build/api/gist.d.ts +8 -22
  9. package/build/api/gist.d.ts.map +1 -1
  10. package/build/api/gist.js +14 -36
  11. package/build/api/handler.d.ts +16 -0
  12. package/build/api/handler.d.ts.map +1 -0
  13. package/build/api/handler.js +29 -0
  14. package/build/api/index.d.ts +13 -12
  15. package/build/api/index.d.ts.map +1 -1
  16. package/build/api/index.js +1 -0
  17. package/build/api/params.d.ts +21 -12
  18. package/build/api/params.d.ts.map +1 -1
  19. package/build/api/params.js +41 -19
  20. package/build/api/pin.d.ts +11 -31
  21. package/build/api/pin.d.ts.map +1 -1
  22. package/build/api/pin.js +35 -63
  23. package/build/api/stats.d.ts +15 -16
  24. package/build/api/stats.d.ts.map +1 -1
  25. package/build/api/stats.js +60 -99
  26. package/build/api/top-langs.d.ts +13 -18
  27. package/build/api/top-langs.d.ts.map +1 -1
  28. package/build/api/top-langs.js +35 -72
  29. package/build/api/wakatime.d.ts +11 -17
  30. package/build/api/wakatime.d.ts.map +1 -1
  31. package/build/api/wakatime.js +27 -64
  32. package/build/calculateRank.d.ts +0 -9
  33. package/build/calculateRank.d.ts.map +1 -1
  34. package/build/calculateRank.js +12 -17
  35. package/build/cards/contributed-to.d.ts +19 -0
  36. package/build/cards/contributed-to.d.ts.map +1 -0
  37. package/build/cards/contributed-to.js +242 -0
  38. package/build/cards/gist.d.ts +3 -4
  39. package/build/cards/gist.d.ts.map +1 -1
  40. package/build/cards/gist.js +38 -43
  41. package/build/cards/options.d.ts +1 -1
  42. package/build/cards/repo.d.ts +14 -5
  43. package/build/cards/repo.d.ts.map +1 -1
  44. package/build/cards/repo.js +93 -103
  45. package/build/cards/stats.d.ts +18 -11
  46. package/build/cards/stats.d.ts.map +1 -1
  47. package/build/cards/stats.js +191 -222
  48. package/build/cards/top-languages.d.ts +18 -33
  49. package/build/cards/top-languages.d.ts.map +1 -1
  50. package/build/cards/top-languages.js +196 -387
  51. package/build/cards/wakatime.d.ts +17 -8
  52. package/build/cards/wakatime.d.ts.map +1 -1
  53. package/build/cards/wakatime.js +133 -187
  54. package/build/common/Card.d.ts +20 -59
  55. package/build/common/Card.d.ts.map +1 -1
  56. package/build/common/Card.js +131 -198
  57. package/build/common/I18n.d.ts +1 -7
  58. package/build/common/I18n.d.ts.map +1 -1
  59. package/build/common/I18n.js +7 -8
  60. package/build/common/brand.d.ts +76 -0
  61. package/build/common/brand.d.ts.map +1 -0
  62. package/build/common/brand.js +73 -0
  63. package/build/common/color.d.ts +4 -17
  64. package/build/common/color.d.ts.map +1 -1
  65. package/build/common/color.js +67 -49
  66. package/build/common/config.d.ts +4 -14
  67. package/build/common/config.d.ts.map +1 -1
  68. package/build/common/config.js +3 -16
  69. package/build/common/constants.d.ts +6 -2
  70. package/build/common/constants.d.ts.map +1 -1
  71. package/build/common/constants.js +5 -1
  72. package/build/common/date.d.ts +50 -5
  73. package/build/common/date.d.ts.map +1 -1
  74. package/build/common/date.js +104 -4
  75. package/build/common/emojiMap.d.ts +8 -0
  76. package/build/common/emojiMap.d.ts.map +1 -0
  77. package/build/common/emojiMap.js +10 -0
  78. package/build/common/emojiMap.json +1915 -0
  79. package/build/common/error.d.ts +1 -10
  80. package/build/common/error.d.ts.map +1 -1
  81. package/build/common/error.js +1 -10
  82. package/build/common/fmt.d.ts +3 -15
  83. package/build/common/fmt.d.ts.map +1 -1
  84. package/build/common/fmt.js +7 -35
  85. package/build/common/http.d.ts +2 -7
  86. package/build/common/http.d.ts.map +1 -1
  87. package/build/common/http.js +8 -17
  88. package/build/common/icons.d.ts +20 -20
  89. package/build/common/icons.d.ts.map +1 -1
  90. package/build/common/icons.js +108 -67
  91. package/build/common/languageColors.d.ts +0 -1
  92. package/build/common/languageColors.d.ts.map +1 -1
  93. package/build/common/languageColors.js +1 -4
  94. package/build/common/languageColors.json +18 -2
  95. package/build/common/ops.d.ts +11 -17
  96. package/build/common/ops.d.ts.map +1 -1
  97. package/build/common/ops.js +22 -39
  98. package/build/common/render.d.ts +34 -82
  99. package/build/common/render.d.ts.map +1 -1
  100. package/build/common/render.js +225 -259
  101. package/build/common/retryer.d.ts +2 -7
  102. package/build/common/retryer.d.ts.map +1 -1
  103. package/build/common/retryer.js +4 -11
  104. package/build/fetchers/contributed-to.d.ts +62 -0
  105. package/build/fetchers/contributed-to.d.ts.map +1 -0
  106. package/build/fetchers/contributed-to.js +184 -0
  107. package/build/fetchers/gist.d.ts +2 -5
  108. package/build/fetchers/gist.d.ts.map +1 -1
  109. package/build/fetchers/gist.js +1 -5
  110. package/build/fetchers/graphql-error.d.ts +13 -0
  111. package/build/fetchers/graphql-error.d.ts.map +1 -0
  112. package/build/fetchers/graphql-error.js +29 -0
  113. package/build/fetchers/index.d.ts +13 -12
  114. package/build/fetchers/index.d.ts.map +1 -1
  115. package/build/fetchers/index.js +1 -0
  116. package/build/fetchers/repo.d.ts +2 -11
  117. package/build/fetchers/repo.d.ts.map +1 -1
  118. package/build/fetchers/repo.js +20 -33
  119. package/build/fetchers/stats.d.ts +16 -40
  120. package/build/fetchers/stats.d.ts.map +1 -1
  121. package/build/fetchers/stats.js +89 -271
  122. package/build/fetchers/top-languages.d.ts +2 -9
  123. package/build/fetchers/top-languages.d.ts.map +1 -1
  124. package/build/fetchers/top-languages.js +16 -47
  125. package/build/fetchers/types.d.ts +25 -1
  126. package/build/fetchers/types.d.ts.map +1 -1
  127. package/build/fetchers/wakatime.d.ts +2 -6
  128. package/build/fetchers/wakatime.d.ts.map +1 -1
  129. package/build/fetchers/wakatime.js +1 -5
  130. package/build/graphql/contributionsCollection.d.ts +9 -0
  131. package/build/graphql/contributionsCollection.d.ts.map +1 -0
  132. package/build/graphql/contributionsCollection.js +12 -0
  133. package/build/graphql/contributionsDocument.d.ts +6 -6
  134. package/build/graphql/contributionsDocument.d.ts.map +1 -1
  135. package/build/graphql/contributionsDocument.js +8 -16
  136. package/build/graphql/generated/contributed-to.d.ts +22 -0
  137. package/build/graphql/generated/contributed-to.d.ts.map +1 -0
  138. package/build/graphql/generated/contributed-to.js +11 -0
  139. package/build/graphql/generated/gist.d.ts +1 -1
  140. package/build/graphql/generated/repo.d.ts +1 -1
  141. package/build/graphql/generated/stats.d.ts +16 -4
  142. package/build/graphql/generated/stats.d.ts.map +1 -1
  143. package/build/graphql/generated/stats.js +2 -2
  144. package/build/graphql/generated/top-languages.d.ts +2 -2
  145. package/build/graphql/graphqlDocument.d.ts +1 -2
  146. package/build/graphql/graphqlDocument.d.ts.map +1 -1
  147. package/build/graphql/graphqlDocument.js +0 -1
  148. package/build/graphql/reposContributedToDocument.d.ts +4 -5
  149. package/build/graphql/reposContributedToDocument.d.ts.map +1 -1
  150. package/build/graphql/reposContributedToDocument.js +11 -7
  151. package/build/markup/css.d.ts +35 -0
  152. package/build/markup/css.d.ts.map +1 -0
  153. package/build/markup/css.js +64 -0
  154. package/build/markup/element.d.ts +41 -0
  155. package/build/markup/element.d.ts.map +1 -0
  156. package/build/markup/element.js +127 -0
  157. package/build/markup/html.d.ts +13 -0
  158. package/build/markup/html.d.ts.map +1 -0
  159. package/build/markup/html.js +27 -0
  160. package/build/markup/index.d.ts +9 -0
  161. package/build/markup/index.d.ts.map +1 -0
  162. package/build/markup/index.js +6 -0
  163. package/build/markup/serialize.d.ts +16 -0
  164. package/build/markup/serialize.d.ts.map +1 -0
  165. package/build/markup/serialize.js +17 -0
  166. package/build/themes/index.d.ts +332 -333
  167. package/build/themes/index.d.ts.map +1 -1
  168. package/build/themes/index.js +1 -1
  169. package/build/translations.d.ts +66 -7
  170. package/build/translations.d.ts.map +1 -1
  171. package/build/translations.js +686 -629
  172. package/package.json +17 -26
  173. package/src/api/api-result.ts +10 -9
  174. package/src/api/contributed-to.ts +84 -0
  175. package/src/api/gist.ts +22 -46
  176. package/src/api/handler.ts +42 -0
  177. package/src/api/index.ts +13 -12
  178. package/src/api/params.ts +74 -29
  179. package/src/api/pin.ts +38 -65
  180. package/src/api/stats.ts +81 -118
  181. package/src/api/top-langs.ts +38 -80
  182. package/src/api/wakatime.ts +35 -73
  183. package/src/calculateRank.ts +12 -23
  184. package/src/cards/contributed-to.ts +373 -0
  185. package/src/cards/gist.ts +55 -49
  186. package/src/cards/options.ts +1 -1
  187. package/src/cards/repo.ts +134 -120
  188. package/src/cards/stats.ts +262 -252
  189. package/src/cards/top-languages.ts +315 -422
  190. package/src/cards/wakatime.ts +207 -225
  191. package/src/common/Card.ts +207 -214
  192. package/src/common/I18n.ts +7 -8
  193. package/src/common/brand.ts +109 -0
  194. package/src/common/color.ts +80 -57
  195. package/src/common/config.ts +5 -18
  196. package/src/common/constants.ts +8 -2
  197. package/src/common/date.ts +135 -5
  198. package/src/common/emojiMap.json +1915 -0
  199. package/src/common/emojiMap.ts +13 -0
  200. package/src/common/error.ts +2 -11
  201. package/src/common/fmt.ts +7 -44
  202. package/src/common/http.ts +9 -15
  203. package/src/common/icons.ts +122 -42
  204. package/src/common/languageColors.json +18 -2
  205. package/src/common/languageColors.ts +1 -4
  206. package/src/common/ops.ts +31 -48
  207. package/src/common/render.ts +334 -284
  208. package/src/common/retryer.ts +8 -15
  209. package/src/fetchers/contributed-to.ts +271 -0
  210. package/src/fetchers/gist.ts +8 -12
  211. package/src/fetchers/graphql-error.ts +36 -0
  212. package/src/fetchers/index.ts +15 -12
  213. package/src/fetchers/repo.ts +27 -40
  214. package/src/fetchers/stats.ts +157 -366
  215. package/src/fetchers/top-languages.ts +27 -55
  216. package/src/fetchers/types.ts +27 -1
  217. package/src/fetchers/wakatime.ts +5 -9
  218. package/src/graphql/contributionsCollection.ts +18 -0
  219. package/src/graphql/contributionsDocument.ts +14 -19
  220. package/src/graphql/generated/contributed-to.ts +25 -0
  221. package/src/graphql/generated/gist.ts +1 -1
  222. package/src/graphql/generated/repo.ts +1 -1
  223. package/src/graphql/generated/stats.ts +21 -8
  224. package/src/graphql/generated/top-languages.ts +2 -2
  225. package/src/graphql/graphqlDocument.ts +1 -2
  226. package/src/graphql/queries/contributed-to.graphql +8 -0
  227. package/src/graphql/queries/stats.graphql +14 -2
  228. package/src/graphql/reposContributedToDocument.ts +16 -15
  229. package/src/markup/css.ts +118 -0
  230. package/src/markup/element.ts +246 -0
  231. package/src/markup/html.ts +34 -0
  232. package/src/markup/index.ts +9 -0
  233. package/src/markup/serialize.ts +27 -0
  234. package/src/themes/index.ts +1 -1
  235. package/src/translations.ts +699 -629
  236. package/build/cards/index.d.ts +0 -11
  237. package/build/cards/index.d.ts.map +0 -1
  238. package/build/cards/index.js +0 -7
  239. package/build/common/html.d.ts +0 -8
  240. package/build/common/html.d.ts.map +0 -1
  241. package/build/common/html.js +0 -14
  242. package/build/index.d.ts +0 -15
  243. package/build/index.d.ts.map +0 -1
  244. package/build/index.js +0 -10
  245. package/src/_emoji-name-map.d.ts +0 -10
  246. package/src/_github-username-regex.d.ts +0 -4
  247. package/src/cards/index.ts +0 -21
  248. package/src/common/html.ts +0 -17
  249. package/src/index.ts +0 -18
@@ -1,8 +1,8 @@
1
1
  import * as z from 'zod/mini';
2
- import { DISPLAY_FORMATS, WAKATIME_LAYOUTS, renderWakatimeCard } from '../cards/wakatime.js';
2
+ import { renderWakatimeCard } from '../cards/wakatime.js';
3
3
  import { fetchWakatimeStats } from '../fetchers/wakatime.js';
4
- import { errorResult } from './api-result.js';
5
- import { booleanParam, enumParam, listParam, localeParam, looseIntParam, numberParam, parseColorParams, parseParams, rawParam, safeParam, } from './params.js';
4
+ import { cardHandler } from './handler.js';
5
+ import { booleanParam, enumParam, listParam, localeParam, looseIntParam, numberParam, rawParam, safeParam, } from './params.js';
6
6
  /** What the wakatime endpoint accepts, on top of the shared color params. */
7
7
  const wakatimeQuery = z.object({
8
8
  username: safeParam,
@@ -13,12 +13,12 @@ const wakatimeQuery = z.object({
13
13
  hide_progress: booleanParam,
14
14
  custom_title: rawParam,
15
15
  locale: localeParam,
16
- layout: enumParam(WAKATIME_LAYOUTS),
16
+ layout: enumParam(renderWakatimeCard.OPTIONS.layout),
17
17
  langs_count: looseIntParam,
18
18
  hide: listParam,
19
19
  api_domain: rawParam,
20
20
  border_radius: numberParam,
21
- display_format: enumParam(DISPLAY_FORMATS),
21
+ display_format: enumParam(renderWakatimeCard.OPTIONS.display_format),
22
22
  disable_animations: booleanParam,
23
23
  });
24
24
  /**
@@ -26,66 +26,29 @@ const wakatimeQuery = z.object({
26
26
  *
27
27
  * WakaTime needs no GitHub token, so the config is read only for the transport it carries.
28
28
  *
29
- * @param query Raw query params, plus any of the shared color params.
30
- * @param query.username WakaTime username.
31
- * @param query.hide_border Whether to hide the card border.
32
- * @param query.card_width Card width.
33
- * @param query.line_height Line height between the languages.
34
- * @param query.hide_title Whether to hide the card title.
35
- * @param query.hide_progress Whether to hide the progress bars.
36
- * @param query.custom_title Card title.
37
- * @param query.locale Language the card is rendered in.
38
- * @param query.layout How the languages are laid out.
39
- * @param query.langs_count Number of languages to show.
40
- * @param query.hide Comma-separated languages to hide.
41
- * @param query.api_domain WakaTime instance the stats are read from.
42
- * @param query.border_radius Card border radius.
43
- * @param query.display_format Whether values are shown as time or percentages.
44
- * @param query.disable_animations Whether to disable the card animations.
45
- * @param config Deployment config supplying the transport.
46
29
  * @returns The rendered card, or a rendered error.
47
30
  */
48
- const renderWakatime = async (query, config) => {
49
- let colors;
50
- try {
51
- colors = parseColorParams(query);
52
- }
53
- catch (err) {
54
- // A rejected color cannot be used to draw its own error card.
55
- return errorResult(err);
56
- }
57
- try {
58
- const { username, hide_border, card_width, line_height, hide_title, hide_progress, custom_title, locale, layout, langs_count, hide, api_domain, border_radius, display_format, disable_animations, } = parseParams(wakatimeQuery, query);
59
- const stats = await fetchWakatimeStats({ username, api_domain }, config);
60
- return {
61
- status: 'success',
62
- content: renderWakatimeCard(stats, {
63
- ...colors,
64
- custom_title,
65
- hide_title,
66
- hide_border,
67
- card_width,
68
- hide,
69
- line_height,
70
- hide_progress,
71
- border_radius,
72
- locale,
73
- layout,
74
- langs_count,
75
- display_format,
76
- disable_animations,
77
- }),
78
- };
79
- }
80
- catch (err) {
81
- return errorResult(err, colors);
82
- }
83
- };
31
+ const renderWakatime = cardHandler(wakatimeQuery, async ({ username, hide_border, card_width, line_height, hide_title, hide_progress, custom_title, locale, layout, langs_count, hide, api_domain, border_radius, display_format, disable_animations, }, colors, config) => {
32
+ const stats = await fetchWakatimeStats({ username, api_domain }, config);
33
+ return renderWakatimeCard(stats, {
34
+ ...colors,
35
+ custom_title,
36
+ hide_title,
37
+ hide_border,
38
+ card_width,
39
+ hide,
40
+ line_height,
41
+ hide_progress,
42
+ border_radius,
43
+ locale,
44
+ layout,
45
+ langs_count,
46
+ display_format,
47
+ disable_animations,
48
+ });
49
+ });
84
50
  /**
85
- * The card, with the values its enum params accept.
86
- * A UI reads them off the function it calls, e.g. `wakatime.LAYOUTS`.
51
+ * The card, and the values each of its options accepts, keyed by the option's own name.
52
+ * A UI reads them off the function it calls: `wakatime.OPTIONS.layout`.
87
53
  */
88
- export const wakatime = Object.assign(renderWakatime, {
89
- LAYOUTS: WAKATIME_LAYOUTS,
90
- DISPLAY_FORMATS,
91
- });
54
+ export const wakatime = Object.assign(renderWakatime, { OPTIONS: renderWakatimeCard.OPTIONS });
@@ -1,15 +1,6 @@
1
1
  /**
2
2
  * Calculates the users rank.
3
3
  *
4
- * @param params Parameters on which the user's rank depends.
5
- * @param params.all_commits Whether `include_all_commits` was used.
6
- * @param params.commits Number of commits.
7
- * @param params.prs The number of pull requests.
8
- * @param params.issues The number of issues.
9
- * @param params.reviews The number of reviews.
10
- * @param params.repos Total number of repos (accepted for compatibility, unused in the calculation).
11
- * @param params.stars The number of stars.
12
- * @param params.followers The number of followers.
13
4
  * @returns The users rank.
14
5
  */
15
6
  declare function calculateRank({ all_commits, commits, prs, issues, reviews, stars, followers, }: {
@@ -1 +1 @@
1
- {"version":3,"file":"calculateRank.d.ts","sourceRoot":"","sources":["../src/calculateRank.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;GAaG;AACH,iBAAS,aAAa,CAAC,EACrB,WAAW,EACX,OAAO,EACP,GAAG,EACH,MAAM,EACN,OAAO,EACP,KAAK,EACL,SAAS,GACV,EAAE;IACD,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAoCxC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"calculateRank.d.ts","sourceRoot":"","sources":["../src/calculateRank.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,iBAAS,aAAa,CAAC,EACrB,WAAW,EACX,OAAO,EACP,GAAG,EACH,MAAM,EACN,OAAO,EACP,KAAK,EACL,SAAS,GACV,EAAE;IACD,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAoCxC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Calculates the exponential cdf.
3
3
  *
4
- * @param x The value.
5
4
  * @returns The exponential cdf.
6
5
  */
7
6
  function exponential_cdf(x) {
@@ -10,7 +9,6 @@ function exponential_cdf(x) {
10
9
  /**
11
10
  * Calculates the log normal cdf.
12
11
  *
13
- * @param x The value.
14
12
  * @returns The log normal cdf.
15
13
  */
16
14
  function log_normal_cdf(x) {
@@ -20,24 +18,21 @@ function log_normal_cdf(x) {
20
18
  /**
21
19
  * Calculates the users rank.
22
20
  *
23
- * @param params Parameters on which the user's rank depends.
24
- * @param params.all_commits Whether `include_all_commits` was used.
25
- * @param params.commits Number of commits.
26
- * @param params.prs The number of pull requests.
27
- * @param params.issues The number of issues.
28
- * @param params.reviews The number of reviews.
29
- * @param params.repos Total number of repos (accepted for compatibility, unused in the calculation).
30
- * @param params.stars The number of stars.
31
- * @param params.followers The number of followers.
32
21
  * @returns The users rank.
33
22
  */
34
23
  function calculateRank({ all_commits, commits, prs, issues, reviews, stars, followers, }) {
35
- const COMMITS_MEDIAN = all_commits ? 1000 : 250, COMMITS_WEIGHT = 2;
36
- const PRS_MEDIAN = 50, PRS_WEIGHT = 3;
37
- const ISSUES_MEDIAN = 25, ISSUES_WEIGHT = 1;
38
- const REVIEWS_MEDIAN = 2, REVIEWS_WEIGHT = 1;
39
- const STARS_MEDIAN = 50, STARS_WEIGHT = 4;
40
- const FOLLOWERS_MEDIAN = 10, FOLLOWERS_WEIGHT = 1;
24
+ const COMMITS_MEDIAN = all_commits ? 1000 : 250;
25
+ const COMMITS_WEIGHT = 2;
26
+ const PRS_MEDIAN = 50;
27
+ const PRS_WEIGHT = 3;
28
+ const ISSUES_MEDIAN = 25;
29
+ const ISSUES_WEIGHT = 1;
30
+ const REVIEWS_MEDIAN = 2;
31
+ const REVIEWS_WEIGHT = 1;
32
+ const STARS_MEDIAN = 50;
33
+ const STARS_WEIGHT = 4;
34
+ const FOLLOWERS_MEDIAN = 10;
35
+ const FOLLOWERS_WEIGHT = 1;
41
36
  const TOTAL_WEIGHT = COMMITS_WEIGHT + PRS_WEIGHT + ISSUES_WEIGHT + REVIEWS_WEIGHT + STARS_WEIGHT + FOLLOWERS_WEIGHT;
42
37
  const THRESHOLDS = [1, 12.5, 25, 37.5, 50, 62.5, 75, 87.5, 100];
43
38
  const LEVELS = ['S', 'A+', 'A', 'A-', 'B+', 'B', 'B-', 'C+', 'C'];
@@ -0,0 +1,19 @@
1
+ import type { ContributedToData } from '../fetchers/types.ts';
2
+ import type { CardOptions, CommonCardOptions } from './options.ts';
3
+ declare const MIN_CARD_WIDTH = 340;
4
+ interface ContributedToCardOptions extends CommonCardOptions {
5
+ locale: string;
6
+ hide_title: boolean;
7
+ card_width: number;
8
+ custom_title: string;
9
+ disable_animations: boolean;
10
+ hide_years: boolean;
11
+ }
12
+ /**
13
+ * Renders the repositories a user contributed to, ranked by contributions.
14
+ *
15
+ * @returns Contributed-to card SVG string.
16
+ */
17
+ declare const renderContributedToCard: (data: ContributedToData, options?: CardOptions<ContributedToCardOptions>) => string;
18
+ export { renderContributedToCard, MIN_CARD_WIDTH };
19
+ //# sourceMappingURL=contributed-to.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contributed-to.d.ts","sourceRoot":"","sources":["../../src/cards/contributed-to.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAmB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAK/E,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGnE,QAAA,MAAM,cAAc,MAAM,CAAC;AA8B3B,UAAU,wBAAyB,SAAQ,iBAAiB;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAC;CACrB;AAmKD;;;;GAIG;AACH,QAAA,MAAM,uBAAuB,SACrB,iBAAiB,YACd,WAAW,CAAC,wBAAwB,CAAC,KAC7C,MAkJF,CAAC;AAEF,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,242 @@
1
+ import { CARD_ICON, CARD_WIDTH, FONT_SIZE, firefoxFontSize, font } from '../common/brand.js';
2
+ import { Card } from '../common/Card.js';
3
+ import { getLightDarkColors } from '../common/color.js';
4
+ import { formatYears } from '../common/date.js';
5
+ import { kFormatter } from '../common/fmt.js';
6
+ import { I18n } from '../common/I18n.js';
7
+ import { clampValue } from '../common/ops.js';
8
+ import { createProgressNode, measureText } from '../common/render.js';
9
+ import { atRule, el, rule } from '../markup/index.js';
10
+ import { contributedToCardLocales } from '../translations.js';
11
+ const CARD_DEFAULT_WIDTH = CARD_WIDTH.wide;
12
+ const MIN_CARD_WIDTH = 340;
13
+ /** Padding the card keeps at its edges; matches `Card`'s own `paddingX`. */
14
+ const CARD_PADDING = 25;
15
+ const TITLE_FONT_SIZE = FONT_SIZE.title;
16
+ /** What `Card`'s title layout reserves for the prefix icon, so the title text starts past it. */
17
+ const TITLE_ICON_COLUMN = 25;
18
+ const NAME_FONT_SIZE = FONT_SIZE.meta;
19
+ /** Room kept at the right edge for the contribution count. */
20
+ const COUNT_WIDTH = 46;
21
+ const BAR_WIDTH = 130;
22
+ const COLUMN_GAP = 12;
23
+ /** Baseline of the first row, measured from the top of the card body. */
24
+ const FIRST_ROW_Y = 10;
25
+ const ROW_HEIGHT = 38;
26
+ /** A row with no year marks under it needs only its own line. */
27
+ const ROW_HEIGHT_NO_YEARS = 24;
28
+ /** How far the year marks sit below their row's baseline. */
29
+ const YEAR_STRIP_Y = 8;
30
+ const YEAR_MARK_SIZE = 7;
31
+ const YEAR_MARK_GAP = 3;
32
+ /** Gap between the last row and the footer's own baseline. */
33
+ const FOOTER_GAP = 12;
34
+ /** Where `Card` puts the body while the title is shown; `setHideTitle` adjusts the height by the same 30. */
35
+ const BODY_OFFSET_Y = 55;
36
+ const BOTTOM_PADDING = 18;
37
+ /**
38
+ * The title, naming the account unless that makes it too wide for the card.
39
+ *
40
+ * A login is up to 39 characters, which at the title's size overruns the default width
41
+ * by half again — so the plain wording is the fallback rather than a truncated login.
42
+ *
43
+ * @returns The default title, which `custom_title` still overrides.
44
+ */
45
+ const defaultTitleFor = (i18n, contentWidth) => {
46
+ const named = i18n.t('contributedtocard.title');
47
+ return measureText(named, TITLE_FONT_SIZE) <= contentWidth
48
+ ? named
49
+ : i18n.t('contributedtocard.title-unnamed');
50
+ };
51
+ /**
52
+ * Shortens a name to fit its column, ending it with an ellipsis when it does not.
53
+ *
54
+ * @returns The name as it is drawn.
55
+ */
56
+ const truncateName = (name, maxWidth) => {
57
+ if (measureText(name, NAME_FONT_SIZE) <= maxWidth) {
58
+ return name;
59
+ }
60
+ let trimmed = name;
61
+ while (trimmed.length > 1 && measureText(`${trimmed}…`, NAME_FONT_SIZE) > maxWidth) {
62
+ trimmed = trimmed.slice(0, -1);
63
+ }
64
+ return `${trimmed}…`;
65
+ };
66
+ /**
67
+ * The marks under a repository's name, one per contribution year of the account,
68
+ * filled for the years that repository got a contribution.
69
+ *
70
+ * The step shrinks to fit, so a long-lived account keeps the strip inside its column
71
+ * rather than running it under the bar.
72
+ *
73
+ * @returns The strip, positioned relative to its row's baseline.
74
+ */
75
+ const createYearStrip = (repoYears, years, columnWidth) => {
76
+ const contributed = new Set(repoYears);
77
+ const step = Math.min(YEAR_MARK_SIZE + YEAR_MARK_GAP, Math.floor(columnWidth / years.length));
78
+ const size = Math.max(step - YEAR_MARK_GAP, 3);
79
+ return el('g', { 'data-testid': 'year-strip', transform: `translate(0, ${YEAR_STRIP_Y})` }, years.map((year, index) => el('rect', {
80
+ 'data-testid': contributed.has(year) ? 'year-on' : 'year-off',
81
+ class: contributed.has(year) ? 'year-on' : 'year-off',
82
+ x: index * step,
83
+ y: 0,
84
+ width: size,
85
+ height: size,
86
+ rx: 1,
87
+ ry: 1,
88
+ })));
89
+ };
90
+ /**
91
+ * One repository: its name, a bar for its share of the top repository's contributions,
92
+ * and the count itself.
93
+ *
94
+ * @returns The row, positioned by its own transform.
95
+ */
96
+ const createRepoRow = ({ repo, index, maxContributions, years, nameWidth, contentWidth, rowHeight, }) => el('g', {
97
+ class: 'stagger',
98
+ style: `animation-delay: ${450 + index * 150}ms`,
99
+ transform: `translate(0, ${FIRST_ROW_Y + index * rowHeight})`,
100
+ }, el('text', { class: 'repo-name', 'data-testid': 'repo-name', x: 0, y: 0 }, truncateName(repo.nameWithOwner, nameWidth)), createProgressNode({
101
+ x: nameWidth + COLUMN_GAP,
102
+ y: -9,
103
+ width: BAR_WIDTH,
104
+ progress: (repo.contributions / maxContributions) * 100,
105
+ delay: 450 + index * 150,
106
+ }), el('text', {
107
+ class: 'count',
108
+ 'data-testid': 'repo-contributions',
109
+ x: contentWidth,
110
+ y: 0,
111
+ 'text-anchor': 'end',
112
+ }, kFormatter(repo.contributions)), years.length > 0 && createYearStrip(repo.years, years, nameWidth));
113
+ /**
114
+ * The line under the rows: how much of the walk the card is showing, and over what years.
115
+ *
116
+ * Never dropped, because the card shows a slice of the repositories
117
+ * and a rank means nothing without the total it was taken from.
118
+ *
119
+ * @returns The footer text.
120
+ */
121
+ const footerText = ({ i18n, shown, totalRepos, years, }) => {
122
+ const parts = [
123
+ i18n.t(shown < totalRepos ? 'contributedtocard.footer-top' : 'contributedtocard.footer-all'),
124
+ ];
125
+ const [firstYear] = years;
126
+ const lastYear = years.at(-1);
127
+ if (firstYear !== undefined && lastYear !== undefined) {
128
+ parts.push(formatYears(firstYear, lastYear));
129
+ }
130
+ return parts.join(' · ');
131
+ };
132
+ /**
133
+ * Renders the repositories a user contributed to, ranked by contributions.
134
+ *
135
+ * @returns Contributed-to card SVG string.
136
+ */
137
+ const renderContributedToCard = (data, options = {}) => {
138
+ const { locale, hide_title = false, hide_border = false, card_width, custom_title, disable_animations = false, hide_years = false, border_radius, theme = 'default', } = options;
139
+ const { login, repos, totalRepos } = data;
140
+ const years = hide_years ? [] : data.years;
141
+ const width = card_width && !Number.isNaN(card_width)
142
+ ? clampValue(card_width, MIN_CARD_WIDTH, Number.MAX_SAFE_INTEGER)
143
+ : CARD_DEFAULT_WIDTH;
144
+ const contentWidth = width - 2 * CARD_PADDING;
145
+ const nameWidth = contentWidth - COUNT_WIDTH - BAR_WIDTH - 2 * COLUMN_GAP;
146
+ const rowHeight = years.length > 0 ? ROW_HEIGHT : ROW_HEIGHT_NO_YEARS;
147
+ // the count is a share of the busiest repository, so the first bar is always full
148
+ const maxContributions = Math.max(...repos.map((repo) => repo.contributions), 1);
149
+ const rows = repos.map((repo, index) => createRepoRow({
150
+ repo,
151
+ index,
152
+ maxContributions,
153
+ years,
154
+ nameWidth,
155
+ contentWidth,
156
+ rowHeight,
157
+ }));
158
+ const i18n = new I18n({
159
+ locale,
160
+ translations: contributedToCardLocales({ login, shown: repos.length, totalRepos }),
161
+ });
162
+ const footer = footerText({ i18n, shown: repos.length, totalRepos, years });
163
+ const footerY = FIRST_ROW_Y + Math.max(repos.length, 1) * rowHeight + FOOTER_GAP;
164
+ const height = BODY_OFFSET_Y + footerY + BOTTOM_PADDING;
165
+ const { lightColors, darkColors } = getLightDarkColors({ ...options, theme });
166
+ const card = new Card({
167
+ customTitle: custom_title,
168
+ defaultTitle: defaultTitleFor(i18n, contentWidth - TITLE_ICON_COLUMN),
169
+ titlePrefixIcon: CARD_ICON.contributedTo,
170
+ width,
171
+ height,
172
+ border_radius,
173
+ colors: { light: lightColors, dark: darkColors },
174
+ });
175
+ if (disable_animations) {
176
+ card.disableAnimations();
177
+ }
178
+ card.setHideBorder(hide_border);
179
+ card.setHideTitle(hide_title);
180
+ card.setCSS({
181
+ light: ({ textColor, titleColor, iconColor, progBarBgColor }) => [
182
+ atRule('@keyframes growWidthAnimation', rule('from', { width: 0 }), rule('to', { width: '100%' })),
183
+ rule('.repo-name', {
184
+ font: font('regular', 'meta'),
185
+ fill: textColor,
186
+ }),
187
+ rule('.count', {
188
+ font: font('semibold', 'meta'),
189
+ fill: textColor,
190
+ 'font-variant-numeric': 'tabular-nums',
191
+ }),
192
+ rule('.footer', {
193
+ font: font('regular', 'micro'),
194
+ fill: textColor,
195
+ opacity: 0.7,
196
+ }),
197
+ firefoxFontSize(['.repo-name', '.count'], 'small'),
198
+ rule('.year-on', { fill: titleColor }),
199
+ // a year with no contribution reads off the text color, not `progBarBgColor`:
200
+ // on a dark theme that color is a light grey, and the empty marks came out looking filled
201
+ rule('.year-off', { fill: textColor, opacity: 0.25 }),
202
+ rule('.progress-background', { fill: progBarBgColor }),
203
+ rule('.lang-progress', {
204
+ fill: titleColor,
205
+ animation: 'growWidthAnimation 0.6s ease-in-out forwards',
206
+ }),
207
+ rule('.stagger', { opacity: 0, animation: 'fadeInAnimation 0.3s ease-in-out forwards' }),
208
+ rule('.icon', { fill: iconColor, display: 'block' }),
209
+ ],
210
+ dark: ({ textColor, titleColor, iconColor, progBarBgColor }) => [
211
+ rule('.repo-name', { fill: textColor }),
212
+ rule('.count', { fill: textColor }),
213
+ rule('.footer', { fill: textColor }),
214
+ rule('.year-on', { fill: titleColor }),
215
+ // a year with no contribution reads off the text color, not `progBarBgColor`:
216
+ // on a dark theme that color is a light grey, and the empty marks came out looking filled
217
+ rule('.year-off', { fill: textColor, opacity: 0.25 }),
218
+ rule('.progress-background', { fill: progBarBgColor }),
219
+ rule('.lang-progress', { fill: titleColor }),
220
+ rule('.icon', { fill: iconColor }),
221
+ ],
222
+ });
223
+ // `role="img"` hides the inner text from assistive tech, so everything the card
224
+ // shows has to be repeated here — the year marks included, since they carry
225
+ // information no other element on the card does.
226
+ card.setAccessibilityLabel({
227
+ title: card.title,
228
+ desc: [
229
+ ...repos.map((repo) => {
230
+ const inYears = hide_years
231
+ ? ''
232
+ : `, ${i18n.t('contributedtocard.years')}: ${repo.years.join(', ')}`;
233
+ return `${repo.nameWithOwner}: ${repo.contributions} ${i18n.t('contributedtocard.contributions')}${inYears}`;
234
+ }),
235
+ footer,
236
+ ].join('; '),
237
+ });
238
+ return card.render(el('g', { 'data-testid': 'contributed-to-body', transform: `translate(${CARD_PADDING}, 0)` }, repos.length === 0
239
+ ? el('text', { class: 'repo-name', 'data-testid': 'no-repos', x: 0, y: FIRST_ROW_Y }, i18n.t('contributedtocard.no-contributions'))
240
+ : rows, el('text', { class: 'footer', 'data-testid': 'footer', x: 0, y: footerY }, footer)));
241
+ };
242
+ export { renderContributedToCard, MIN_CARD_WIDTH };
@@ -1,14 +1,13 @@
1
- import type { GistData } from '../fetchers/types.js';
2
- import type { CardOptions, CommonCardOptions } from './options.js';
1
+ import type { GistData } from '../fetchers/types.ts';
2
+ import type { CardOptions, CommonCardOptions } from './options.ts';
3
3
  interface GistCardOptions extends CommonCardOptions {
4
+ locale: string;
4
5
  show_owner: boolean;
5
6
  browser_rendering: boolean;
6
7
  }
7
8
  /**
8
9
  * Render gist card.
9
10
  *
10
- * @param gistData Gist data.
11
- * @param options Gist card options.
12
11
  * @returns Gist card.
13
12
  */
14
13
  declare const renderGistCard: (gistData: GistData, options?: CardOptions<GistCardOptions>) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"gist.d.ts","sourceRoot":"","sources":["../../src/cards/gist.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAWnE,UAAU,eAAgB,SAAQ,iBAAiB;IACjD,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,QAAA,MAAM,cAAc,GAAI,UAAU,QAAQ,EAAE,UAAS,WAAW,CAAC,eAAe,CAAM,KAAG,MA6HxF,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"gist.d.ts","sourceRoot":"","sources":["../../src/cards/gist.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKrD,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAWnE,UAAU,eAAgB,SAAQ,iBAAiB;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,QAAA,MAAM,cAAc,aAAc,QAAQ,YAAW,WAAW,CAAC,eAAe,CAAC,KAAQ,MA+HxF,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -1,31 +1,33 @@
1
- import { default as Card } from '../common/Card.js';
1
+ import { CARD_ICON, CARD_WIDTH, FONT_SIZE, font } from '../common/brand.js';
2
+ import { Card } from '../common/Card.js';
2
3
  import { getLightDarkColors } from '../common/color.js';
3
- import { kFormatter, wrapTextMultiline } from '../common/fmt.js';
4
- import { encodeHTML } from '../common/html.js';
4
+ import { kFormatter } from '../common/fmt.js';
5
+ import { I18n } from '../common/I18n.js';
5
6
  import { icons } from '../common/icons.js';
6
7
  import { getLanguageColor } from '../common/languageColors.js';
7
8
  import { parseEmojis } from '../common/ops.js';
8
- import { countWrappedLines, createLanguageNode, flexLayout, iconWithLabel, measureText, wrappedTextNode, wrappedTextStyles, } from '../common/render.js';
9
+ import { countWrappedLines, wrapTextMultiline, createLanguageNode, flexLayout, iconWithLabel, measureText, wrappedTextNode, wrappedTextStyles, } from '../common/render.js';
10
+ import { el, rule } from '../markup/index.js';
11
+ import { gistCardLocales } from '../translations.js';
9
12
  const ICON_SIZE = 16;
10
- const CARD_DEFAULT_WIDTH = 400;
13
+ const CARD_DEFAULT_WIDTH = CARD_WIDTH.standard;
11
14
  const X_OFFSET = 25;
12
15
  const HEADER_MAX_LENGTH = 35;
13
16
  const DESCRIPTION_BOX_WIDTH = CARD_DEFAULT_WIDTH - 2 * X_OFFSET;
14
- const DESCRIPTION_FONT_SIZE = 13;
17
+ const DESCRIPTION_FONT_SIZE = FONT_SIZE.meta;
15
18
  const DESCRIPTION_LINE_HEIGHT_PX = 16;
16
19
  const DESCRIPTION_MAX_LINES = 10;
17
20
  /**
18
21
  * Render gist card.
19
22
  *
20
- * @param gistData Gist data.
21
- * @param options Gist card options.
22
23
  * @returns Gist card.
23
24
  */
24
25
  const renderGistCard = (gistData, options = {}) => {
25
26
  const { name, nameWithOwner, description, language, starsCount, forksCount } = gistData;
26
- const { theme = 'default_repocard', border_radius, show_owner = false, browser_rendering = false, hide_border = false, } = options;
27
+ const { locale, theme = 'default_repocard', border_radius, show_owner = false, browser_rendering = false, hide_border = false, } = options;
27
28
  const { lightColors, darkColors } = getLightDarkColors({ ...options, theme });
28
- const desc = parseEmojis(description || 'No description provided');
29
+ const i18n = new I18n({ locale, translations: gistCardLocales });
30
+ const desc = parseEmojis(description || i18n.t('gistcard.no-description'));
29
31
  let descriptionLines;
30
32
  let descriptionSvg;
31
33
  if (browser_rendering) {
@@ -49,12 +51,7 @@ const renderGistCard = (gistData, options = {}) => {
49
51
  const linesLimit = 10;
50
52
  const multiLineDescription = wrapTextMultiline(desc, DESCRIPTION_BOX_WIDTH, DESCRIPTION_FONT_SIZE, linesLimit);
51
53
  descriptionLines = multiLineDescription.length;
52
- descriptionSvg = multiLineDescription
53
- .map((line) => `<tspan dy="1.2em" x="${X_OFFSET}">${encodeHTML(line)}</tspan>`)
54
- .join('');
55
- descriptionSvg = `<text class="description" x="${X_OFFSET}" y="-5">
56
- ${descriptionSvg}
57
- </text>`;
54
+ descriptionSvg = el('text', { class: 'description', x: X_OFFSET, y: -5 }, multiLineDescription.map((line) => el('tspan', { dy: '1.2em', x: X_OFFSET }, line)));
58
55
  }
59
56
  const lineHeight = descriptionLines > 3 ? 12 : 10;
60
57
  const height = (descriptionLines > 1 ? 120 : 110) + descriptionLines * lineHeight;
@@ -62,7 +59,7 @@ const renderGistCard = (gistData, options = {}) => {
62
59
  const totalForks = kFormatter(forksCount);
63
60
  const svgStars = iconWithLabel(icons.star, totalStars, 'starsCount', ICON_SIZE);
64
61
  const svgForks = iconWithLabel(icons.fork, totalForks, 'forksCount', ICON_SIZE);
65
- const languageName = language || 'Unspecified';
62
+ const languageName = language || i18n.t('gistcard.unspecified-language');
66
63
  const languageColor = getLanguageColor(languageName);
67
64
  const svgLanguage = createLanguageNode(languageName, languageColor);
68
65
  const starAndForkCount = flexLayout({
@@ -73,47 +70,45 @@ const renderGistCard = (gistData, options = {}) => {
73
70
  ICON_SIZE + measureText(`${totalForks}`, 12),
74
71
  ],
75
72
  gap: 25,
76
- }).join('');
73
+ });
77
74
  const header = show_owner ? nameWithOwner : name;
78
75
  const card = new Card({
79
76
  defaultTitle: header.length > HEADER_MAX_LENGTH ? `${header.slice(0, HEADER_MAX_LENGTH)}...` : header,
80
- titlePrefixIcon: icons.gist,
77
+ titlePrefixIcon: CARD_ICON.gist,
81
78
  width: CARD_DEFAULT_WIDTH,
82
79
  height,
83
80
  border_radius,
84
81
  colors: { light: lightColors, dark: darkColors },
85
82
  });
86
83
  card.setCSS({
87
- light: ({ textColor, iconColor }) => `
88
- .description {
89
- font: 400 ${DESCRIPTION_FONT_SIZE}px 'Segoe UI', Ubuntu, Sans-Serif;fill: ${textColor};
90
- ${browser_rendering ? wrappedTextStyles(textColor) : ''}
91
- }
92
- .gray { font: 400 12px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
93
- .icon { fill: ${iconColor} }
94
- `,
95
- dark: ({ textColor, iconColor }) => `
96
- .description {
97
- fill: ${textColor};
98
- ${browser_rendering ? wrappedTextStyles(textColor) : ''}
99
- }
100
- .gray { fill: ${textColor} }
101
- .icon { fill: ${iconColor} }
102
- `,
84
+ light: ({ textColor, iconColor }) => [
85
+ rule('.description', {
86
+ font: font('regular', 'meta'),
87
+ fill: textColor,
88
+ ...(browser_rendering ? wrappedTextStyles(textColor) : {}),
89
+ }),
90
+ rule('.gray', { font: font('regular', 'small'), fill: textColor }),
91
+ rule('.icon', { fill: iconColor }),
92
+ ],
93
+ dark: ({ textColor, iconColor }) => [
94
+ rule('.description', {
95
+ fill: textColor,
96
+ ...(browser_rendering ? wrappedTextStyles(textColor) : {}),
97
+ }),
98
+ rule('.gray', { fill: textColor }),
99
+ rule('.icon', { fill: iconColor }),
100
+ ],
103
101
  });
104
102
  card.setHideBorder(hide_border);
105
103
  // `role="img"` hides the inner text from assistive tech, so everything the card
106
104
  // shows has to be repeated here.
107
105
  card.setAccessibilityLabel({
108
106
  title: card.title,
109
- desc: `${desc}. Language: ${languageName}, Stars: ${totalStars}, Forks: ${totalForks}`,
107
+ desc: `${desc}. ${i18n.t('gistcard.language')}: ${languageName}, ${i18n.t('gistcard.stars')}: ${totalStars}, ${i18n.t('gistcard.forks')}: ${totalForks}`,
110
108
  });
111
- return card.render(`
112
- ${descriptionSvg}
113
-
114
- <g transform="translate(30, ${height - 75})">
115
- ${starAndForkCount}
116
- </g>
117
- `);
109
+ return card.render([
110
+ descriptionSvg,
111
+ el('g', { transform: `translate(30, ${height - 75})` }, starAndForkCount),
112
+ ]);
118
113
  };
119
114
  export { renderGistCard };
@@ -1,4 +1,4 @@
1
- import type { ColorParams } from '../common/color.js';
1
+ import type { ColorParams } from '../common/color.ts';
2
2
  /**
3
3
  * Options every card accepts.
4
4
  * Cards spread these into `getLightDarkColors`, hence {@link ColorParams}.
@@ -1,5 +1,5 @@
1
- import type { RepositoryData } from '../fetchers/types.js';
2
- import type { CardOptions, CommonCardOptions } from './options.js';
1
+ import type { RepositoryData } from '../fetchers/types.ts';
2
+ import type { CardOptions, CommonCardOptions } from './options.ts';
3
3
  interface RepoCardOptions extends CommonCardOptions {
4
4
  locale: string;
5
5
  show_owner: boolean;
@@ -16,10 +16,19 @@ interface RepoCardOptions extends CommonCardOptions {
16
16
  /**
17
17
  * Renders repository card details.
18
18
  *
19
- * @param repo Repository data.
20
- * @param options Card options.
21
19
  * @returns Repository card SVG object.
22
20
  */
23
- declare const renderRepoCard: (repo: RepositoryData, options?: CardOptions<RepoCardOptions>) => string;
21
+ declare const renderCard: (repo: RepositoryData, options?: CardOptions<RepoCardOptions>) => string;
22
+ /**
23
+ * The card, and the values each of its options accepts, keyed by the option's own name.
24
+ * They ride on the renderer so a list cannot be found without what draws it;
25
+ * the api handler forwards them onto its own export, which is what a UI reads.
26
+ */
27
+ declare const renderRepoCard: typeof renderCard & {
28
+ OPTIONS: {
29
+ show: readonly ["prs_authored", "prs_commented", "prs_reviewed", "issues_authored", "issues_commented"];
30
+ number_format: readonly ["short", "long"];
31
+ };
32
+ };
24
33
  export { renderRepoCard };
25
34
  //# sourceMappingURL=repo.d.ts.map