@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,36 +1,44 @@
1
- // @ts-check
1
+ import { isPrefixedHexColor, isValidGradient } from "./color.js";
2
2
  import { encodeHTML } from "./html.js";
3
3
  import { flexLayout } from "./render.js";
4
4
  class Card {
5
+ width;
6
+ height;
7
+ hideBorder;
8
+ hideTitle;
9
+ border_radius;
10
+ colors;
11
+ title;
12
+ css;
13
+ paddingX;
14
+ paddingY;
15
+ titlePrefixIcon;
16
+ animations;
17
+ a11yTitle;
18
+ a11yDesc;
5
19
  /**
6
20
  * Creates a new card instance.
7
21
  *
8
- * @param {object} args Card arguments.
9
- * @param {number=} args.width Card width.
10
- * @param {number=} args.height Card height.
11
- * @param {number=} args.border_radius Card border radius.
12
- * @param {string=} args.customTitle Card custom title.
13
- * @param {string=} args.defaultTitle Card default title.
14
- * @param {string=} args.titlePrefixIcon Card title prefix icon.
15
- * @param {object} [args.colors={}] Card colors arguments.
16
- * @param {string=} args.colors.titleColor Card title color.
17
- * @param {string=} args.colors.textColor Card text color.
18
- * @param {string=} args.colors.iconColor Card icon color.
19
- * @param {string|string[]=} args.colors.bgColor Card background color.
20
- * @param {string=} args.colors.borderColor Card border color.
22
+ * The caller must ensure that the passed `titlePrefixIcon` is properly sanitized!
23
+ *
24
+ * @param props Card arguments.
25
+ * @param props.width Card width.
26
+ * @param props.height Card height.
27
+ * @param props.border_radius Card border radius.
28
+ * @param props.colors Card colors arguments.
29
+ * @param props.customTitle Card custom title.
30
+ * @param props.defaultTitle Card default title.
31
+ * @param props.titlePrefixIcon Sanitized card title prefix icon.
21
32
  */
22
33
  constructor({ width = 100, height = 100, border_radius = 4.5, colors = {}, customTitle, defaultTitle = "", titlePrefixIcon, }) {
23
34
  this.width = width;
24
35
  this.height = height;
25
36
  this.hideBorder = false;
26
37
  this.hideTitle = false;
27
- this.border_radius = border_radius;
38
+ this.border_radius = parseFloat(String(border_radius));
28
39
  // returns theme based colors with proper overrides and defaults
29
40
  this.colors = colors;
30
- this.title =
31
- customTitle === undefined
32
- ? encodeHTML(defaultTitle)
33
- : encodeHTML(customTitle);
41
+ this.title = customTitle === undefined ? defaultTitle : customTitle;
34
42
  this.css = "";
35
43
  this.paddingX = 25;
36
44
  this.paddingY = 35;
@@ -39,55 +47,52 @@ class Card {
39
47
  this.a11yTitle = "";
40
48
  this.a11yDesc = "";
41
49
  }
42
- /**
43
- * @returns {void}
44
- */
45
50
  disableAnimations() {
46
51
  this.animations = false;
47
52
  }
48
53
  /**
49
- * @param {Object} props The props object.
50
- * @param {string} props.title Accessibility title.
51
- * @param {string} props.desc Accessibility description.
52
- * @returns {void}
54
+ * @param props The props object.
55
+ * @param props.title Accessibility title.
56
+ * @param props.desc Accessibility description.
53
57
  */
54
- setAccessibilityLabel({ title, desc }) {
58
+ setAccessibilityLabel({ title, desc, }) {
55
59
  this.a11yTitle = title;
56
60
  this.a11yDesc = desc;
57
61
  }
58
62
  /**
59
- * @param {string} value The CSS to add to the card.
60
- * @returns {void}
63
+ * The caller must ensure that the passed `css` string is properly sanitized!
64
+ *
65
+ * @param value The sanitized CSS to add to the card.
61
66
  */
62
67
  setCSS(value) {
63
68
  this.css = value;
64
69
  }
65
70
  /**
66
- * @param {boolean} value Whether to hide the border or not.
67
- * @returns {void}
71
+ * @param value Whether to hide the border or not.
68
72
  */
69
73
  setHideBorder(value) {
70
74
  this.hideBorder = value;
71
75
  }
72
76
  /**
73
- * @param {boolean} value Whether to hide the title or not.
74
- * @returns {void}
77
+ * @param value Whether to hide the title or not.
75
78
  */
76
79
  setHideTitle(value) {
77
- this.hideTitle = value;
78
- if (value) {
80
+ if (value && !this.hideTitle) {
79
81
  this.height -= 30;
80
82
  }
83
+ if (!value && this.hideTitle) {
84
+ this.height += 30;
85
+ }
86
+ this.hideTitle = value;
81
87
  }
82
88
  /**
83
- * @param {string} text The title to set.
84
- * @returns {void}
89
+ * @param text The title to set.
85
90
  */
86
91
  setTitle(text) {
87
92
  this.title = text;
88
93
  }
89
94
  /**
90
- * @returns {string} The rendered card title.
95
+ * @returns The rendered card title.
91
96
  */
92
97
  renderTitle() {
93
98
  const titleText = `
@@ -96,7 +101,7 @@ class Card {
96
101
  y="0"
97
102
  class="header"
98
103
  data-testid="header"
99
- >${this.title}</text>
104
+ >${encodeHTML(this.title)}</text>
100
105
  `;
101
106
  const prefixIcon = `
102
107
  <svg
@@ -108,7 +113,7 @@ class Card {
108
113
  width="16"
109
114
  height="16"
110
115
  >
111
- ${this.titlePrefixIcon}
116
+ ${String(this.titlePrefixIcon)}
112
117
  </svg>
113
118
  `;
114
119
  return `
@@ -124,34 +129,37 @@ class Card {
124
129
  `;
125
130
  }
126
131
  /**
127
- * @returns {string} The rendered card gradient.
132
+ * @returns The rendered card gradient.
128
133
  */
129
134
  renderGradient() {
130
135
  if (typeof this.colors.bgColor !== "object") {
131
136
  return "";
132
137
  }
138
+ if (!isValidGradient(this.colors.bgColor)) {
139
+ throw new Error(`Invalid gradient: ${this.colors.bgColor.join(",")}`);
140
+ }
133
141
  const gradients = this.colors.bgColor.slice(1);
134
- return typeof this.colors.bgColor === "object"
135
- ? `
142
+ return `
136
143
  <defs>
137
144
  <linearGradient
138
145
  id="gradient"
139
- gradientTransform="rotate(${this.colors.bgColor[0]})"
146
+ gradientTransform="rotate(${String(this.colors.bgColor[0])})"
140
147
  gradientUnits="userSpaceOnUse"
141
148
  >
142
- ${gradients.map((grad, index) => {
143
- let offset = (index * 100) / (gradients.length - 1);
144
- return `<stop offset="${offset}%" stop-color="#${grad}" />`;
145
- })}
149
+ ${gradients
150
+ .map((grad, index) => {
151
+ const offset = (index * 100) / (gradients.length - 1);
152
+ return `<stop offset="${offset}%" stop-color="#${grad}" />`;
153
+ })
154
+ .join(",")}
146
155
  </linearGradient>
147
156
  </defs>
148
- `
149
- : "";
157
+ `;
150
158
  }
151
159
  /**
152
160
  * Retrieves css animations for a card.
153
161
  *
154
- * @returns {string} Animation css.
162
+ * @returns Animation css.
155
163
  */
156
164
  getAnimations = () => {
157
165
  return `
@@ -175,10 +183,29 @@ class Card {
175
183
  `;
176
184
  };
177
185
  /**
178
- * @param {string} body The inner body of the card.
179
- * @returns {string} The rendered card.
186
+ * The caller must ensure that the passed `body` string is properly sanitized!
187
+ *
188
+ * @param body The sanitized inner body of the card.
189
+ * @returns The rendered card.
180
190
  */
181
191
  render(body) {
192
+ if (!Number.isFinite(this.border_radius)) {
193
+ throw new Error(`Invalid border radius: "${this.border_radius}"`);
194
+ }
195
+ if (this.colors.titleColor !== undefined &&
196
+ !isPrefixedHexColor(this.colors.titleColor)) {
197
+ throw new Error(`Invalid title color: "${this.colors.titleColor}"`);
198
+ }
199
+ if (this.colors.borderColor !== undefined &&
200
+ !isPrefixedHexColor(this.colors.borderColor)) {
201
+ throw new Error(`Invalid border color: "${this.colors.borderColor}"`);
202
+ }
203
+ if (this.colors.bgColor !== undefined &&
204
+ !(typeof this.colors.bgColor === "object"
205
+ ? isValidGradient(this.colors.bgColor)
206
+ : isPrefixedHexColor(this.colors.bgColor))) {
207
+ throw new Error(`Invalid background color: ${String(this.colors.bgColor)}`);
208
+ }
182
209
  return `
183
210
  <svg
184
211
  width="${this.width}"
@@ -189,12 +216,12 @@ class Card {
189
216
  role="img"
190
217
  aria-labelledby="descId"
191
218
  >
192
- <title id="titleId">${this.a11yTitle}</title>
193
- <desc id="descId">${this.a11yDesc}</desc>
219
+ <title id="titleId">${encodeHTML(this.a11yTitle)}</title>
220
+ <desc id="descId">${encodeHTML(this.a11yDesc)}</desc>
194
221
  <style>
195
222
  .header {
196
223
  font: 600 18px 'Segoe UI', Ubuntu, Sans-Serif;
197
- fill: ${this.colors.titleColor};
224
+ fill: ${String(this.colors.titleColor)};
198
225
  animation: fadeInAnimation 0.8s ease-in-out forwards;
199
226
  }
200
227
  @supports(-moz-appearance: auto) {
@@ -204,9 +231,9 @@ class Card {
204
231
  ${this.css}
205
232
 
206
233
  ${this.getAnimations()}
207
- ${this.animations === false
208
- ? `* { animation-duration: 0s !important; animation-delay: 0s !important; }`
209
- : ""}
234
+ ${this.animations
235
+ ? ""
236
+ : `* { animation-duration: 0s !important; animation-delay: 0s !important; }`}
210
237
  </style>
211
238
 
212
239
  ${this.renderGradient()}
@@ -217,11 +244,11 @@ class Card {
217
244
  y="0.5"
218
245
  rx="${this.border_radius}"
219
246
  height="99%"
220
- stroke="${this.colors.borderColor}"
247
+ stroke="${String(this.colors.borderColor)}"
221
248
  width="${this.width - 1}"
222
249
  fill="${typeof this.colors.bgColor === "object"
223
250
  ? "url(#gradient)"
224
- : this.colors.bgColor}"
251
+ : String(this.colors.bgColor)}"
225
252
  stroke-opacity="${this.hideBorder ? 0 : 1}"
226
253
  />
227
254
 
@@ -1,26 +1,25 @@
1
1
  /**
2
2
  * I18n translation class.
3
3
  */
4
- export class I18n {
4
+ declare class I18n<Translations extends Record<string, Record<string, string>>> {
5
+ locale: string;
6
+ translations: Translations;
5
7
  /**
6
- * Constructor.
7
- *
8
- * @param {Object} options Options.
9
- * @param {string=} options.locale Locale.
10
- * @param {any} options.translations Translations.
8
+ * @param props Constructor arguments.
9
+ * @param props.locale Locale.
10
+ * @param props.translations Translations.
11
11
  */
12
- constructor({ locale, translations }: {
13
- locale?: string | undefined;
14
- translations: any;
12
+ constructor({ locale, translations, }: {
13
+ locale?: string;
14
+ translations: Translations;
15
15
  });
16
- locale: string;
17
- translations: any;
18
16
  /**
19
17
  * Get translation.
20
18
  *
21
- * @param {string} str String to translate.
22
- * @returns {string} Translated string.
19
+ * @param str String to translate.
20
+ * @returns Translated string.
23
21
  */
24
- t(str: string): string;
22
+ t(str: keyof Translations & string): string;
25
23
  }
24
+ export { I18n };
26
25
  //# sourceMappingURL=I18n.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"I18n.d.ts","sourceRoot":"","sources":["../../src/common/I18n.js"],"names":[],"mappings":"AAIA;;GAEG;AACH;IACE;;;;;;OAMG;IACH,sCAHG;QAAyB,MAAM,GAAvB,MAAM,YAAC;QACM,YAAY,EAAzB,GAAG;KACb,EAIA;IAFC,eAAuC;IACvC,kBAAgC;IAGlC;;;;;OAKG;IACH,OAHW,MAAM,GACJ,MAAM,CAclB;CACF"}
1
+ {"version":3,"file":"I18n.d.ts","sourceRoot":"","sources":["../../src/common/I18n.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,cAAM,IAAI,CAAC,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,YAAY,CAAC;IAE3B;;;;OAIG;gBACS,EACV,MAAM,EACN,YAAY,GACb,EAAE;QACD,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,YAAY,CAAC;KAC5B;IAKD;;;;;OAKG;IACH,CAAC,CAAC,GAAG,EAAE,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM;CAe5C;AAED,OAAO,EAAE,IAAI,EAAE,CAAC"}
@@ -1,34 +1,35 @@
1
- // @ts-check
2
1
  const FALLBACK_LOCALE = "en";
3
2
  /**
4
3
  * I18n translation class.
5
4
  */
6
5
  class I18n {
6
+ locale;
7
+ translations;
7
8
  /**
8
- * Constructor.
9
- *
10
- * @param {Object} options Options.
11
- * @param {string=} options.locale Locale.
12
- * @param {any} options.translations Translations.
9
+ * @param props Constructor arguments.
10
+ * @param props.locale Locale.
11
+ * @param props.translations Translations.
13
12
  */
14
- constructor({ locale, translations }) {
13
+ constructor({ locale, translations, }) {
15
14
  this.locale = locale || FALLBACK_LOCALE;
16
15
  this.translations = translations;
17
16
  }
18
17
  /**
19
18
  * Get translation.
20
19
  *
21
- * @param {string} str String to translate.
22
- * @returns {string} Translated string.
20
+ * @param str String to translate.
21
+ * @returns Translated string.
23
22
  */
24
23
  t(str) {
25
- if (!this.translations[str]) {
24
+ const translation = this.translations[str];
25
+ if (!translation) {
26
26
  throw new Error(`${str} Translation string not found`);
27
27
  }
28
- if (!this.translations[str][this.locale]) {
28
+ const localized = translation[this.locale];
29
+ if (!localized) {
29
30
  throw new Error(`'${str}' translation not found for locale '${this.locale}'`);
30
31
  }
31
- return this.translations[str][this.locale];
32
+ return localized;
32
33
  }
33
34
  }
34
35
  export { I18n };
@@ -1,47 +1,70 @@
1
1
  /**
2
- * Object containing card colors.
2
+ * Checks if a value is a bare hex color, i.e. hex digits with no `#` prefix
3
+ * (`"f00"`, `"ffffff"`). This is the form user-supplied color params and
4
+ * gradient stops arrive in.
5
+ *
6
+ * @param value Value to check.
7
+ * @returns True if the value is a bare hex color.
3
8
  */
4
- export type CardColors = {
5
- titleColor: string;
6
- iconColor: string;
7
- textColor: string;
8
- bgColor: string | string[];
9
- borderColor: string;
10
- ringColor: string;
11
- };
9
+ declare const isBareHexColor: (value: unknown) => boolean;
10
+ /**
11
+ * Checks if a value is a `#`-prefixed hex color (`"#f00"`, `"#ffffff"`). This
12
+ * is the form colors take once resolved by {@link getCardColors}, i.e. right
13
+ * before they are written into the SVG.
14
+ *
15
+ * @param value Value to check.
16
+ * @returns True if the value is a `#`-prefixed hex color.
17
+ */
18
+ declare const isPrefixedHexColor: (value: unknown) => boolean;
19
+ /**
20
+ * Checks if the given parts form a valid gradient: a finite numeric angle
21
+ * followed by at least two bare-hex color stops, e.g. `["90", "f00", "0f0"]`.
22
+ * The angle is written into the SVG `gradientTransform="rotate(...)"`.
23
+ *
24
+ * @param parts Gradient parts: `[angle, ...stops]`.
25
+ * @returns True if the parts form a valid gradient.
26
+ */
27
+ declare const isValidGradient: (parts: Array<string>) => boolean;
28
+ /**
29
+ * Iterates over a collection of colors inputs and verifies that each is a valid color or gradient.
30
+ *
31
+ * @param colors Object whose values are checked as valid color inputs.
32
+ * @return The first key where the associated input value is not valid. null if all inputs are valid.
33
+ */
34
+ declare const findInvalidColor: (colors: Record<string, string | null | undefined>) => string | null;
12
35
  /**
13
36
  * Retrieves a gradient if color has more than one valid hex codes else a single color.
14
37
  *
15
- * @param {string} color The color to parse.
16
- * @param {string | string[]} fallbackColor The fallback color.
17
- * @returns {string | string[]} The gradient or color.
38
+ * @param color The color to parse.
39
+ * @param fallbackColor The fallback color.
40
+ * @returns The gradient or color.
18
41
  */
19
- export function fallbackColor(color: string, fallbackColor: string | string[]): string | string[];
42
+ declare const fallbackColor: (color: string | undefined, fallbackColor: string | Array<string>) => string | Array<string>;
20
43
  /**
21
44
  * Object containing card colors.
22
- * @typedef {{
23
- * titleColor: string;
24
- * iconColor: string;
25
- * textColor: string;
26
- * bgColor: string | string[];
27
- * borderColor: string;
28
- * ringColor: string;
29
- * }} CardColors
30
45
  */
46
+ interface CardColors {
47
+ titleColor: string;
48
+ iconColor: string;
49
+ textColor: string;
50
+ bgColor: string | Array<string>;
51
+ borderColor: string;
52
+ ringColor: string;
53
+ }
31
54
  /**
32
55
  * Returns theme based colors with proper overrides and defaults.
33
56
  *
34
- * @param {Object} args Function arguments.
35
- * @param {string=} args.title_color Card title color.
36
- * @param {string=} args.text_color Card text color.
37
- * @param {string=} args.icon_color Card icon color.
38
- * @param {string=} args.bg_color Card background color.
39
- * @param {string=} args.border_color Card border color.
40
- * @param {string=} args.ring_color Card ring color.
41
- * @param {string=} args.theme Card theme.
42
- * @returns {CardColors} Card colors.
57
+ * @param props Function arguments.
58
+ * @param props.title_color Card title color.
59
+ * @param props.text_color Card text color.
60
+ * @param props.icon_color Card icon color.
61
+ * @param props.bg_color Card background color.
62
+ * @param props.border_color Card border color.
63
+ * @param props.ring_color Card ring color.
64
+ * @param props.theme Card theme.
65
+ * @returns Card colors.
43
66
  */
44
- export function getCardColors({ title_color, text_color, icon_color, bg_color, border_color, ring_color, theme, }: {
67
+ declare const getCardColors: ({ title_color, text_color, icon_color, bg_color, border_color, ring_color, theme, }: {
45
68
  title_color?: string | undefined;
46
69
  text_color?: string | undefined;
47
70
  icon_color?: string | undefined;
@@ -49,5 +72,6 @@ export function getCardColors({ title_color, text_color, icon_color, bg_color, b
49
72
  border_color?: string | undefined;
50
73
  ring_color?: string | undefined;
51
74
  theme?: string | undefined;
52
- }): CardColors;
75
+ }) => CardColors;
76
+ export { fallbackColor, getCardColors, findInvalidColor, isValidGradient, isBareHexColor, isPrefixedHexColor, };
53
77
  //# sourceMappingURL=color.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../src/common/color.js"],"names":[],"mappings":";;;yBAoDa;IACT,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CAClB;AA9BJ;;;;;;GAMG;AACH,qCAJW,MAAM,iBACN,MAAM,GAAG,MAAM,EAAE,GACf,MAAM,GAAG,MAAM,EAAE,CAc7B;AAED;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;GAYG;AACH,mHATG;IAAsB,WAAW,GAAzB,MAAM,YAAC;IACO,UAAU,GAAxB,MAAM,YAAC;IACO,UAAU,GAAxB,MAAM,YAAC;IACO,QAAQ,GAAtB,MAAM,YAAC;IACO,YAAY,GAA1B,MAAM,YAAC;IACO,UAAU,GAAxB,MAAM,YAAC;IACO,KAAK,GAAnB,MAAM,YAAC;CACf,GAAU,UAAU,CAqEtB"}
1
+ {"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../src/common/color.ts"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AACH,QAAA,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,OAExC,CAAC;AAEF;;;;;;;GAOG;AACH,QAAA,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,OAM5C,CAAC;AAEF;;;;;;;GAOG;AACH,QAAA,MAAM,eAAe,GAAI,OAAO,KAAK,CAAC,MAAM,CAAC,KAAG,OAS/C,CAAC;AAeF;;;;;GAKG;AACH,QAAA,MAAM,gBAAgB,GACpB,QAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,KAChD,MAAM,GAAG,IAOX,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,aAAa,GACjB,OAAO,MAAM,GAAG,SAAS,EACzB,eAAe,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,KACpC,MAAM,GAAG,KAAK,CAAC,MAAM,CAWvB,CAAC;AAEF;;GAEG;AACH,UAAU,UAAU;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,aAAa,GAAI,qFAQpB;IACD,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,KAAG,UAuDH,CAAC;AAEF,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,kBAAkB,GACnB,CAAC"}
@@ -1,81 +1,118 @@
1
- // @ts-check
2
1
  import { themes } from "../themes/index.js";
2
+ /** Matches a 3-, 4-, 6-, or 8-digit hex color with no leading `#`. */
3
+ const HEX_COLOR = /^([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{3})$/;
3
4
  /**
4
- * Checks if a string is a valid hex color.
5
+ * Checks if a value is a bare hex color, i.e. hex digits with no `#` prefix
6
+ * (`"f00"`, `"ffffff"`). This is the form user-supplied color params and
7
+ * gradient stops arrive in.
5
8
  *
6
- * @param {string} hexColor String to check.
7
- * @returns {boolean} True if the given string is a valid hex color.
9
+ * @param value Value to check.
10
+ * @returns True if the value is a bare hex color.
8
11
  */
9
- const isValidHexColor = (hexColor) => {
10
- return new RegExp(/^([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{4})$/).test(hexColor);
12
+ const isBareHexColor = (value) => {
13
+ return typeof value === "string" && HEX_COLOR.test(value);
11
14
  };
12
15
  /**
13
- * Check if the given string is a valid gradient.
16
+ * Checks if a value is a `#`-prefixed hex color (`"#f00"`, `"#ffffff"`). This
17
+ * is the form colors take once resolved by {@link getCardColors}, i.e. right
18
+ * before they are written into the SVG.
14
19
  *
15
- * @param {string[]} colors Array of colors.
16
- * @returns {boolean} True if the given string is a valid gradient.
20
+ * @param value Value to check.
21
+ * @returns True if the value is a `#`-prefixed hex color.
17
22
  */
18
- const isValidGradient = (colors) => {
19
- return (colors.length > 2 &&
20
- colors.slice(1).every((color) => isValidHexColor(color)));
23
+ const isPrefixedHexColor = (value) => {
24
+ return (typeof value === "string" &&
25
+ value.startsWith("#") &&
26
+ HEX_COLOR.test(value.slice(1)));
27
+ };
28
+ /**
29
+ * Checks if the given parts form a valid gradient: a finite numeric angle
30
+ * followed by at least two bare-hex color stops, e.g. `["90", "f00", "0f0"]`.
31
+ * The angle is written into the SVG `gradientTransform="rotate(...)"`.
32
+ *
33
+ * @param parts Gradient parts: `[angle, ...stops]`.
34
+ * @returns True if the parts form a valid gradient.
35
+ */
36
+ const isValidGradient = (parts) => {
37
+ const [angle, ...stops] = parts;
38
+ return (stops.length >= 2 &&
39
+ angle !== undefined &&
40
+ angle.trim() !== "" &&
41
+ Number.isFinite(Number(angle)) &&
42
+ stops.every(isBareHexColor));
43
+ };
44
+ /**
45
+ * Checks if a string is a valid input for a color or gradient.
46
+ *
47
+ * @param color String to check, may be null or undefined.
48
+ * @returns True if the given string is a valid input.
49
+ */
50
+ const isValidColorInput = (color) => {
51
+ if (color === null || color === undefined) {
52
+ return true;
53
+ }
54
+ return isValidGradient(color.split(",")) || isBareHexColor(color);
55
+ };
56
+ /**
57
+ * Iterates over a collection of colors inputs and verifies that each is a valid color or gradient.
58
+ *
59
+ * @param colors Object whose values are checked as valid color inputs.
60
+ * @return The first key where the associated input value is not valid. null if all inputs are valid.
61
+ */
62
+ const findInvalidColor = (colors) => {
63
+ for (const [key, value] of Object.entries(colors)) {
64
+ if (!isValidColorInput(value)) {
65
+ return key;
66
+ }
67
+ }
68
+ return null;
21
69
  };
22
70
  /**
23
71
  * Retrieves a gradient if color has more than one valid hex codes else a single color.
24
72
  *
25
- * @param {string} color The color to parse.
26
- * @param {string | string[]} fallbackColor The fallback color.
27
- * @returns {string | string[]} The gradient or color.
73
+ * @param color The color to parse.
74
+ * @param fallbackColor The fallback color.
75
+ * @returns The gradient or color.
28
76
  */
29
77
  const fallbackColor = (color, fallbackColor) => {
30
- let gradient = null;
31
- let colors = color ? color.split(",") : [];
78
+ const colors = color ? color.split(",") : [];
32
79
  if (colors.length > 1 && isValidGradient(colors)) {
33
- gradient = colors;
80
+ return colors;
81
+ }
82
+ if (color !== undefined && isBareHexColor(color)) {
83
+ return `#${color}`;
34
84
  }
35
- return ((gradient ? gradient : isValidHexColor(color) && `#${color}`) ||
36
- fallbackColor);
85
+ return fallbackColor;
37
86
  };
38
- /**
39
- * Object containing card colors.
40
- * @typedef {{
41
- * titleColor: string;
42
- * iconColor: string;
43
- * textColor: string;
44
- * bgColor: string | string[];
45
- * borderColor: string;
46
- * ringColor: string;
47
- * }} CardColors
48
- */
49
87
  /**
50
88
  * Returns theme based colors with proper overrides and defaults.
51
89
  *
52
- * @param {Object} args Function arguments.
53
- * @param {string=} args.title_color Card title color.
54
- * @param {string=} args.text_color Card text color.
55
- * @param {string=} args.icon_color Card icon color.
56
- * @param {string=} args.bg_color Card background color.
57
- * @param {string=} args.border_color Card border color.
58
- * @param {string=} args.ring_color Card ring color.
59
- * @param {string=} args.theme Card theme.
60
- * @returns {CardColors} Card colors.
90
+ * @param props Function arguments.
91
+ * @param props.title_color Card title color.
92
+ * @param props.text_color Card text color.
93
+ * @param props.icon_color Card icon color.
94
+ * @param props.bg_color Card background color.
95
+ * @param props.border_color Card border color.
96
+ * @param props.ring_color Card ring color.
97
+ * @param props.theme Card theme.
98
+ * @returns Card colors.
61
99
  */
62
100
  const getCardColors = ({ title_color, text_color, icon_color, bg_color, border_color, ring_color, theme, }) => {
63
- const defaultTheme = themes["default"];
64
- const isThemeProvided = theme !== null && theme !== undefined && theme in themes;
65
- // @ts-ignore
66
- const selectedTheme = isThemeProvided ? themes[theme] : defaultTheme;
101
+ const defaultTheme = themes.default;
102
+ const isThemeProvided = theme !== undefined && theme in themes;
103
+ const selectedTheme = isThemeProvided
104
+ ? themes[theme]
105
+ : defaultTheme;
67
106
  const defaultBorderColor = "border_color" in selectedTheme
68
107
  ? selectedTheme.border_color
69
- : // @ts-ignore
70
- defaultTheme.border_color;
108
+ : defaultTheme.border_color;
71
109
  // get the color provided by the user else the theme color
72
110
  // finally if both colors are invalid fallback to default theme
73
111
  const titleColor = fallbackColor(title_color || selectedTheme.title_color, "#" + defaultTheme.title_color);
74
112
  // get the color provided by the user else the theme color
75
113
  // finally if both colors are invalid we use the titleColor
76
- const ringColor = fallbackColor(
77
- // @ts-ignore
78
- ring_color || selectedTheme.ring_color, titleColor);
114
+ // NOTE: no built-in theme defines `ring_color`, so it falls back to the title color.
115
+ const ringColor = fallbackColor(ring_color, titleColor);
79
116
  const iconColor = fallbackColor(icon_color || selectedTheme.icon_color, "#" + defaultTheme.icon_color);
80
117
  const textColor = fallbackColor(text_color || selectedTheme.text_color, "#" + defaultTheme.text_color);
81
118
  const bgColor = fallbackColor(bg_color || selectedTheme.bg_color, "#" + defaultTheme.bg_color);
@@ -89,4 +126,4 @@ const getCardColors = ({ title_color, text_color, icon_color, bg_color, border_c
89
126
  }
90
127
  return { titleColor, iconColor, textColor, bgColor, borderColor, ringColor };
91
128
  };
92
- export { fallbackColor, getCardColors };
129
+ export { fallbackColor, getCardColors, findInvalidColor, isValidGradient, isBareHexColor, isPrefixedHexColor, };