@stats-forge/github-stats-forge-core 0.0.1 → 0.1.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 (208) 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/gist.d.ts +3 -10
  6. package/build/api/gist.d.ts.map +1 -1
  7. package/build/api/gist.js +4 -11
  8. package/build/api/index.d.ts +12 -12
  9. package/build/api/params.d.ts +11 -8
  10. package/build/api/params.d.ts.map +1 -1
  11. package/build/api/params.js +16 -14
  12. package/build/api/pin.d.ts +3 -19
  13. package/build/api/pin.d.ts.map +1 -1
  14. package/build/api/pin.js +6 -22
  15. package/build/api/stats.d.ts +10 -4
  16. package/build/api/stats.d.ts.map +1 -1
  17. package/build/api/stats.js +6 -32
  18. package/build/api/top-langs.d.ts +12 -6
  19. package/build/api/top-langs.d.ts.map +1 -1
  20. package/build/api/top-langs.js +6 -26
  21. package/build/api/wakatime.d.ts +13 -5
  22. package/build/api/wakatime.d.ts.map +1 -1
  23. package/build/api/wakatime.js +4 -21
  24. package/build/calculateRank.d.ts +0 -9
  25. package/build/calculateRank.d.ts.map +1 -1
  26. package/build/calculateRank.js +12 -17
  27. package/build/cards/gist.d.ts +2 -4
  28. package/build/cards/gist.d.ts.map +1 -1
  29. package/build/cards/gist.js +27 -36
  30. package/build/cards/options.d.ts +1 -1
  31. package/build/cards/repo.d.ts +2 -4
  32. package/build/cards/repo.d.ts.map +1 -1
  33. package/build/cards/repo.js +61 -93
  34. package/build/cards/stats.d.ts +3 -8
  35. package/build/cards/stats.d.ts.map +1 -1
  36. package/build/cards/stats.js +119 -165
  37. package/build/cards/top-languages.d.ts +5 -31
  38. package/build/cards/top-languages.d.ts.map +1 -1
  39. package/build/cards/top-languages.js +176 -384
  40. package/build/cards/wakatime.d.ts +4 -6
  41. package/build/cards/wakatime.d.ts.map +1 -1
  42. package/build/cards/wakatime.js +118 -185
  43. package/build/common/Card.d.ts +14 -62
  44. package/build/common/Card.d.ts.map +1 -1
  45. package/build/common/Card.js +97 -199
  46. package/build/common/I18n.d.ts +0 -6
  47. package/build/common/I18n.d.ts.map +1 -1
  48. package/build/common/I18n.js +3 -6
  49. package/build/common/color.d.ts +4 -17
  50. package/build/common/color.d.ts.map +1 -1
  51. package/build/common/color.js +67 -49
  52. package/build/common/config.d.ts +4 -14
  53. package/build/common/config.d.ts.map +1 -1
  54. package/build/common/config.js +3 -16
  55. package/build/common/constants.d.ts +4 -2
  56. package/build/common/constants.d.ts.map +1 -1
  57. package/build/common/constants.js +3 -1
  58. package/build/common/date.d.ts +0 -2
  59. package/build/common/date.d.ts.map +1 -1
  60. package/build/common/date.js +0 -2
  61. package/build/common/emojiMap.d.ts +8 -0
  62. package/build/common/emojiMap.d.ts.map +1 -0
  63. package/build/common/emojiMap.js +10 -0
  64. package/build/common/emojiMap.json +1915 -0
  65. package/build/common/error.d.ts +1 -10
  66. package/build/common/error.d.ts.map +1 -1
  67. package/build/common/error.js +1 -10
  68. package/build/common/fmt.d.ts +3 -15
  69. package/build/common/fmt.d.ts.map +1 -1
  70. package/build/common/fmt.js +7 -35
  71. package/build/common/http.d.ts +2 -7
  72. package/build/common/http.d.ts.map +1 -1
  73. package/build/common/http.js +8 -17
  74. package/build/common/icons.d.ts +18 -20
  75. package/build/common/icons.d.ts.map +1 -1
  76. package/build/common/icons.js +103 -67
  77. package/build/common/languageColors.d.ts +0 -1
  78. package/build/common/languageColors.d.ts.map +1 -1
  79. package/build/common/languageColors.js +1 -4
  80. package/build/common/languageColors.json +18 -2
  81. package/build/common/ops.d.ts +3 -14
  82. package/build/common/ops.d.ts.map +1 -1
  83. package/build/common/ops.js +19 -30
  84. package/build/common/render.d.ts +28 -82
  85. package/build/common/render.d.ts.map +1 -1
  86. package/build/common/render.js +175 -211
  87. package/build/common/retryer.d.ts +2 -7
  88. package/build/common/retryer.d.ts.map +1 -1
  89. package/build/common/retryer.js +4 -11
  90. package/build/fetchers/gist.d.ts +2 -5
  91. package/build/fetchers/gist.d.ts.map +1 -1
  92. package/build/fetchers/gist.js +1 -5
  93. package/build/fetchers/index.d.ts +12 -12
  94. package/build/fetchers/repo.d.ts +2 -11
  95. package/build/fetchers/repo.d.ts.map +1 -1
  96. package/build/fetchers/repo.js +20 -33
  97. package/build/fetchers/stats.d.ts +2 -32
  98. package/build/fetchers/stats.d.ts.map +1 -1
  99. package/build/fetchers/stats.js +27 -86
  100. package/build/fetchers/top-languages.d.ts +2 -9
  101. package/build/fetchers/top-languages.d.ts.map +1 -1
  102. package/build/fetchers/top-languages.js +15 -31
  103. package/build/fetchers/types.d.ts +1 -1
  104. package/build/fetchers/wakatime.d.ts +2 -6
  105. package/build/fetchers/wakatime.d.ts.map +1 -1
  106. package/build/fetchers/wakatime.js +1 -5
  107. package/build/graphql/contributionsDocument.d.ts +3 -3
  108. package/build/graphql/contributionsDocument.d.ts.map +1 -1
  109. package/build/graphql/contributionsDocument.js +0 -1
  110. package/build/graphql/generated/gist.d.ts +1 -1
  111. package/build/graphql/generated/repo.d.ts +1 -1
  112. package/build/graphql/generated/stats.d.ts +3 -3
  113. package/build/graphql/generated/top-languages.d.ts +2 -2
  114. package/build/graphql/graphqlDocument.d.ts +0 -1
  115. package/build/graphql/graphqlDocument.d.ts.map +1 -1
  116. package/build/graphql/graphqlDocument.js +0 -1
  117. package/build/graphql/reposContributedToDocument.d.ts +4 -5
  118. package/build/graphql/reposContributedToDocument.d.ts.map +1 -1
  119. package/build/graphql/reposContributedToDocument.js +0 -2
  120. package/build/markup/css.d.ts +35 -0
  121. package/build/markup/css.d.ts.map +1 -0
  122. package/build/markup/css.js +64 -0
  123. package/build/markup/element.d.ts +41 -0
  124. package/build/markup/element.d.ts.map +1 -0
  125. package/build/markup/element.js +127 -0
  126. package/build/markup/html.d.ts +13 -0
  127. package/build/markup/html.d.ts.map +1 -0
  128. package/build/markup/html.js +27 -0
  129. package/build/markup/index.d.ts +9 -0
  130. package/build/markup/index.d.ts.map +1 -0
  131. package/build/markup/index.js +6 -0
  132. package/build/markup/serialize.d.ts +16 -0
  133. package/build/markup/serialize.d.ts.map +1 -0
  134. package/build/markup/serialize.js +17 -0
  135. package/build/themes/index.d.ts +332 -333
  136. package/build/themes/index.d.ts.map +1 -1
  137. package/build/themes/index.js +1 -1
  138. package/build/translations.d.ts +2 -6
  139. package/build/translations.d.ts.map +1 -1
  140. package/build/translations.js +621 -628
  141. package/package.json +17 -26
  142. package/src/api/api-result.ts +10 -9
  143. package/src/api/gist.ts +11 -18
  144. package/src/api/index.ts +12 -12
  145. package/src/api/params.ts +27 -21
  146. package/src/api/pin.ts +13 -28
  147. package/src/api/stats.ts +13 -39
  148. package/src/api/top-langs.ts +13 -33
  149. package/src/api/wakatime.ts +11 -28
  150. package/src/calculateRank.ts +12 -23
  151. package/src/cards/gist.ts +40 -43
  152. package/src/cards/options.ts +1 -1
  153. package/src/cards/repo.ts +97 -107
  154. package/src/cards/stats.ts +165 -184
  155. package/src/cards/top-languages.ts +297 -413
  156. package/src/cards/wakatime.ts +193 -221
  157. package/src/common/Card.ts +165 -217
  158. package/src/common/I18n.ts +3 -6
  159. package/src/common/color.ts +80 -57
  160. package/src/common/config.ts +5 -18
  161. package/src/common/constants.ts +5 -2
  162. package/src/common/date.ts +0 -2
  163. package/src/common/emojiMap.json +1915 -0
  164. package/src/common/emojiMap.ts +13 -0
  165. package/src/common/error.ts +2 -11
  166. package/src/common/fmt.ts +7 -44
  167. package/src/common/http.ts +9 -15
  168. package/src/common/icons.ts +117 -42
  169. package/src/common/languageColors.json +18 -2
  170. package/src/common/languageColors.ts +1 -4
  171. package/src/common/ops.ts +26 -34
  172. package/src/common/render.ts +279 -232
  173. package/src/common/retryer.ts +8 -15
  174. package/src/fetchers/gist.ts +8 -12
  175. package/src/fetchers/index.ts +12 -12
  176. package/src/fetchers/repo.ts +27 -40
  177. package/src/fetchers/stats.ts +44 -102
  178. package/src/fetchers/top-languages.ts +26 -40
  179. package/src/fetchers/types.ts +1 -1
  180. package/src/fetchers/wakatime.ts +5 -9
  181. package/src/graphql/contributionsDocument.ts +7 -5
  182. package/src/graphql/generated/gist.ts +1 -1
  183. package/src/graphql/generated/repo.ts +1 -1
  184. package/src/graphql/generated/stats.ts +2 -2
  185. package/src/graphql/generated/top-languages.ts +2 -2
  186. package/src/graphql/graphqlDocument.ts +0 -1
  187. package/src/graphql/reposContributedToDocument.ts +6 -7
  188. package/src/markup/css.ts +118 -0
  189. package/src/markup/element.ts +246 -0
  190. package/src/markup/html.ts +34 -0
  191. package/src/markup/index.ts +9 -0
  192. package/src/markup/serialize.ts +27 -0
  193. package/src/themes/index.ts +1 -1
  194. package/src/translations.ts +622 -629
  195. package/build/cards/index.d.ts +0 -11
  196. package/build/cards/index.d.ts.map +0 -1
  197. package/build/cards/index.js +0 -7
  198. package/build/common/html.d.ts +0 -8
  199. package/build/common/html.d.ts.map +0 -1
  200. package/build/common/html.js +0 -14
  201. package/build/index.d.ts +0 -15
  202. package/build/index.d.ts.map +0 -1
  203. package/build/index.js +0 -10
  204. package/src/_emoji-name-map.d.ts +0 -10
  205. package/src/_github-username-regex.d.ts +0 -4
  206. package/src/cards/index.ts +0 -21
  207. package/src/common/html.ts +0 -17
  208. package/src/index.ts +0 -18
