@stats-organization/github-readme-stats-core 2.1.3 → 2.1.5

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 (123) hide show
  1. package/build/api/gist.d.ts.map +1 -1
  2. package/build/api/gist.js +34 -1
  3. package/build/api/index.d.ts.map +1 -1
  4. package/build/api/index.js +18 -1
  5. package/build/api/pin.d.ts.map +1 -1
  6. package/build/api/pin.js +17 -1
  7. package/build/api/top-langs.d.ts.map +1 -1
  8. package/build/api/top-langs.js +36 -5
  9. package/build/api/wakatime.d.ts.map +1 -1
  10. package/build/api/wakatime.js +34 -1
  11. package/build/calculateRank.d.ts +12 -11
  12. package/build/calculateRank.d.ts.map +1 -1
  13. package/build/calculateRank.js +18 -18
  14. package/build/cards/gist.d.ts.map +1 -1
  15. package/build/cards/gist.js +0 -1
  16. package/build/cards/repo.d.ts.map +1 -1
  17. package/build/cards/repo.js +29 -21
  18. package/build/cards/stats.d.ts +4 -2
  19. package/build/cards/stats.d.ts.map +1 -1
  20. package/build/cards/stats.js +21 -9
  21. package/build/cards/top-languages.d.ts.map +1 -1
  22. package/build/cards/top-languages.js +39 -12
  23. package/build/cards/wakatime.d.ts.map +1 -1
  24. package/build/cards/wakatime.js +29 -9
  25. package/build/common/Card.d.ts +54 -60
  26. package/build/common/Card.d.ts.map +1 -1
  27. package/build/common/Card.js +88 -61
  28. package/build/common/I18n.d.ts +13 -14
  29. package/build/common/I18n.d.ts.map +1 -1
  30. package/build/common/I18n.js +13 -12
  31. package/build/common/color.d.ts +56 -32
  32. package/build/common/color.d.ts.map +1 -1
  33. package/build/common/color.js +87 -50
  34. package/build/common/config.d.ts +18 -2
  35. package/build/common/config.d.ts.map +1 -1
  36. package/build/common/config.js +17 -26
  37. package/build/common/constants.d.ts +2 -2
  38. package/build/common/constants.d.ts.map +1 -1
  39. package/build/common/constants.js +5 -3
  40. package/build/common/error.d.ts +36 -29
  41. package/build/common/error.d.ts.map +1 -1
  42. package/build/common/error.js +14 -10
  43. package/build/common/fmt.d.ts +14 -13
  44. package/build/common/fmt.d.ts.map +1 -1
  45. package/build/common/fmt.js +19 -15
  46. package/build/common/html.d.ts +2 -4
  47. package/build/common/html.d.ts.map +1 -1
  48. package/build/common/html.js +2 -6
  49. package/build/common/http.d.ts +13 -4
  50. package/build/common/http.d.ts.map +1 -1
  51. package/build/common/http.js +3 -4
  52. package/build/common/icons.d.ts +22 -21
  53. package/build/common/icons.d.ts.map +1 -1
  54. package/build/common/icons.js +4 -5
  55. package/build/common/languageColors.json +9 -1
  56. package/build/common/ops.d.ts +30 -29
  57. package/build/common/ops.d.ts.map +1 -1
  58. package/build/common/ops.js +32 -38
  59. package/build/common/render.d.ts +115 -111
  60. package/build/common/render.d.ts.map +1 -1
  61. package/build/common/render.js +138 -88
  62. package/build/common/retryer.d.ts +24 -13
  63. package/build/common/retryer.d.ts.map +1 -1
  64. package/build/common/retryer.js +22 -30
  65. package/build/fetchers/gist.d.ts +6 -21
  66. package/build/fetchers/gist.d.ts.map +1 -1
  67. package/build/fetchers/gist.js +30 -36
  68. package/build/fetchers/repo.d.ts.map +1 -1
  69. package/build/fetchers/repo.js +4 -7
  70. package/build/fetchers/stats.d.ts.map +1 -1
  71. package/build/fetchers/stats.js +3 -7
  72. package/build/fetchers/top-languages.d.ts.map +1 -1
  73. package/build/fetchers/top-languages.js +0 -1
  74. package/build/fetchers/types.d.ts +126 -0
  75. package/build/fetchers/types.d.ts.map +1 -0
  76. package/build/fetchers/types.js +1 -0
  77. package/build/fetchers/wakatime.d.ts.map +1 -1
  78. package/build/fetchers/wakatime.js +0 -1
  79. package/build/translations.d.ts +627 -24
  80. package/build/translations.d.ts.map +1 -1
  81. package/build/translations.js +7 -8
  82. package/package.json +4 -4
  83. package/src/_emoji-name-map.d.ts +10 -0
  84. package/src/api/gist.js +36 -2
  85. package/src/api/index.js +19 -2
  86. package/src/api/pin.js +18 -2
  87. package/src/api/top-langs.js +38 -6
  88. package/src/api/wakatime.js +36 -2
  89. package/src/{calculateRank.js → calculateRank.ts} +29 -19
  90. package/src/cards/gist.js +0 -2
  91. package/src/cards/repo.js +30 -22
  92. package/src/cards/stats.js +22 -10
  93. package/src/cards/top-languages.js +49 -13
  94. package/src/cards/wakatime.js +33 -10
  95. package/src/common/Card.ts +338 -0
  96. package/src/common/I18n.ts +49 -0
  97. package/src/common/color.ts +212 -0
  98. package/src/common/config.ts +83 -0
  99. package/src/common/constants.ts +10 -0
  100. package/src/common/{error.js → error.ts} +20 -14
  101. package/src/common/{fmt.js → fmt.ts} +27 -19
  102. package/src/common/{html.js → html.ts} +3 -8
  103. package/src/common/http.ts +31 -0
  104. package/src/common/{icons.js → icons.ts} +9 -7
  105. package/src/common/languageColors.json +9 -1
  106. package/src/common/{ops.js → ops.ts} +48 -52
  107. package/src/common/{render.js → render.ts} +208 -98
  108. package/src/common/retryer.ts +125 -0
  109. package/src/fetchers/gist.ts +136 -0
  110. package/src/fetchers/repo.js +4 -8
  111. package/src/fetchers/stats.js +3 -8
  112. package/src/fetchers/top-languages.js +0 -2
  113. package/src/fetchers/{types.d.ts → types.ts} +1 -1
  114. package/src/fetchers/wakatime.js +0 -2
  115. package/src/{translations.js → translations.ts} +14 -10
  116. package/src/common/Card.js +0 -275
  117. package/src/common/I18n.js +0 -42
  118. package/src/common/color.js +0 -145
  119. package/src/common/config.js +0 -78
  120. package/src/common/constants.js +0 -9
  121. package/src/common/http.js +0 -21
  122. package/src/common/retryer.js +0 -104
  123. package/src/fetchers/gist.js +0 -114