@@ -1,10 +1,10 @@
1
- import type { WakaTimeData } from '../fetchers/types.js';
2
- import type { CardOptions, CommonCardOptions } from './options.js';
1
+ import type { WakaTimeData } from '../fetchers/types.ts';
2
+ import type { CardOptions, CommonCardOptions } from './options.ts';
3
3
  /** Layouts the card can draw; the api validates `layout` against this. */
4
- declare const WAKATIME_LAYOUTS: readonly ["compact", "normal"];
4
+ declare const WAKATIME_LAYOUTS: readonly ['compact', 'normal'];
5
5
  type WakaTimeLayout = (typeof WAKATIME_LAYOUTS)[number];
6
6
  /** How a language's time is written; the api validates `display_format` against this. */
7
- declare const DISPLAY_FORMATS: readonly ["time", "percent"];
7
+ declare const DISPLAY_FORMATS: readonly ['time', 'percent'];
8
8
  type DisplayFormat = (typeof DISPLAY_FORMATS)[number];
9
9
  interface WakaTimeOptions extends CommonCardOptions {
10
10
  locale: string;
@@ -22,8 +22,6 @@ interface WakaTimeOptions extends CommonCardOptions {
22
22
  /**
23
23
  * Renders WakaTime card.
24
24
  *
25
- * @param stats WakaTime stats.
26
- * @param options Card options.
27
25
  * @returns WakaTime card SVG.
28
26
  */
29
27
  declare const renderWakatimeCard: (stats?: Partial<WakaTimeData>, options?: CardOptions<WakaTimeOptions>) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"wakatime.d.ts","sourceRoot":"","sources":["../../src/cards/wakatime.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,sBAAsB,CAAC;AAGvE,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAWnE,0EAA0E;AAC1E,QAAA,MAAM,gBAAgB,gCAAiC,CAAC;AACxD,KAAK,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD,yFAAyF;AACzF,QAAA,MAAM,eAAe,8BAA+B,CAAC;AACrD,KAAK,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,UAAU,eAAgB,SAAQ,iBAAiB;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,aAAa,CAAC;IAC9B,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AA4OD;;;;;;GAMG;AACH,QAAA,MAAM,kBAAkB,GACtB,QAAO,OAAO,CAAC,YAAY,CAAM,EACjC,UAAS,WAAW,CAAC,eAAe,CAAgB,KACnD,MAmNF,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"wakatime.d.ts","sourceRoot":"","sources":["../../src/cards/wakatime.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,sBAAsB,CAAC;AAKvE,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAWnE,0EAA0E;AAC1E,QAAA,MAAM,gBAAgB,YAAI,SAAS,EAAE,QAAQ,CAAU,CAAC;AACxD,KAAK,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD,yFAAyF;AACzF,QAAA,MAAM,eAAe,YAAI,MAAM,EAAE,SAAS,CAAU,CAAC;AACrD,KAAK,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,UAAU,eAAgB,SAAQ,iBAAiB;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,aAAa,CAAC;IAC9B,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAoND;;;;GAIG;AACH,QAAA,MAAM,kBAAkB,WACf,OAAO,CAAC,YAAY,CAAC,YACnB,WAAW,CAAC,eAAe,CAAC,KACpC,MAgNF,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,CAAC"}
@@ -1,10 +1,10 @@
1
1
  import { Card } from '../common/Card.js';
2
2
  import { getLightDarkColors, isPrefixedHexColor } from '../common/color.js';
3
- import { encodeHTML } from '../common/html.js';
4
3
  import { I18n } from '../common/I18n.js';
5
4
  import { getLanguageColor } from '../common/languageColors.js';
6
5
  import { clampValue, lowercaseTrim } from '../common/ops.js';
7
6
  import { createProgressNode, flexLayout } from '../common/render.js';
7
+ import { atRule, cssComment, el, rule } from '../markup/index.js';
8
8
  import { wakatimeCardLocales } from '../translations.js';
9
9
  const DEFAULT_CARD_WIDTH = 495;
10
10
  const MIN_CARD_WIDTH = 250;
@@ -21,62 +21,34 @@ const DISPLAY_FORMATS = ['time', 'percent'];
21
21
  /**
22
22
  * Creates the no coding activity SVG node.
23
23
  *
24
- * @param props The function properties.
25
- * @param props.text No coding activity translated text.
26
24
  * @returns No coding activity SVG node string.
27
25
  */
28
- const noCodingActivityNode = ({ text }) => {
29
- return `
30
- <text x="25" y="11" class="stat bold">${encodeHTML(text)}</text>
31
- `;
32
- };
26
+ const noCodingActivityNode = ({ text }) => el('text', { x: 25, y: 11, class: 'stat bold' }, text);
33
27
  /**
34
28
  * Format language value.
35
29
  *
36
- * @param args The function arguments.
37
- * @param args.lang The language object.
38
- * @param args.display_format The display format of the language node.
39
30
  * @returns The formatted language value.
40
31
  */
41
- const formatLanguageValue = ({ display_format, lang, }) => {
42
- return display_format === 'percent' ? `${lang.percent.toFixed(2)} %` : lang.text;
43
- };
32
+ const formatLanguageValue = ({ display_format, lang, }) => (display_format === 'percent' ? `${lang.percent.toFixed(2)} %` : lang.text);
44
33
  /**
45
34
  * Create compact WakaTime layout.
46
35
  *
47
- * @param args The function arguments.
48
- * @param args.lang The languages array.
49
- * @param args.x The x position of the language node.
50
- * @param args.y The y position of the language node.
51
- * @param args.display_format The display format of the language node.
52
36
  * @returns The compact layout language SVG node.
53
37
  */
54
38
  const createCompactLangNode = ({ lang, x, y, display_format, }) => {
55
39
  if (!Number.isFinite(x)) {
56
- throw new Error(`Invalid x: "${x}"`);
40
+ throw new TypeError(`Invalid x: "${x}"`);
57
41
  }
58
42
  if (!Number.isFinite(y)) {
59
- throw new Error(`Invalid y: "${y}"`);
43
+ throw new TypeError(`Invalid y: "${y}"`);
60
44
  }
61
45
  const color = getLanguageColor(lang.name);
62
46
  const value = formatLanguageValue({ display_format, lang });
63
- return `
64
- <g transform="translate(${x}, ${y})">
65
- <circle cx="5" cy="6" r="5" fill="${color}" />
66
- <text data-testid="lang-name" x="15" y="10" class='lang-name'>
67
- ${encodeHTML(lang.name)} - ${encodeHTML(value)}
68
- </text>
69
- </g>
70
- `;
47
+ return el('g', { transform: `translate(${x}, ${y})` }, el('circle', { cx: 5, cy: 6, r: 5, fill: color }), el('text', { 'data-testid': 'lang-name', x: 15, y: 10, class: 'lang-name' }, `${lang.name} - ${value}`));
71
48
  };
72
49
  /**
73
50
  * Create WakaTime language text node item.
74
51
  *
75
- * @param args The function arguments.
76
- * @param args.langs The language objects.
77
- * @param args.y The y position of the language node.
78
- * @param args.display_format The display format of the language node.
79
- * @param args.card_width Width in px of the card.
80
52
  * @returns The language text node items.
81
53
  */
82
54
  const createLanguageTextNode = ({ langs, y, display_format, card_width, }) => {
@@ -97,95 +69,73 @@ const createLanguageTextNode = ({ langs, y, display_format, card_width, }) => {
97
69
  /**
98
70
  * Create WakaTime text item.
99
71
  *
100
- * @param args The function arguments.
101
- * @param args.id The id of the text node item.
102
- * @param args.label The label of the text node item.
103
- * @param args.value The value of the text node item.
104
- * @param args.index The index of the text node item.
105
- * @param args.percent Percentage of the text node item.
106
- * @param args.hideProgress Whether to hide the progress bar.
107
- * @param args.progressBarWidth The width of the progress bar.
108
72
  * @returns The text SVG node.
109
73
  */
110
74
  const createTextNode = ({ id, label, value, index, percent, hideProgress, progressBarWidth, }) => {
111
75
  if (!Number.isFinite(index)) {
112
- throw new Error(`Invalid index: "${index}"`);
76
+ throw new TypeError(`Invalid index: "${index}"`);
113
77
  }
114
78
  if (!Number.isFinite(progressBarWidth)) {
115
- throw new Error(`Invalid progressBarWidth: "${progressBarWidth}"`);
79
+ throw new TypeError(`Invalid progressBarWidth: "${progressBarWidth}"`);
116
80
  }
117
81
  const staggerDelay = (index + 3) * 150;
118
- const cardProgress = hideProgress
119
- ? null
120
- : createProgressNode({
82
+ return el('g', {
83
+ class: 'stagger',
84
+ style: `animation-delay: ${staggerDelay}ms`,
85
+ transform: 'translate(25, 0)',
86
+ }, el('text', { class: 'stat bold', y: 12.5, 'data-testid': id }, `${label}:`), el('text', {
87
+ class: 'stat',
88
+ x: hideProgress ? HIDDEN_PROGRESSBAR_PADDING : PROGRESSBAR_PADDING + progressBarWidth,
89
+ y: 12.5,
90
+ }, value), !hideProgress &&
91
+ createProgressNode({
121
92
  x: 110,
122
93
  y: 4,
123
94
  progress: percent,
124
95
  width: progressBarWidth,
125
96
  delay: staggerDelay + 300,
126
- });
127
- return `
128
- <g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">
129
- <text class="stat bold" y="12.5" data-testid="${encodeHTML(id)}">${encodeHTML(label)}:</text>
130
- <text
131
- class="stat"
132
- x="${hideProgress ? HIDDEN_PROGRESSBAR_PADDING : PROGRESSBAR_PADDING + progressBarWidth}"
133
- y="12.5"
134
- >${encodeHTML(value)}</text>
135
- ${String(cardProgress)}
136
- </g>
137
- `;
97
+ }));
138
98
  };
139
99
  /**
140
100
  * Recalculating percentages so that, compact layout's progress bar does not break when
141
101
  * hiding languages.
142
- *
143
- * @param languages The languages array.
144
102
  */
145
103
  const recalculatePercentages = (languages) => {
146
- const totalSum = languages.reduce((totalSum, language) => totalSum + language.percent, 0);
147
- const weight = +(100 / totalSum).toFixed(2);
148
- languages.forEach((language) => {
149
- language.percent = +(language.percent * weight).toFixed(2);
150
- });
104
+ const totalSum = languages.reduce((sum, language) => sum + language.percent, 0);
105
+ const weight = Number((100 / totalSum).toFixed(2));
106
+ for (const language of languages) {
107
+ language.percent = Number((language.percent * weight).toFixed(2));
108
+ }
151
109
  };
152
110
  /**
153
111
  * Retrieves CSS styles for a card.
154
112
  *
155
- * @param colors The colors to use for the card.
156
- * @param colors.textColor The text color.
157
113
  * @returns Card CSS styles.
158
114
  */
159
115
  const getStyles = ({ textColor }) => {
160
116
  if (!isPrefixedHexColor(textColor)) {
161
117
  throw new Error(`Invalid text color: "${textColor}"`);
162
118
  }
163
- return `
164
- .stat {
165
- font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${textColor};
166
- }
167
- @supports(-moz-appearance: auto) {
168
- /* Selector detects Firefox */
169
- .stat { font-size:12px; }
170
- }
171
- .stagger {
172
- opacity: 0;
173
- animation: fadeInAnimation 0.3s ease-in-out forwards;
174
- }
175
- .not_bold { font-weight: 400 }
176
- .bold { font-weight: 700 }
177
- `;
119
+ return [
120
+ rule('.stat', {
121
+ font: `600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif`,
122
+ fill: textColor,
123
+ }),
124
+ atRule('@supports(-moz-appearance: auto)', cssComment('Selector detects Firefox'), rule('.stat', { 'font-size': '12px' })),
125
+ rule('.stagger', { opacity: 0, animation: 'fadeInAnimation 0.3s ease-in-out forwards' }),
126
+ rule('.not_bold', { 'font-weight': 400 }),
127
+ rule('.bold', { 'font-weight': 700 }),
128
+ ];
178
129
  };
130
+ /** A bar the same color as the text behind it would be invisible, so it goes transparent. */
131
+ const progressBackground = (titleColor, textColor) => textColor === titleColor ? '#fff0' : textColor;
179
132
  /**
180
133
  * Normalize incoming width (string or number) and clamp to minimum.
181
134
  *
182
- * @param args The function arguments.
183
- * @param args.layout The incoming layout value.
184
- * @param args.value The incoming width value.
185
135
  * @returns The normalized width value.
186
136
  */
187
137
  const normalizeCardWidth = ({ value, layout, }) => {
188
- if (value === undefined || isNaN(value)) {
138
+ if (value === undefined || Number.isNaN(value)) {
189
139
  return DEFAULT_CARD_WIDTH;
190
140
  }
191
141
  return Math.max(layout === 'compact' ? COMPACT_LAYOUT_MIN_WIDTH : MIN_CARD_WIDTH, value);
@@ -193,11 +143,9 @@ const normalizeCardWidth = ({ value, layout, }) => {
193
143
  /**
194
144
  * Renders WakaTime card.
195
145
  *
196
- * @param stats WakaTime stats.
197
- * @param options Card options.
198
146
  * @returns WakaTime card SVG.
199
147
  */
200
- const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
148
+ const renderWakatimeCard = (stats = {}, options = {}) => {
201
149
  let { languages = [] } = stats;
202
150
  const { hide_title = false, hide_border = false, card_width, hide, line_height = DEFAULT_LINE_HEIGHT, hide_progress, custom_title, locale, layout, langs_count = languages.length, border_radius, display_format = 'time', disable_animations, } = options;
203
151
  const normalizedWidth = normalizeCardWidth({ value: card_width, layout });
@@ -214,14 +162,13 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
214
162
  locale,
215
163
  translations: wakatimeCardLocales,
216
164
  });
217
- const lheight = parseInt(String(line_height), 10);
165
+ const lheight = Number.parseInt(String(line_height), 10);
218
166
  const langsCount = clampValue(langs_count, 1, langs_count);
219
167
  const { lightColors, darkColors } = getLightDarkColors(options);
220
168
  const filteredLanguages = languages
221
169
  .filter((language) => language.hours || language.minutes)
222
170
  .slice(0, langsCount);
223
- // Calculate the card height depending on how many items there are
224
- // but if rank circle is visible clamp the minimum height to `150`
171
+ // A short language list would otherwise draw a stub card, so 150 is the floor.
225
172
  let height = Math.max(45 + (filteredLanguages.length + 1) * lheight, 150);
226
173
  let finalLayout;
227
174
  // RENDER COMPACT LAYOUT
@@ -231,60 +178,58 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
231
178
  // progressOffset holds the previous language's width and used to offset the next language
232
179
  // so that we can stack them one after another, like this: [--][----][---]
233
180
  let progressOffset = 0;
234
- const compactProgressBar = filteredLanguages
235
- .map((language) => {
181
+ const compactProgressBar = filteredLanguages.map((language) => {
236
182
  const progress = ((width - COMPACT_LAYOUT_PROGRESSBAR_PADDING) * language.percent) / 100;
237
- const languageColor = getLanguageColor(language.name);
238
- const output = `
239
- <rect
240
- mask="url(#rect-mask)"
241
- data-testid="lang-progress"
242
- x="${progressOffset}"
243
- y="0"
244
- width="${progress}"
245
- height="8"
246
- fill="${languageColor}"
247
- />
248
- `;
183
+ const x = progressOffset;
249
184
  progressOffset += progress;
250
- return output;
251
- })
252
- .join('');
253
- finalLayout = `
254
- <mask id="rect-mask">
255
- <rect x="${COMPACT_LAYOUT_PROGRESSBAR_PADDING}" y="0" width="${width - 2 * COMPACT_LAYOUT_PROGRESSBAR_PADDING}" height="8" fill="white" rx="5" />
256
- </mask>
257
- ${compactProgressBar}
258
- ${filteredLanguages.length
259
- ? createLanguageTextNode({
260
- y: 25,
261
- langs: filteredLanguages,
262
- display_format,
263
- card_width: normalizedWidth,
264
- }).join('')
265
- : noCodingActivityNode({
266
- text: stats.is_coding_activity_visible
267
- ? stats.is_other_usage_visible
268
- ? i18n.t('wakatimecard.nocodingactivity')
269
- : i18n.t('wakatimecard.nocodedetails')
270
- : i18n.t('wakatimecard.notpublic'),
271
- })}
272
- `;
185
+ return el('rect', {
186
+ mask: 'url(#rect-mask)',
187
+ 'data-testid': 'lang-progress',
188
+ x,
189
+ y: 0,
190
+ width: progress,
191
+ height: 8,
192
+ fill: getLanguageColor(language.name),
193
+ });
194
+ });
195
+ finalLayout = [
196
+ el('mask', { id: 'rect-mask' }, el('rect', {
197
+ x: COMPACT_LAYOUT_PROGRESSBAR_PADDING,
198
+ y: 0,
199
+ width: width - 2 * COMPACT_LAYOUT_PROGRESSBAR_PADDING,
200
+ height: 8,
201
+ fill: 'white',
202
+ rx: 5,
203
+ })),
204
+ compactProgressBar,
205
+ filteredLanguages.length > 0
206
+ ? createLanguageTextNode({
207
+ y: 25,
208
+ langs: filteredLanguages,
209
+ display_format,
210
+ card_width: normalizedWidth,
211
+ })
212
+ : noCodingActivityNode({
213
+ text: stats.is_coding_activity_visible
214
+ ? stats.is_other_usage_visible
215
+ ? i18n.t('wakatimecard.nocodingactivity')
216
+ : i18n.t('wakatimecard.nocodedetails')
217
+ : i18n.t('wakatimecard.notpublic'),
218
+ }),
219
+ ];
273
220
  }
274
221
  else {
275
222
  finalLayout = flexLayout({
276
- items: filteredLanguages.length
277
- ? filteredLanguages.map((language, index) => {
278
- return createTextNode({
279
- id: language.name,
280
- label: language.name,
281
- value: formatLanguageValue({ display_format, lang: language }),
282
- index,
283
- percent: language.percent,
284
- hideProgress: hide_progress,
285
- progressBarWidth: normalizedWidth - TOTAL_TEXT_WIDTH,
286
- });
287
- })
223
+ items: filteredLanguages.length > 0
224
+ ? filteredLanguages.map((language, index) => createTextNode({
225
+ id: language.name,
226
+ label: language.name,
227
+ value: formatLanguageValue({ display_format, lang: language }),
228
+ index,
229
+ percent: language.percent,
230
+ hideProgress: hide_progress,
231
+ progressBarWidth: normalizedWidth - TOTAL_TEXT_WIDTH,
232
+ }))
288
233
  : [
289
234
  noCodingActivityNode({
290
235
  text: stats.is_coding_activity_visible
@@ -296,17 +241,22 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
296
241
  ],
297
242
  gap: lheight,
298
243
  direction: 'column',
299
- }).join('');
244
+ });
300
245
  }
301
246
  // Get title range text
302
247
  let titleText = i18n.t('wakatimecard.title');
303
248
  switch (stats.range) {
304
- case 'last_7_days':
249
+ case 'last_7_days': {
305
250
  titleText += ` (${i18n.t('wakatimecard.last7days')})`;
306
251
  break;
307
- case 'last_year':
252
+ }
253
+ case 'last_year': {
308
254
  titleText += ` (${i18n.t('wakatimecard.lastyear')})`;
309
255
  break;
256
+ }
257
+ default: {
258
+ break;
259
+ }
310
260
  }
311
261
  const card = new Card({
312
262
  customTitle: custom_title,
@@ -322,55 +272,38 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
322
272
  card.setHideBorder(hide_border);
323
273
  card.setHideTitle(hide_title);
324
274
  card.setCSS({
325
- light: ({ titleColor, textColor }) => `
326
- ${getStyles({ textColor })}
327
- @keyframes slideInAnimation {
328
- from {
329
- width: 0;
330
- }
331
- to {
332
- width: calc(100%-100px);
333
- }
334
- }
335
- @keyframes growWidthAnimation {
336
- from {
337
- width: 0;
338
- }
339
- to {
340
- width: 100%;
341
- }
342
- }
343
- .lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
344
- #rect-mask rect{
345
- animation: slideInAnimation 1s ease-in-out forwards;
346
- }
347
- .lang-progress{
348
- animation: growWidthAnimation 0.6s ease-in-out forwards;
349
- fill: ${titleColor};
350
- }
351
- .progress-background { fill: ${textColor === titleColor ? '#fff0' /* transparent */ : textColor}; }
352
- `,
353
- dark: ({ titleColor, textColor }) => `
354
- ${getStyles({ textColor })}
355
- .lang-name { fill: ${textColor} }
356
- .lang-progress { fill: ${titleColor}; }
357
- .progress-background { fill: ${textColor === titleColor ? '#fff0' /* transparent */ : textColor}; }
358
- `,
275
+ light: ({ titleColor, textColor }) => [
276
+ getStyles({ textColor }),
277
+ atRule('@keyframes slideInAnimation', rule('from', { width: 0 }),
278
+ // Invalid on purpose — `calc` needs spaces around its `-`. Browsers drop the
279
+ // declaration and animate to the rect's own width, which is the reveal the mask wants.
280
+ rule('to', { width: 'calc(100%-100px)' })),
281
+ atRule('@keyframes growWidthAnimation', rule('from', { width: 0 }), rule('to', { width: '100%' })),
282
+ rule('.lang-name', { font: "400 11px 'Segoe UI', Ubuntu, Sans-Serif", fill: textColor }),
283
+ rule('#rect-mask rect', { animation: 'slideInAnimation 1s ease-in-out forwards' }),
284
+ rule('.lang-progress', {
285
+ animation: 'growWidthAnimation 0.6s ease-in-out forwards',
286
+ fill: titleColor,
287
+ }),
288
+ rule('.progress-background', { fill: progressBackground(titleColor, textColor) }),
289
+ ],
290
+ dark: ({ titleColor, textColor }) => [
291
+ getStyles({ textColor }),
292
+ rule('.lang-name', { fill: textColor }),
293
+ rule('.lang-progress', { fill: titleColor }),
294
+ rule('.progress-background', { fill: progressBackground(titleColor, textColor) }),
295
+ ],
359
296
  });
360
297
  // `role="img"` hides the inner text from assistive tech, so everything the card
361
298
  // shows has to be repeated here.
362
299
  card.setAccessibilityLabel({
363
300
  title: card.title,
364
- desc: filteredLanguages.length
301
+ desc: filteredLanguages.length > 0
365
302
  ? filteredLanguages
366
303
  .map((lang) => `${lang.name}: ${formatLanguageValue({ display_format, lang })}`)
367
304
  .join(', ')
368
305
  : i18n.t('wakatimecard.nocodingactivity'),
369
306
  });
370
- return card.render(`
371
- <svg x="0" y="0" width="100%">
372
- ${finalLayout}
373
- </svg>
374
- `);
307
+ return card.render(el('svg', { x: 0, y: 0, width: '100%' }, finalLayout));
375
308
  };
376
309
  export { DISPLAY_FORMATS, WAKATIME_LAYOUTS, renderWakatimeCard };
@@ -1,8 +1,9 @@
1
- import type { CardColors } from './color.js';
1
+ import type { Child, CssChild, MarkupElement } from '../markup/index.ts';
2
+ import type { CardColors } from './color.ts';
2
3
  /**
3
4
  * Builds the card CSS for one color scheme from that scheme's resolved colors.
4
5
  */
5
- type CardCSSBuilder = (colors: CardColors) => string;
6
+ type CardCSSBuilder = (colors: CardColors) => Array<CssChild>;
6
7
  declare class Card {
7
8
  width: number;
8
9
  height: number;
@@ -14,29 +15,16 @@ declare class Card {
14
15
  dark: CardColors | null;
15
16
  };
16
17
  title: string;
17
- css: string;
18
- darkCss: string;
18
+ css: Array<CssChild>;
19
+ darkCss: Array<CssChild>;
19
20
  paddingX: number;
20
21
  paddingY: number;
21
- titlePrefixIcon: string | undefined;
22
+ titlePrefixIcon: Child;
22
23
  animations: boolean;
23
24
  a11yTitle: string;
24
25
  a11yDesc: string;
25
26
  /**
26
27
  * Creates a new card instance.
27
- *
28
- * The caller must ensure that the passed `titlePrefixIcon` is properly sanitized!
29
- *
30
- * @param props Card arguments.
31
- * @param props.width Card width.
32
- * @param props.height Card height.
33
- * @param props.border_radius Card border radius.
34
- * @param props.colors Card colors for light and dark mode.
35
- * @param props.colors.light Card colors for light mode.
36
- * @param props.colors.dark Card colors for dark mode, or `null` when no dark-mode override is needed.
37
- * @param props.customTitle Card custom title.
38
- * @param props.defaultTitle Card default title.
39
- * @param props.titlePrefixIcon Sanitized card title prefix icon.
40
28
  */
41
29
  constructor({ width, height, border_radius, colors, customTitle, defaultTitle, titlePrefixIcon, }: {
42
30
  width?: number;
@@ -48,14 +36,9 @@ declare class Card {
48
36
  };
49
37
  customTitle?: string | undefined;
50
38
  defaultTitle?: string;
51
- titlePrefixIcon?: string;
39
+ titlePrefixIcon?: Child;
52
40
  });
53
41
  disableAnimations(): void;
54
- /**
55
- * @param props The props object.
56
- * @param props.title Accessibility title.
57
- * @param props.desc Accessibility description.
58
- */
59
42
  setAccessibilityLabel({ title, desc }: {
60
43
  title: string;
61
44
  desc: string;
@@ -66,56 +49,25 @@ declare class Card {
66
49
  * Each builder receives the colors of its own color scheme,
67
50
  * so a card never handles a missing dark palette itself:
68
51
  * `dark` runs only when the card has dark colors, and always with non-null ones.
69
- *
70
- * @warning The caller must ensure that the returned CSS strings are properly sanitized!
71
- *
72
- * @param props The props object.
73
- * @param props.light Builds the CSS applied unconditionally (light/default mode).
74
- * @param props.dark Builds the CSS placed inside a `@media (prefers-color-scheme: dark)` block.
75
52
  */
76
53
  setCSS({ light, dark }: {
77
54
  light: CardCSSBuilder;
78
55
  dark: CardCSSBuilder;
79
56
  }): void;
80
- /**
81
- * @param value Whether to hide the border or not.
82
- */
83
57
  setHideBorder(value: boolean): void;
84
- /**
85
- * @param value Whether to hide the title or not.
86
- */
87
58
  setHideTitle(value: boolean): void;
88
- /**
89
- * @param text The title to set.
90
- */
91
59
  setTitle(text: string): void;
92
- /**
93
- * @returns The rendered card title.
94
- */
95
- renderTitle(): string;
96
- /**
97
- * @returns The rendered card gradient.
98
- */
99
- renderGradient(): string;
100
- /**
101
- * Retrieves css animations for a card.
102
- *
103
- * @returns Animation css.
104
- */
105
- getAnimations: () => string;
60
+ /** @returns The rendered card title. */
61
+ renderTitle(): MarkupElement;
62
+ /** @returns The card's gradient definitions, or nothing when no color is a gradient. */
63
+ renderGradient(): Child;
106
64
  /**
107
65
  * Builds the @media (prefers-color-scheme: dark) CSS block for the card.
108
- * Returns an empty string when no dark colors are set.
66
+ * Returns nothing when no dark colors are set.
109
67
  */
110
68
  private renderDarkMediaBlock;
111
- /**
112
- * The caller must ensure that the passed `body` string is properly sanitized!
113
- *
114
- * @param body The sanitized inner body of the card.
115
- * @returns The rendered card.
116
- */
117
- render(body: string): string;
69
+ /** @returns The rendered card. */
70
+ render(body: Child): string;
118
71
  }
119
72
  export { Card };
120
- export default Card;
121
73
  //# sourceMappingURL=Card.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../src/common/Card.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C;;GAEG;AACH,KAAK,cAAc,GAAG,CAAC,MAAM,EAAE,UAAU,KAAK,MAAM,CAAC;AAErD,cAAM,IAAI;IACR,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,CAAC;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;;;;;;;;;;;;OAeG;gBACS,EACV,KAAW,EACX,MAAY,EACZ,aAAmB,EACnB,MAAiD,EACjD,WAAW,EACX,YAAiB,EACjB,eAAe,GAChB,EAAE;QACD,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAEhB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACnC,MAAM,CAAC,EAAE;YAAE,KAAK,EAAE,UAAU,CAAC;YAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;SAAE,CAAC;QACxD,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACjC,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B;IAuBD,iBAAiB,IAAI,IAAI;IAIzB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAK7E;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI;IAK9E;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAInC;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAUlC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,WAAW,IAAI,MAAM;IAoCrB;;OAEG;IACH,cAAc,IAAI,MAAM;IAwCxB;;;;OAIG;IACH,aAAa,QAAO,MAAM,CAoBxB;IAEF;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAkB5B;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAiF7B;AAED,OAAO,EAAE,IAAI,EAAE,CAAC;AAChB,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../src/common/Card.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C;;GAEG;AACH,KAAK,cAAc,GAAG,CAAC,MAAM,EAAE,UAAU,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC;AA2C9D,cAAM,IAAI;IACR,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,CAAC;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,KAAK,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,YAAY,EACV,KAAW,EACX,MAAY,EACZ,aAAiB,EACjB,MAAiD,EACjD,WAAW,EACX,YAAiB,EACjB,eAAe,GAChB,EAAE;QACD,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAEhB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACnC,MAAM,CAAC,EAAE;YAAE,KAAK,EAAE,UAAU,CAAC;YAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;SAAE,CAAC;QACxD,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACjC,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,KAAK,CAAC;KACzB,EAqBA;IAED,iBAAiB,IAAI,IAAI,CAExB;IAED,qBAAqB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAG5E;IAED;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI,CAG7E;IAED,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAElC;IAED,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAQjC;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE3B;IAED,wCAAwC;IACxC,WAAW,IAAI,aAAa,CA4B3B;IAED,wFAAwF;IACxF,cAAc,IAAI,KAAK,CAwBtB;IAED;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAkB5B,kCAAkC;IAClC,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CA2E1B;CACF;AAED,OAAO,EAAE,IAAI,EAAE,CAAC"}