@@ -1 +1 @@
1
- {"version":3,"file":"gist.d.ts","sourceRoot":"","sources":["../../src/api/gist.js"],"names":[],"mappings":"AAae;;;;;;;;;;;;;;;;GAqFd"}
1
+ {"version":3,"file":"gist.d.ts","sourceRoot":"","sources":["../../src/api/gist.js"],"names":[],"mappings":"AAYe;;;;;;;;;;;;;;;;GAwHd"}
package/build/api/gist.js CHANGED
@@ -1,5 +1,5 @@
1
- // @ts-check
2
1
  import { renderGistCard } from "../cards/gist.js";
2
+ import { findInvalidColor } from "../common/color.js";
3
3
  import { MissingParamError, retrieveSecondaryMessage, } from "../common/error.js";
4
4
  import { parseBoolean } from "../common/ops.js";
5
5
  import { renderError } from "../common/render.js";
@@ -7,6 +7,22 @@ import { fetchGist } from "../fetchers/gist.js";
7
7
  import { isLocaleAvailable } from "../translations.js";
8
8
  // @ts-ignore
9
9
  export default async ({ id, title_color, icon_color, text_color, bg_color, theme, locale, border_radius, border_color, show_owner, browser_rendering, hide_border, }, pat = null) => {
10
+ const invalidColorInput = findInvalidColor({
11
+ title_color,
12
+ icon_color,
13
+ text_color,
14
+ bg_color,
15
+ border_color,
16
+ });
17
+ if (invalidColorInput) {
18
+ return {
19
+ status: "error - permanent",
20
+ content: renderError({
21
+ message: "Something went wrong",
22
+ secondaryMessage: `Invalid color input for parameter "${invalidColorInput}"`,
23
+ }),
24
+ };
25
+ }
10
26
  if (locale && !isLocaleAvailable(locale)) {
11
27
  return {
12
28
  status: "error - permanent",
@@ -23,6 +39,23 @@ export default async ({ id, title_color, icon_color, text_color, bg_color, theme
23
39
  }),
24
40
  };
25
41
  }
42
+ const safePattern = /^[-\w/.,]+$/;
43
+ if (id && !safePattern.test(id)) {
44
+ return {
45
+ status: "error - permanent",
46
+ content: renderError({
47
+ message: "Something went wrong",
48
+ secondaryMessage: "Gist ID contains unsafe characters",
49
+ renderOptions: {
50
+ title_color,
51
+ text_color,
52
+ bg_color,
53
+ border_color,
54
+ theme,
55
+ },
56
+ }),
57
+ };
58
+ }
26
59
  try {
27
60
  const gistData = await fetchGist(id, pat);
28
61
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.js"],"names":[],"mappings":"AAae;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2Kd"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.js"],"names":[],"mappings":"AAYe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6Ld"}
@@ -1,5 +1,5 @@
1
- // @ts-check
2
1
  import { renderStatsCard } from "../cards/stats.js";
2
+ import { findInvalidColor } from "../common/color.js";
3
3
  import { MissingParamError, retrieveSecondaryMessage, } from "../common/error.js";
4
4
  import { parseArray, parseBoolean } from "../common/ops.js";
5
5
  import { renderError } from "../common/render.js";
@@ -7,6 +7,23 @@ import { fetchStats } from "../fetchers/stats.js";
7
7
  import { isLocaleAvailable } from "../translations.js";
8
8
  // @ts-ignore
9
9
  export default async ({ username, repo, owner, hide, hide_title, hide_border, card_width, hide_rank, show_icons, include_all_commits, commits_year, line_height, title_color, ring_color, icon_color, text_color, text_bold, bg_color, theme, exclude_repo, custom_title, locale, disable_animations, border_radius, number_format, role, number_precision, border_color, rank_icon, show, }, pat = null) => {
10
+ const invalidColorInput = findInvalidColor({
11
+ title_color,
12
+ ring_color,
13
+ icon_color,
14
+ text_color,
15
+ bg_color,
16
+ border_color,
17
+ });
18
+ if (invalidColorInput) {
19
+ return {
20
+ status: "error - permanent",
21
+ content: renderError({
22
+ message: "Something went wrong",
23
+ secondaryMessage: `Invalid color input for parameter "${invalidColorInput}"`,
24
+ }),
25
+ };
26
+ }
10
27
  if (locale && !isLocaleAvailable(locale)) {
11
28
  return {
12
29
  status: "error - permanent",
@@ -1 +1 @@
1
- {"version":3,"file":"pin.d.ts","sourceRoot":"","sources":["../../src/api/pin.js"],"names":[],"mappings":"AAae;;;;;;;;;;;;;;;;;;;;;;;;GAoId"}
1
+ {"version":3,"file":"pin.d.ts","sourceRoot":"","sources":["../../src/api/pin.js"],"names":[],"mappings":"AAYe;;;;;;;;;;;;;;;;;;;;;;;;GAqJd"}
package/build/api/pin.js CHANGED
@@ -1,5 +1,5 @@
1
- // @ts-check
2
1
  import { renderRepoCard } from "../cards/repo.js";
2
+ import { findInvalidColor } from "../common/color.js";
3
3
  import { MissingParamError, retrieveSecondaryMessage, } from "../common/error.js";
4
4
  import { parseArray, parseBoolean } from "../common/ops.js";
5
5
  import { renderError } from "../common/render.js";
@@ -7,6 +7,22 @@ import { fetchRepo } from "../fetchers/repo.js";
7
7
  import { isLocaleAvailable } from "../translations.js";
8
8
  // @ts-ignore
9
9
  export default async ({ username, repo, hide_border, title_color, icon_color, text_color, bg_color, card_width, theme, show_owner, browser_rendering, show, show_icons, number_format, text_bold, line_height, locale, border_radius, border_color, description_lines_count, }, pat = null) => {
10
+ const invalidColorInput = findInvalidColor({
11
+ title_color,
12
+ icon_color,
13
+ text_color,
14
+ bg_color,
15
+ border_color,
16
+ });
17
+ if (invalidColorInput) {
18
+ return {
19
+ status: "error - permanent",
20
+ content: renderError({
21
+ message: "Something went wrong",
22
+ secondaryMessage: `Invalid color input for parameter "${invalidColorInput}"`,
23
+ }),
24
+ };
25
+ }
10
26
  if (locale && !isLocaleAvailable(locale)) {
11
27
  return {
12
28
  status: "error - permanent",
@@ -1 +1 @@
1
- {"version":3,"file":"top-langs.d.ts","sourceRoot":"","sources":["../../src/api/top-langs.js"],"names":[],"mappings":"AAae;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0Jd"}
1
+ {"version":3,"file":"top-langs.d.ts","sourceRoot":"","sources":["../../src/api/top-langs.js"],"names":[],"mappings":"AAYe;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2Ld"}
@@ -1,5 +1,5 @@
1
- // @ts-check
2
1
  import { renderTopLanguages } from "../cards/top-languages.js";
2
+ import { findInvalidColor } from "../common/color.js";
3
3
  import { MissingParamError, retrieveSecondaryMessage, } from "../common/error.js";
4
4
  import { parseArray, parseBoolean } from "../common/ops.js";
5
5
  import { renderError } from "../common/render.js";
@@ -7,6 +7,22 @@ import { fetchTopLanguages } from "../fetchers/top-languages.js";
7
7
  import { isLocaleAvailable } from "../translations.js";
8
8
  // @ts-ignore
9
9
  export default async ({ username, hide, hide_title, hide_border, card_width, title_color, text_color, bg_color, prog_bar_bg_color, theme, layout, langs_count, exclude_repo, size_weight, count_weight, custom_title, locale, border_radius, border_color, role, disable_animations, hide_progress, hide_values, stats_format, }, pat = null) => {
10
+ const invalidColorInput = findInvalidColor({
11
+ title_color,
12
+ text_color,
13
+ bg_color,
14
+ prog_bar_bg_color,
15
+ border_color,
16
+ });
17
+ if (invalidColorInput) {
18
+ return {
19
+ status: "error - permanent",
20
+ content: renderError({
21
+ message: "Something went wrong",
22
+ secondaryMessage: `Invalid color input for parameter "${invalidColorInput}"`,
23
+ }),
24
+ };
25
+ }
10
26
  if (locale && !isLocaleAvailable(locale)) {
11
27
  return {
12
28
  status: "error - permanent",
@@ -23,9 +39,25 @@ export default async ({ username, hide, hide_title, hide_border, card_width, tit
23
39
  }),
24
40
  };
25
41
  }
42
+ const safePattern = /^[-\w/.,]+$/;
43
+ if (username && !safePattern.test(username)) {
44
+ return {
45
+ status: "error - permanent",
46
+ content: renderError({
47
+ message: "Something went wrong",
48
+ secondaryMessage: "Username contains unsafe characters",
49
+ renderOptions: {
50
+ title_color,
51
+ text_color,
52
+ bg_color,
53
+ border_color,
54
+ theme,
55
+ },
56
+ }),
57
+ };
58
+ }
26
59
  if (layout !== undefined &&
27
- (typeof layout !== "string" ||
28
- !["compact", "normal", "donut", "donut-vertical", "pie"].includes(layout))) {
60
+ !["compact", "normal", "donut", "donut-vertical", "pie"].includes(layout)) {
29
61
  return {
30
62
  status: "error - permanent",
31
63
  content: renderError({
@@ -42,8 +74,7 @@ export default async ({ username, hide, hide_title, hide_border, card_width, tit
42
74
  };
43
75
  }
44
76
  if (stats_format !== undefined &&
45
- (typeof stats_format !== "string" ||
46
- !["bytes", "percentages"].includes(stats_format))) {
77
+ !["bytes", "percentages"].includes(stats_format)) {
47
78
  return {
48
79
  status: "error - permanent",
49
80
  content: renderError({
@@ -1 +1 @@
1
- {"version":3,"file":"wakatime.d.ts","sourceRoot":"","sources":["../../src/api/wakatime.js"],"names":[],"mappings":"AAae;;;;;;;;;;;;;;;;;;;;;;;;;GAmGd"}
1
+ {"version":3,"file":"wakatime.d.ts","sourceRoot":"","sources":["../../src/api/wakatime.js"],"names":[],"mappings":"AAYe;;;;;;;;;;;;;;;;;;;;;;;;;GAsId"}
@@ -1,5 +1,5 @@
1
- // @ts-check
2
1
  import { renderWakatimeCard } from "../cards/wakatime.js";
2
+ import { findInvalidColor } from "../common/color.js";
3
3
  import { MissingParamError, retrieveSecondaryMessage, } from "../common/error.js";
4
4
  import { parseArray, parseBoolean } from "../common/ops.js";
5
5
  import { renderError } from "../common/render.js";
@@ -7,6 +7,22 @@ import { fetchWakatimeStats } from "../fetchers/wakatime.js";
7
7
  import { isLocaleAvailable } from "../translations.js";
8
8
  // @ts-ignore
9
9
  export default async ({ username, title_color, icon_color, hide_border, card_width, line_height, text_color, bg_color, theme, hide_title, hide_progress, custom_title, locale, layout, langs_count, hide, api_domain, border_radius, border_color, display_format, disable_animations, }) => {
10
+ const invalidColorInput = findInvalidColor({
11
+ title_color,
12
+ icon_color,
13
+ text_color,
14
+ bg_color,
15
+ border_color,
16
+ });
17
+ if (invalidColorInput) {
18
+ return {
19
+ status: "error - permanent",
20
+ content: renderError({
21
+ message: "Something went wrong",
22
+ secondaryMessage: `Invalid color input for parameter "${invalidColorInput}"`,
23
+ }),
24
+ };
25
+ }
10
26
  if (locale && !isLocaleAvailable(locale)) {
11
27
  return {
12
28
  status: "error - permanent",
@@ -23,6 +39,23 @@ export default async ({ username, title_color, icon_color, hide_border, card_wid
23
39
  }),
24
40
  };
25
41
  }
42
+ const safePattern = /^[-\w/.,]+$/;
43
+ if (username && !safePattern.test(username)) {
44
+ return {
45
+ status: "error - permanent",
46
+ content: renderError({
47
+ message: "Something went wrong",
48
+ secondaryMessage: "Username contains unsafe characters",
49
+ renderOptions: {
50
+ title_color,
51
+ text_color,
52
+ bg_color,
53
+ border_color,
54
+ theme,
55
+ },
56
+ }),
57
+ };
58
+ }
26
59
  try {
27
60
  const stats = await fetchWakatimeStats({ username, api_domain });
28
61
  return {
@@ -1,18 +1,18 @@
1
1
  /**
2
2
  * Calculates the users rank.
3
3
  *
4
- * @param {object} params Parameters on which the user's rank depends.
5
- * @param {boolean} params.all_commits Whether `include_all_commits` was used.
6
- * @param {number} params.commits Number of commits.
7
- * @param {number} params.prs The number of pull requests.
8
- * @param {number} params.issues The number of issues.
9
- * @param {number} params.reviews The number of reviews.
10
- * @param {number} params.repos Total number of repos.
11
- * @param {number} params.stars The number of stars.
12
- * @param {number} params.followers The number of followers.
13
- * @returns {{ level: string, percentile: number }} The users rank.
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
+ * @returns The users rank.
14
14
  */
15
- export function calculateRank({ all_commits, commits, prs, issues, reviews, repos, stars, followers, }: {
15
+ declare function calculateRank({ all_commits, commits, prs, issues, reviews, stars, followers, }: {
16
16
  all_commits: boolean;
17
17
  commits: number;
18
18
  prs: number;
@@ -25,4 +25,5 @@ export function calculateRank({ all_commits, commits, prs, issues, reviews, repo
25
25
  level: string;
26
26
  percentile: number;
27
27
  };
28
+ export { calculateRank };
28
29
  //# sourceMappingURL=calculateRank.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"calculateRank.d.ts","sourceRoot":"","sources":["../src/calculateRank.js"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;GAaG;AACH,wGAVG;IAAwB,WAAW,EAA3B,OAAO;IACQ,OAAO,EAAtB,MAAM;IACS,GAAG,EAAlB,MAAM;IACS,MAAM,EAArB,MAAM;IACS,OAAO,EAAtB,MAAM;IACS,KAAK,EAApB,MAAM;IACS,KAAK,EAApB,MAAM;IACS,SAAS,EAAxB,MAAM;CACd,GAAU;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAkDjD"}
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,CAyCxC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Calculates the exponential cdf.
3
3
  *
4
- * @param {number} x The value.
5
- * @returns {number} The exponential cdf.
4
+ * @param x The value.
5
+ * @returns The exponential cdf.
6
6
  */
7
7
  function exponential_cdf(x) {
8
8
  return 1 - 2 ** -x;
@@ -10,8 +10,8 @@ function exponential_cdf(x) {
10
10
  /**
11
11
  * Calculates the log normal cdf.
12
12
  *
13
- * @param {number} x The value.
14
- * @returns {number} The log normal cdf.
13
+ * @param x The value.
14
+ * @returns The log normal cdf.
15
15
  */
16
16
  function log_normal_cdf(x) {
17
17
  // approximation
@@ -20,21 +20,18 @@ function log_normal_cdf(x) {
20
20
  /**
21
21
  * Calculates the users rank.
22
22
  *
23
- * @param {object} params Parameters on which the user's rank depends.
24
- * @param {boolean} params.all_commits Whether `include_all_commits` was used.
25
- * @param {number} params.commits Number of commits.
26
- * @param {number} params.prs The number of pull requests.
27
- * @param {number} params.issues The number of issues.
28
- * @param {number} params.reviews The number of reviews.
29
- * @param {number} params.repos Total number of repos.
30
- * @param {number} params.stars The number of stars.
31
- * @param {number} params.followers The number of followers.
32
- * @returns {{ level: string, percentile: number }} The users rank.
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
+ * @returns The users rank.
33
33
  */
34
- function calculateRank({ all_commits, commits, prs, issues, reviews,
35
- // eslint-disable-next-line no-unused-vars
36
- repos, // unused
37
- stars, followers, }) {
34
+ function calculateRank({ all_commits, commits, prs, issues, reviews, stars, followers, }) {
38
35
  const COMMITS_MEDIAN = all_commits ? 1000 : 250, COMMITS_WEIGHT = 2;
39
36
  const PRS_MEDIAN = 50, PRS_WEIGHT = 3;
40
37
  const ISSUES_MEDIAN = 25, ISSUES_WEIGHT = 1;
@@ -58,6 +55,9 @@ stars, followers, }) {
58
55
  FOLLOWERS_WEIGHT * log_normal_cdf(followers / FOLLOWERS_MEDIAN)) /
59
56
  TOTAL_WEIGHT;
60
57
  const level = LEVELS[THRESHOLDS.findIndex((t) => rank * 100 <= t)];
58
+ if (level === undefined) {
59
+ throw new Error("Unable to determine rank level");
60
+ }
61
61
  return { level, percentile: rank * 100 };
62
62
  }
63
63
  export { calculateRank };
@@ -1 +1 @@
1
- {"version":3,"file":"gist.d.ts","sourceRoot":"","sources":["../../src/cards/gist.js"],"names":[],"mappings":";;;;;;;;AA4BA;;;GAGG;AAEH;;;;;;GAMG;AACH,yCAJW,QAAQ,YACR,OAAO,CAAC,eAAe,CAAC,GACtB,MAAM,CAkJlB"}
1
+ {"version":3,"file":"gist.d.ts","sourceRoot":"","sources":["../../src/cards/gist.js"],"names":[],"mappings":";;;;;;;;AA0BA;;;GAGG;AAEH;;;;;;GAMG;AACH,yCAJW,QAAQ,YACR,OAAO,CAAC,eAAe,CAAC,GACtB,MAAM,CAkJlB"}
@@ -1,4 +1,3 @@
1
- // @ts-check
2
1
  import { default as Card } from "../common/Card.js";
3
2
  import { getCardColors } from "../common/color.js";
4
3
  import { kFormatter, wrapTextMultiline } from "../common/fmt.js";
@@ -1 +1 @@
1
- {"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../src/cards/repo.js"],"names":[],"mappings":";;;;;;;;AAmDA;;;GAGG;AAEH;;;;;;GAMG;AACH,qCAJW,cAAc,YACd,OAAO,CAAC,eAAe,CAAC,GACtB,MAAM,CA6SlB"}
1
+ {"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../src/cards/repo.js"],"names":[],"mappings":";;;;;;;;AA0DA;;;GAGG;AAEH;;;;;;GAMG;AACH,qCAJW,cAAc,YACd,OAAO,CAAC,eAAe,CAAC,GACtB,MAAM,CA8SlB"}
@@ -1,7 +1,6 @@
1
- // @ts-check
2
1
  import { Card } from "../common/Card.js";
3
2
  import { I18n } from "../common/I18n.js";
4
- import { getCardColors } from "../common/color.js";
3
+ import { getCardColors, isPrefixedHexColor } from "../common/color.js";
5
4
  import { kFormatter, wrapTextMultiline } from "../common/fmt.js";
6
5
  import { encodeHTML } from "../common/html.js";
7
6
  import { icons } from "../common/icons.js";
@@ -22,20 +21,28 @@ const DESCRIPTION_MAX_LINES = 3;
22
21
  * @param {string} textColor The color of the text.
23
22
  * @returns {string} Wrapped repo description SVG object.
24
23
  */
25
- const getBadgeSVG = (label, textColor, xOffset = 0) => `
26
- <g data-testid="badge" class="badge" transform="translate(${320 + xOffset}, -18)">
27
- <rect stroke="${textColor}" stroke-width="1" width="70" height="20" x="-12" y="-14" ry="10" rx="10"></rect>
28
- <text
29
- x="23" y="-5"
30
- alignment-baseline="central"
31
- dominant-baseline="central"
32
- text-anchor="middle"
33
- fill="${textColor}"
34
- >
35
- ${label}
36
- </text>
37
- </g>
38
- `;
24
+ const getBadgeSVG = (label, textColor, xOffset = 0) => {
25
+ if (!isPrefixedHexColor(textColor)) {
26
+ throw new Error(`Invalid text color: "${textColor}"`);
27
+ }
28
+ if (!Number.isFinite(xOffset)) {
29
+ throw new Error(`Invalid xOffset: "${xOffset}"`);
30
+ }
31
+ return `
32
+ <g data-testid="badge" class="badge" transform="translate(${320 + xOffset}, -18)">
33
+ <rect stroke="${textColor}" stroke-width="1" width="70" height="20" x="-12" y="-14" ry="10" rx="10"></rect>
34
+ <text
35
+ x="23" y="-5"
36
+ alignment-baseline="central"
37
+ dominant-baseline="central"
38
+ text-anchor="middle"
39
+ fill="${textColor}"
40
+ >
41
+ ${encodeHTML(label)}
42
+ </text>
43
+ </g>
44
+ `;
45
+ };
39
46
  /**
40
47
  * @typedef {import("../fetchers/types").RepositoryData} RepositoryData Repository data.
41
48
  * @typedef {import("./types").RepoCardOptions} RepoCardOptions Repo card options.
@@ -60,6 +67,7 @@ const renderRepoCard = (repo, options = {}) => {
60
67
  translations: repoCardLocales,
61
68
  });
62
69
  let repoFilter = encodeURIComponent(buildSearchFilter([nameWithOwner], []));
70
+ const encodedUsername = encodeURIComponent(username);
63
71
  const STATS = {};
64
72
  if (show.includes("prs_authored")) {
65
73
  STATS.prs_authored = {
@@ -67,7 +75,7 @@ const renderRepoCard = (repo, options = {}) => {
67
75
  label: i18n.t("repocard.prs-authored"),
68
76
  value: totalPRsAuthored,
69
77
  id: "prs_authored",
70
- link: `https://github.com/search?q=${repoFilter}author%3A${username}&amp;type=pullrequests`,
78
+ link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&amp;type=pullrequests`,
71
79
  };
72
80
  }
73
81
  if (show.includes("prs_commented")) {
@@ -76,7 +84,7 @@ const renderRepoCard = (repo, options = {}) => {
76
84
  label: i18n.t("repocard.prs-commented"),
77
85
  value: totalPRsCommented,
78
86
  id: "prs_commented",
79
- link: `https://github.com/search?q=${repoFilter}commenter%3A${username}+-author%3A${username}&amp;type=pullrequests`,
87
+ link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=pullrequests`,
80
88
  };
81
89
  }
82
90
  if (show.includes("prs_reviewed")) {
@@ -85,7 +93,7 @@ const renderRepoCard = (repo, options = {}) => {
85
93
  label: i18n.t("repocard.prs-reviewed"),
86
94
  value: totalPRsReviewed,
87
95
  id: "prs_reviewed",
88
- link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${username}+-author%3A${username}&amp;type=pullrequests`,
96
+ link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=pullrequests`,
89
97
  };
90
98
  }
91
99
  if (show.includes("issues_authored")) {
@@ -94,7 +102,7 @@ const renderRepoCard = (repo, options = {}) => {
94
102
  label: i18n.t("repocard.issues-authored"),
95
103
  value: totalIssuesAuthored,
96
104
  id: "issues_authored",
97
- link: `https://github.com/search?q=${repoFilter}author%3A${username}&amp;type=issues`,
105
+ link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&amp;type=issues`,
98
106
  };
99
107
  }
100
108
  if (show.includes("issues_commented")) {
@@ -103,7 +111,7 @@ const renderRepoCard = (repo, options = {}) => {
103
111
  label: i18n.t("repocard.issues-commented"),
104
112
  value: totalIssuesCommented,
105
113
  id: "issues_commented",
106
- link: `https://github.com/search?q=${repoFilter}commenter%3A${username}+-author%3A${username}&amp;type=issues`,
114
+ link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=issues`,
107
115
  };
108
116
  }
109
117
  const statItems = Object.keys(STATS).map((key, index) =>
@@ -15,8 +15,10 @@ export function renderStatsCard(stats: StatsData, options: Partial<StatCardOptio
15
15
  /**
16
16
  * Create a stats card text item.
17
17
  *
18
+ * The caller must ensure that the passed `icon` and `link` are properly sanitized!
19
+ *
18
20
  * @param {object} params Object that contains the createTextNode parameters.
19
- * @param {string} params.icon The icon to display.
21
+ * @param {string} params.icon The sanitized icon to display.
20
22
  * @param {string} params.label The label to display.
21
23
  * @param {number} params.value The value to display.
22
24
  * @param {string} params.id The id of the stat.
@@ -27,7 +29,7 @@ export function renderStatsCard(stats: StatsData, options: Partial<StatCardOptio
27
29
  * @param {boolean} params.bold Whether to bold the label.
28
30
  * @param {string} params.numberFormat The format of numbers on card.
29
31
  * @param {number=} params.numberPrecision The precision of numbers on card.
30
- * @param {string} params.link Url to link to.
32
+ * @param {string} params.link Sanitized url to link to.
31
33
  * @param {number} params.labelXOffset horizontal offset for label.
32
34
  * @returns {string} The stats card text item SVG object.
33
35
  */
@@ -1 +1 @@
1
- {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/cards/stats.js"],"names":[],"mappings":";;AA8PA;;;GAGG;AAEH;;;;;;GAMG;AACH,uCAJW,SAAS,WACT,OAAO,CAAC,eAAe,CAAC,+CACtB,MAAM,CAsZlB;AAzmBD;;;;;;;;;;;;;;;;;;GAkBG;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,CAuDlB"}
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,9 +1,9 @@
1
- // @ts-check
2
1
  import { Card } from "../common/Card.js";
3
2
  import { I18n } from "../common/I18n.js";
4
3
  import { getCardColors } from "../common/color.js";
5
4
  import { CustomError } from "../common/error.js";
6
5
  import { kFormatter } from "../common/fmt.js";
6
+ import { encodeHTML } from "../common/html.js";
7
7
  import { icons, rankIcon } from "../common/icons.js";
8
8
  import { buildSearchFilter, clampValue } from "../common/ops.js";
9
9
  import { flexLayout, measureText } from "../common/render.js";
@@ -50,8 +50,10 @@ const LONG_LOCALES = [
50
50
  /**
51
51
  * Create a stats card text item.
52
52
  *
53
+ * The caller must ensure that the passed `icon` and `link` are properly sanitized!
54
+ *
53
55
  * @param {object} params Object that contains the createTextNode parameters.
54
- * @param {string} params.icon The icon to display.
56
+ * @param {string} params.icon The sanitized icon to display.
55
57
  * @param {string} params.label The label to display.
56
58
  * @param {number} params.value The value to display.
57
59
  * @param {string} params.id The id of the stat.
@@ -62,11 +64,20 @@ const LONG_LOCALES = [
62
64
  * @param {boolean} params.bold Whether to bold the label.
63
65
  * @param {string} params.numberFormat The format of numbers on card.
64
66
  * @param {number=} params.numberPrecision The precision of numbers on card.
65
- * @param {string} params.link Url to link to.
67
+ * @param {string} params.link Sanitized url to link to.
66
68
  * @param {number} params.labelXOffset horizontal offset for label.
67
69
  * @returns {string} The stats card text item SVG object.
68
70
  */
69
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
+ }
70
81
  const precision = typeof numberPrecision === "number" && !isNaN(numberPrecision)
71
82
  ? clampValue(numberPrecision, 0, 2)
72
83
  : undefined;
@@ -87,7 +98,7 @@ const createTextNode = ({ icon, label, value, id, unitSymbol, index, showIcons,
87
98
  (link ? `<a href="${link}">` : "") +
88
99
  `
89
100
  ${iconSvg}
90
- <text class="stat ${bold ? " bold" : "not_bold"}" ${labelOffset} y="12.5">${label}:</text>
101
+ <text class="stat ${bold ? " bold" : "not_bold"}" ${labelOffset} y="12.5">${encodeHTML(label)}:</text>
91
102
  <text
92
103
  class="stat ${bold ? " bold" : "not_bold"}"
93
104
  x="${(showIcons ? 140 : 120) + (bold ? 5 : 0) + shiftValuePos}"
@@ -316,13 +327,14 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
316
327
  };
317
328
  }
318
329
  let repoFilter = encodeURIComponent(buildSearchFilter(repo, owner));
330
+ const encodedUsername = encodeURIComponent(username);
319
331
  if (show.includes("prs_authored")) {
320
332
  STATS.prs_authored = {
321
333
  icon: icons.prs,
322
334
  label: i18n.t("statcard.prs-authored"),
323
335
  value: totalPRsAuthored,
324
336
  id: "prs_authored",
325
- link: `https://github.com/search?q=${repoFilter}author%3A${username}&amp;type=pullrequests`,
337
+ link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&amp;type=pullrequests`,
326
338
  };
327
339
  }
328
340
  if (show.includes("prs_commented")) {
@@ -331,7 +343,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
331
343
  label: i18n.t("statcard.prs-commented"),
332
344
  value: totalPRsCommented,
333
345
  id: "prs_commented",
334
- link: `https://github.com/search?q=${repoFilter}commenter%3A${username}+-author%3A${username}&amp;type=pullrequests`,
346
+ link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=pullrequests`,
335
347
  };
336
348
  }
337
349
  if (show.includes("prs_reviewed")) {
@@ -340,7 +352,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
340
352
  label: i18n.t("statcard.prs-reviewed"),
341
353
  value: totalPRsReviewed,
342
354
  id: "prs_reviewed",
343
- link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${username}+-author%3A${username}&amp;type=pullrequests`,
355
+ link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=pullrequests`,
344
356
  };
345
357
  }
346
358
  if (show.includes("issues_authored")) {
@@ -349,7 +361,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
349
361
  label: i18n.t("statcard.issues-authored"),
350
362
  value: totalIssuesAuthored,
351
363
  id: "issues_authored",
352
- link: `https://github.com/search?q=${repoFilter}author%3A${username}&amp;type=issues`,
364
+ link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&amp;type=issues`,
353
365
  };
354
366
  }
355
367
  if (show.includes("issues_commented")) {
@@ -358,7 +370,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
358
370
  label: i18n.t("statcard.issues-commented"),
359
371
  value: totalIssuesCommented,
360
372
  id: "issues_commented",
361
- link: `https://github.com/search?q=${repoFilter}commenter%3A${username}+-author%3A${username}&amp;type=issues`,
373
+ link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=issues`,
362
374
  };
363
375
  }
364
376
  STATS.contribs = {
@@ -1 +1 @@
1
- {"version":3,"file":"top-languages.d.ts","sourceRoot":"","sources":["../../src/cards/top-languages.js"],"names":[],"mappings":";;qBAswBa,cAAc,CAAC,QAAQ,CAAC;;AA3uBrC;;GAEG;AAEH;;;;;GAKG;AACH,oCAHW,IAAI,EAAE,GACJ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAOvD;AAEH;;;;;GAKG;AACH,iDAHW,MAAM,GACJ,MAAM,CAE4D;AAE/E;;;;;GAKG;AACH,iDAHW,MAAM,GACJ,MAAM,CAE4D;AAE/E;;;;;;;;GAQG;AACH,0CANW,MAAM,WACN,MAAM,UACN,MAAM,kBACN,MAAM,GACJ;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAC,CAQlC;AAED;;;;;;;;GAQG;AACH,0CANW,MAAM,WACN,MAAM,KACN,MAAM,KACN,MAAM,GACJ;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAC,CASpD;AAED;;;;;GAKG;AACH,wCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,yDAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,wDAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,uDAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,+DAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,qDAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,mDAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;GAOG;AACH,2CALW,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,eACpB,MAAM,SACN,MAAM,EAAE,YAAC,GACP;IAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CA4BxD;AA0mBD;;GAEG;AAEH;;;;;;GAMG;AACH,6CAJW,WAAW,YACX,OAAO,CAAC,cAAc,CAAC,GACrB,MAAM,CAkLlB;AA59BD,6BAAuB,GAAG,CAAC;AA2wB3B;;;;;;;GAOG;AACH,4EAJG;IAAuB,MAAM,GAArB,MAAM,YAAC;IACS,aAAa,GAA7B,OAAO,YAAC;CAChB,GAAU,MAAM,CAclB"}
1
+ {"version":3,"file":"top-languages.d.ts","sourceRoot":"","sources":["../../src/cards/top-languages.js"],"names":[],"mappings":";;qBAsyBa,cAAc,CAAC,QAAQ,CAAC;;AAxwBrC;;GAEG;AAEH;;;;;GAKG;AACH,oCAHW,IAAI,EAAE,GACJ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAOvD;AAEH;;;;;GAKG;AACH,iDAHW,MAAM,GACJ,MAAM,CAE4D;AAE/E;;;;;GAKG;AACH,iDAHW,MAAM,GACJ,MAAM,CAE4D;AAE/E;;;;;;;;GAQG;AACH,0CANW,MAAM,WACN,MAAM,UACN,MAAM,kBACN,MAAM,GACJ;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAC,CAQlC;AAED;;;;;;;;GAQG;AACH,0CANW,MAAM,WACN,MAAM,KACN,MAAM,KACN,MAAM,GACJ;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAC,CASpD;AAED;;;;;GAKG;AACH,wCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,yDAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,wDAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,uDAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,+DAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,qDAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,mDAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;GAOG;AACH,2CALW,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,eACpB,MAAM,SACN,MAAM,EAAE,YAAC,GACP;IAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CA4BxD;AA2oBD;;GAEG;AAEH;;;;;;GAMG;AACH,6CAJW,WAAW,YACX,OAAO,CAAC,cAAc,CAAC,GACrB,MAAM,CAkLlB;AA7/BD,6BAAuB,GAAG,CAAC;AA4yB3B;;;;;;;GAOG;AACH,4EAJG;IAAuB,MAAM,GAArB,MAAM,YAAC;IACS,aAAa,GAA7B,OAAO,YAAC;CAChB,GAAU,MAAM,CAclB"}