@stats-organization/github-readme-stats-core 2.1.4 → 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 (77) hide show
  1. package/build/api/gist.d.ts.map +1 -1
  2. package/build/api/gist.js +34 -0
  3. package/build/api/index.d.ts.map +1 -1
  4. package/build/api/index.js +18 -0
  5. package/build/api/pin.d.ts.map +1 -1
  6. package/build/api/pin.js +17 -0
  7. package/build/api/top-langs.d.ts.map +1 -1
  8. package/build/api/top-langs.js +36 -4
  9. package/build/api/wakatime.d.ts.map +1 -1
  10. package/build/api/wakatime.js +34 -0
  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/repo.d.ts.map +1 -1
  15. package/build/cards/repo.js +29 -20
  16. package/build/cards/stats.d.ts +4 -2
  17. package/build/cards/stats.d.ts.map +1 -1
  18. package/build/cards/stats.js +21 -8
  19. package/build/cards/top-languages.d.ts.map +1 -1
  20. package/build/cards/top-languages.js +39 -11
  21. package/build/cards/wakatime.d.ts.map +1 -1
  22. package/build/cards/wakatime.js +29 -8
  23. package/build/common/Card.d.ts +9 -3
  24. package/build/common/Card.d.ts.map +1 -1
  25. package/build/common/Card.js +47 -19
  26. package/build/common/color.d.ts +42 -8
  27. package/build/common/color.d.ts.map +1 -1
  28. package/build/common/color.js +62 -13
  29. package/build/common/html.js +1 -1
  30. package/build/common/http.d.ts +13 -4
  31. package/build/common/http.d.ts.map +1 -1
  32. package/build/common/http.js +3 -3
  33. package/build/common/languageColors.json +9 -1
  34. package/build/common/ops.d.ts +30 -29
  35. package/build/common/ops.d.ts.map +1 -1
  36. package/build/common/ops.js +32 -37
  37. package/build/common/render.d.ts +115 -111
  38. package/build/common/render.d.ts.map +1 -1
  39. package/build/common/render.js +138 -87
  40. package/build/common/retryer.d.ts +14 -6
  41. package/build/common/retryer.d.ts.map +1 -1
  42. package/build/common/retryer.js +1 -0
  43. package/build/fetchers/gist.d.ts +6 -21
  44. package/build/fetchers/gist.d.ts.map +1 -1
  45. package/build/fetchers/gist.js +30 -35
  46. package/build/fetchers/repo.js +1 -1
  47. package/build/fetchers/stats.d.ts.map +1 -1
  48. package/build/fetchers/stats.js +0 -1
  49. package/build/fetchers/types.d.ts +126 -0
  50. package/build/fetchers/types.d.ts.map +1 -0
  51. package/build/fetchers/types.js +1 -0
  52. package/package.json +4 -4
  53. package/src/_emoji-name-map.d.ts +10 -0
  54. package/src/api/gist.js +36 -0
  55. package/src/api/index.js +19 -0
  56. package/src/api/pin.js +18 -0
  57. package/src/api/top-langs.js +38 -4
  58. package/src/api/wakatime.js +36 -0
  59. package/src/{calculateRank.js → calculateRank.ts} +29 -19
  60. package/src/cards/repo.js +30 -20
  61. package/src/cards/stats.js +22 -8
  62. package/src/cards/top-languages.js +49 -11
  63. package/src/cards/wakatime.js +33 -8
  64. package/src/common/Card.ts +51 -16
  65. package/src/common/color.ts +85 -22
  66. package/src/common/html.ts +1 -1
  67. package/src/common/http.ts +31 -0
  68. package/src/common/languageColors.json +9 -1
  69. package/src/common/{ops.js → ops.ts} +48 -50
  70. package/src/common/{render.js → render.ts} +208 -96
  71. package/src/common/retryer.ts +18 -10
  72. package/src/fetchers/gist.ts +136 -0
  73. package/src/fetchers/repo.js +1 -1
  74. package/src/fetchers/stats.js +0 -1
  75. package/src/common/http.js +0 -19
  76. package/src/fetchers/gist.js +0 -112
  77. /package/src/fetchers/{types.d.ts → types.ts} +0 -0
@@ -1,7 +1,8 @@
1
1
  import { Card } from "../common/Card.js";
2
2
  import { I18n } from "../common/I18n.js";
3
- import { fallbackColor, getCardColors } from "../common/color.js";
3
+ import { fallbackColor, getCardColors, isPrefixedHexColor, } from "../common/color.js";
4
4
  import { formatBytes } from "../common/fmt.js";
5
+ import { encodeHTML } from "../common/html.js";
5
6
  import { chunkArray, clampValue, lowercaseTrim } from "../common/ops.js";
6
7
  import { createProgressNode, flexLayout, measureText, } from "../common/render.js";
7
8
  import { langCardLocales } from "../translations.js";
@@ -201,8 +202,8 @@ const createProgressTextNode = ({ width, color, progBarBgColor, name, size, tota
201
202
  const displayValue = getDisplayValue(size, progress, statsFormat);
202
203
  return `
203
204
  <g class="stagger" style="animation-delay: ${staggerDelay}ms">
204
- <text data-testid="lang-name" x="2" y="15" class="lang-name">${name}</text>
205
- ${hideValues ? "" : `<text x="${progressTextX}" y="34" class="lang-name">${displayValue}</text>`}
205
+ <text data-testid="lang-name" x="2" y="15" class="lang-name">${encodeHTML(name)}</text>
206
+ ${hideValues ? "" : `<text x="${progressTextX}" y="34" class="lang-name">${encodeHTML(displayValue)}</text>`}
206
207
  ${createProgressNode({
207
208
  x: 0,
208
209
  y: 25,
@@ -232,11 +233,14 @@ const createCompactLangNode = ({ lang, totalSize, hideProgress, hideValues, stat
232
233
  const displayValue = getDisplayValue(lang.size, percentages, statsFormat);
233
234
  const staggerDelay = (index + 3) * 150;
234
235
  const color = lang.color || "#858585";
236
+ if (!isPrefixedHexColor(color)) {
237
+ throw new Error(`Invalid language color: "${color}"`);
238
+ }
235
239
  return `
236
240
  <g class="stagger" style="animation-delay: ${staggerDelay}ms">
237
241
  <circle cx="5" cy="6" r="5" fill="${color}" />
238
242
  <text data-testid="lang-name" x="15" y="10" class='lang-name'>
239
- ${lang.name} ${hideProgress || hideValues ? "" : displayValue}
243
+ ${encodeHTML(lang.name)} ${hideProgress || hideValues ? "" : encodeHTML(displayValue)}
240
244
  </text>
241
245
  </g>
242
246
  `;
@@ -354,6 +358,10 @@ const renderCompactLayout = (langs, width, totalLanguageSize, hideProgress, stat
354
358
  let progressOffset = 0;
355
359
  const compactProgressBar = langs
356
360
  .map((lang) => {
361
+ const langColor = lang.color || DEFAULT_LANG_COLOR;
362
+ if (!isPrefixedHexColor(langColor)) {
363
+ throw new Error(`Invalid language color: "${langColor}"`);
364
+ }
357
365
  const percentage = parseFloat(((lang.size / totalLanguageSize) * offsetWidth).toFixed(2));
358
366
  const progress = percentage < 10 ? percentage + 10 : percentage;
359
367
  const output = `
@@ -364,7 +372,7 @@ const renderCompactLayout = (langs, width, totalLanguageSize, hideProgress, stat
364
372
  y="0"
365
373
  width="${progress}"
366
374
  height="8"
367
- fill="${lang.color || "#858585"}"
375
+ fill="${langColor}"
368
376
  />
369
377
  `;
370
378
  progressOffset += percentage;
@@ -412,17 +420,21 @@ const renderDonutVerticalLayout = (langs, totalLanguageSize, statsFormat, hideVa
412
420
  let startDelayCoefficient = 1;
413
421
  // Generate each donut vertical chart part
414
422
  for (const lang of langs) {
423
+ const langColor = lang.color || DEFAULT_LANG_COLOR;
424
+ if (!isPrefixedHexColor(langColor)) {
425
+ throw new Error(`Invalid language color: "${langColor}"`);
426
+ }
415
427
  const percentage = (lang.size / totalLanguageSize) * 100;
416
428
  const circleLength = totalCircleLength * (percentage / 100);
417
429
  const delay = startDelayCoefficient * 100;
418
430
  circles.push(`
419
431
  <g class="stagger" style="animation-delay: ${delay}ms">
420
- <circle
432
+ <circle
421
433
  cx="150"
422
434
  cy="100"
423
435
  r="${radius}"
424
436
  fill="transparent"
425
- stroke="${lang.color}"
437
+ stroke="${langColor}"
426
438
  stroke-width="25"
427
439
  stroke-dasharray="${totalCircleLength}"
428
440
  stroke-dashoffset="${indent}"
@@ -479,6 +491,10 @@ const renderPieLayout = (langs, totalLanguageSize, statsFormat, hideValues) => {
479
491
  const paths = [];
480
492
  // Generate each pie chart part
481
493
  for (const lang of langs) {
494
+ const langColor = lang.color || DEFAULT_LANG_COLOR;
495
+ if (!isPrefixedHexColor(langColor)) {
496
+ throw new Error(`Invalid language color: "${langColor}"`);
497
+ }
482
498
  if (langs.length === 1) {
483
499
  paths.push(`
484
500
  <circle
@@ -486,7 +502,7 @@ const renderPieLayout = (langs, totalLanguageSize, statsFormat, hideValues) => {
486
502
  cy="${centerY}"
487
503
  r="${radius}"
488
504
  stroke="none"
489
- fill="${lang.color}"
505
+ fill="${langColor}"
490
506
  data-testid="lang-pie"
491
507
  size="100"
492
508
  />
@@ -513,7 +529,7 @@ const renderPieLayout = (langs, totalLanguageSize, statsFormat, hideValues) => {
513
529
  data-testid="lang-pie"
514
530
  size="${percentage}"
515
531
  d="M ${centerX} ${centerY} L ${startPoint.x} ${startPoint.y} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${endPoint.x} ${endPoint.y} Z"
516
- fill="${lang.color}"
532
+ fill="${langColor}"
517
533
  />
518
534
  </g>
519
535
  `);
@@ -582,11 +598,20 @@ const createDonutPaths = (cx, cy, radius, percentages) => {
582
598
  * @returns {string} Donut layout card SVG object.
583
599
  */
584
600
  const renderDonutLayout = (langs, width, totalLanguageSize, statsFormat, hideValues) => {
601
+ if (!Number.isFinite(width)) {
602
+ throw new Error(`Invalid width: "${width}"`);
603
+ }
585
604
  const centerX = width / 3;
586
605
  const centerY = width / 3;
587
606
  const radius = centerX - 60;
588
607
  const strokeWidth = 12;
589
- const colors = langs.map((lang) => lang.color);
608
+ const colors = langs.map((lang) => {
609
+ const langColor = lang.color || DEFAULT_LANG_COLOR;
610
+ if (!isPrefixedHexColor(langColor)) {
611
+ throw new Error(`Invalid language color: "${langColor}"`);
612
+ }
613
+ return langColor;
614
+ });
590
615
  const langsPercents = langs.map((lang) => parseFloat(((lang.size / totalLanguageSize) * 100).toFixed(2)));
591
616
  const langPaths = createDonutPaths(centerX, centerY, radius, langsPercents);
592
617
  const donutPaths = langs.length === 1
@@ -637,8 +662,11 @@ const renderDonutLayout = (langs, width, totalLanguageSize, statsFormat, hideVal
637
662
  * @returns {string} No languages data SVG node string.
638
663
  */
639
664
  const noLanguagesDataNode = ({ color, text, layout }) => {
665
+ if (!isPrefixedHexColor(color)) {
666
+ throw new Error(`Invalid text color: "${color}"`);
667
+ }
640
668
  return `
641
- <text x="${layout === "pie" || layout === "donut-vertical" ? CARD_PADDING : 0}" y="11" class="stat bold" fill="${color}">${text}</text>
669
+ <text x="${layout === "pie" || layout === "donut-vertical" ? CARD_PADDING : 0}" y="11" class="stat bold" fill="${color}">${encodeHTML(text)}</text>
642
670
  `;
643
671
  };
644
672
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"wakatime.d.ts","sourceRoot":"","sources":["../../src/cards/wakatime.js"],"names":[],"mappings":";;;AA6NA;;;GAGG;AAEH;;;;;;GAMG;AACH,2CAJW,OAAO,CAAC,YAAY,CAAC,YACrB,OAAO,CAAC,eAAe,CAAC,GACtB,MAAM,CA2OlB"}
1
+ {"version":3,"file":"wakatime.d.ts","sourceRoot":"","sources":["../../src/cards/wakatime.js"],"names":[],"mappings":";;;AAoPA;;;GAGG;AAEH;;;;;;GAMG;AACH,2CAJW,OAAO,CAAC,YAAY,CAAC,YACrB,OAAO,CAAC,eAAe,CAAC,GACtB,MAAM,CA6OlB"}
@@ -1,6 +1,7 @@
1
1
  import { Card } from "../common/Card.js";
2
2
  import { I18n } from "../common/I18n.js";
3
- import { getCardColors } from "../common/color.js";
3
+ import { getCardColors, isPrefixedHexColor } from "../common/color.js";
4
+ import { encodeHTML } from "../common/html.js";
4
5
  import languageColors from "../common/languageColors.json" with { type: "json" };
5
6
  import { clampValue, lowercaseTrim } from "../common/ops.js";
6
7
  import { createProgressNode, flexLayout } from "../common/render.js";
@@ -22,8 +23,11 @@ const TOTAL_TEXT_WIDTH = 275;
22
23
  * @returns {string} No coding activity SVG node string.
23
24
  */
24
25
  const noCodingActivityNode = ({ color, text }) => {
26
+ if (!isPrefixedHexColor(color)) {
27
+ throw new Error(`Invalid text color: "${color}"`);
28
+ }
25
29
  return `
26
- <text x="25" y="11" class="stat bold" fill="${color}">${text}</text>
30
+ <text x="25" y="11" class="stat bold" fill="${color}">${encodeHTML(text)}</text>
27
31
  `;
28
32
  };
29
33
  /**
@@ -53,6 +57,12 @@ const formatLanguageValue = ({ display_format, lang }) => {
53
57
  * @returns {string} The compact layout language SVG node.
54
58
  */
55
59
  const createCompactLangNode = ({ lang, x, y, display_format }) => {
60
+ if (!Number.isFinite(x)) {
61
+ throw new Error(`Invalid x: "${x}"`);
62
+ }
63
+ if (!Number.isFinite(y)) {
64
+ throw new Error(`Invalid y: "${y}"`);
65
+ }
56
66
  // @ts-ignore
57
67
  const color = languageColors[lang.name] || "#858585";
58
68
  const value = formatLanguageValue({ display_format, lang });
@@ -60,7 +70,7 @@ const createCompactLangNode = ({ lang, x, y, display_format }) => {
60
70
  <g transform="translate(${x}, ${y})">
61
71
  <circle cx="5" cy="6" r="5" fill="${color}" />
62
72
  <text data-testid="lang-name" x="15" y="10" class='lang-name'>
63
- ${lang.name} - ${value}
73
+ ${encodeHTML(lang.name)} - ${encodeHTML(value)}
64
74
  </text>
65
75
  </g>
66
76
  `;
@@ -106,6 +116,12 @@ const createLanguageTextNode = ({ langs, y, display_format, card_width }) => {
106
116
  * @returns {string} The text SVG node.
107
117
  */
108
118
  const createTextNode = ({ id, label, value, index, percent, hideProgress, progressBarColor, progressBarBackgroundColor, progressBarWidth, }) => {
119
+ if (!Number.isFinite(index)) {
120
+ throw new Error(`Invalid index: "${index}"`);
121
+ }
122
+ if (!Number.isFinite(progressBarWidth)) {
123
+ throw new Error(`Invalid progressBarWidth: "${progressBarWidth}"`);
124
+ }
109
125
  const staggerDelay = (index + 3) * 150;
110
126
  const cardProgress = hideProgress
111
127
  ? null
@@ -122,12 +138,12 @@ const createTextNode = ({ id, label, value, index, percent, hideProgress, progre
122
138
  });
123
139
  return `
124
140
  <g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">
125
- <text class="stat bold" y="12.5" data-testid="${id}">${label}:</text>
141
+ <text class="stat bold" y="12.5" data-testid="${encodeHTML(id)}">${encodeHTML(label)}:</text>
126
142
  <text
127
143
  class="stat"
128
144
  x="${hideProgress ? HIDDEN_PROGRESSBAR_PADDING : PROGRESSBAR_PADDING + progressBarWidth}"
129
145
  y="12.5"
130
- >${value}</text>
146
+ >${encodeHTML(value)}</text>
131
147
  ${cardProgress}
132
148
  </g>
133
149
  `;
@@ -154,9 +170,12 @@ const recalculatePercentages = (languages) => {
154
170
  * @param {string} colors.textColor The text color.
155
171
  * @returns {string} Card CSS styles.
156
172
  */
157
- const getStyles = ({
173
+ const getStyles = function ({
158
174
  // eslint-disable-next-line no-unused-vars
159
- titleColor, textColor, }) => {
175
+ titleColor, textColor, }) {
176
+ if (!isPrefixedHexColor(textColor)) {
177
+ throw new Error(`Invalid text color: "${textColor}"`);
178
+ }
160
179
  return `
161
180
  .stat {
162
181
  font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${textColor};
@@ -302,7 +321,9 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
302
321
  // @ts-ignore
303
322
  progressBarColor: titleColor,
304
323
  // @ts-ignore
305
- progressBarBackgroundColor: textColor === titleColor ? bgColor : textColor,
324
+ progressBarBackgroundColor: textColor === titleColor
325
+ ? "#fff0" // transparent
326
+ : textColor,
306
327
  hideProgress: hide_progress,
307
328
  progressBarWidth: normalizedWidth - TOTAL_TEXT_WIDTH,
308
329
  });
@@ -28,6 +28,8 @@ declare class Card {
28
28
  /**
29
29
  * Creates a new card instance.
30
30
  *
31
+ * The caller must ensure that the passed `titlePrefixIcon` is properly sanitized!
32
+ *
31
33
  * @param props Card arguments.
32
34
  * @param props.width Card width.
33
35
  * @param props.height Card height.
@@ -35,7 +37,7 @@ declare class Card {
35
37
  * @param props.colors Card colors arguments.
36
38
  * @param props.customTitle Card custom title.
37
39
  * @param props.defaultTitle Card default title.
38
- * @param props.titlePrefixIcon Card title prefix icon.
40
+ * @param props.titlePrefixIcon Sanitized card title prefix icon.
39
41
  */
40
42
  constructor({ width, height, border_radius, colors, customTitle, defaultTitle, titlePrefixIcon, }: {
41
43
  width?: number;
@@ -57,7 +59,9 @@ declare class Card {
57
59
  desc: string;
58
60
  }): void;
59
61
  /**
60
- * @param value The CSS to add to the card.
62
+ * The caller must ensure that the passed `css` string is properly sanitized!
63
+ *
64
+ * @param value The sanitized CSS to add to the card.
61
65
  */
62
66
  setCSS(value: string): void;
63
67
  /**
@@ -87,7 +91,9 @@ declare class Card {
87
91
  */
88
92
  getAnimations: () => string;
89
93
  /**
90
- * @param body The inner body of the card.
94
+ * The caller must ensure that the passed `body` string is properly sanitized!
95
+ *
96
+ * @param body The sanitized inner body of the card.
91
97
  * @returns The rendered card.
92
98
  */
93
99
  render(body: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../src/common/Card.ts"],"names":[],"mappings":"AAGA,UAAU,UAAU;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IACjC,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,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,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,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;;;;;;;;;;;OAWG;gBACS,EACV,KAAW,EACX,MAAY,EACZ,aAAmB,EACnB,MAAW,EACX,WAAW,EACX,YAAiB,EACjB,eAAe,GAChB,EAAE;QACD,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,UAAU,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B;IAyBD,iBAAiB,IAAI,IAAI;IAIzB;;;;OAIG;IACH,qBAAqB,CAAC,EACpB,KAAK,EACL,IAAI,GACL,EAAE;QACD,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,IAAI;IAKR;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI3B;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAInC;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAOlC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,WAAW,IAAI,MAAM;IAoCrB;;OAEG;IACH,cAAc,IAAI,MAAM;IA0BxB;;;;OAIG;IACH,aAAa,QAAO,MAAM,CAoBxB;IAEF;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAgE7B;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":"AAIA,UAAU,UAAU;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IACjC,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,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,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,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;;;;;;;;;;;;;OAaG;gBACS,EACV,KAAW,EACX,MAAY,EACZ,aAAmB,EACnB,MAAW,EACX,WAAW,EACX,YAAiB,EACjB,eAAe,GAChB,EAAE;QACD,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,UAAU,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B;IAuBD,iBAAiB,IAAI,IAAI;IAIzB;;;;OAIG;IACH,qBAAqB,CAAC,EACpB,KAAK,EACL,IAAI,GACL,EAAE;QACD,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,IAAI;IAKR;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI3B;;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;IA2BxB;;;;OAIG;IACH,aAAa,QAAO,MAAM,CAoBxB;IAEF;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CA0F7B;AAED,OAAO,EAAE,IAAI,EAAE,CAAC;AAChB,eAAe,IAAI,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { isPrefixedHexColor, isValidGradient } from "./color.js";
1
2
  import { encodeHTML } from "./html.js";
2
3
  import { flexLayout } from "./render.js";
3
4
  class Card {
@@ -18,6 +19,8 @@ class Card {
18
19
  /**
19
20
  * Creates a new card instance.
20
21
  *
22
+ * The caller must ensure that the passed `titlePrefixIcon` is properly sanitized!
23
+ *
21
24
  * @param props Card arguments.
22
25
  * @param props.width Card width.
23
26
  * @param props.height Card height.
@@ -25,17 +28,17 @@ class Card {
25
28
  * @param props.colors Card colors arguments.
26
29
  * @param props.customTitle Card custom title.
27
30
  * @param props.defaultTitle Card default title.
28
- * @param props.titlePrefixIcon Card title prefix icon.
31
+ * @param props.titlePrefixIcon Sanitized card title prefix icon.
29
32
  */
30
33
  constructor({ width = 100, height = 100, border_radius = 4.5, colors = {}, customTitle, defaultTitle = "", titlePrefixIcon, }) {
31
34
  this.width = width;
32
35
  this.height = height;
33
36
  this.hideBorder = false;
34
37
  this.hideTitle = false;
35
- this.border_radius = border_radius;
38
+ this.border_radius = parseFloat(String(border_radius));
36
39
  // returns theme based colors with proper overrides and defaults
37
40
  this.colors = colors;
38
- this.title = encodeHTML(customTitle === undefined ? defaultTitle : customTitle);
41
+ this.title = customTitle === undefined ? defaultTitle : customTitle;
39
42
  this.css = "";
40
43
  this.paddingX = 25;
41
44
  this.paddingY = 35;
@@ -57,7 +60,9 @@ class Card {
57
60
  this.a11yDesc = desc;
58
61
  }
59
62
  /**
60
- * @param value The CSS to add to the card.
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;
@@ -72,10 +77,13 @@ class Card {
72
77
  * @param value Whether to hide the title or not.
73
78
  */
74
79
  setHideTitle(value) {
75
- this.hideTitle = value;
76
- if (value) {
80
+ if (value && !this.hideTitle) {
77
81
  this.height -= 30;
78
82
  }
83
+ if (!value && this.hideTitle) {
84
+ this.height += 30;
85
+ }
86
+ this.hideTitle = value;
79
87
  }
80
88
  /**
81
89
  * @param text The title to set.
@@ -93,7 +101,7 @@ class Card {
93
101
  y="0"
94
102
  class="header"
95
103
  data-testid="header"
96
- >${this.title}</text>
104
+ >${encodeHTML(this.title)}</text>
97
105
  `;
98
106
  const prefixIcon = `
99
107
  <svg
@@ -127,9 +135,11 @@ class Card {
127
135
  if (typeof this.colors.bgColor !== "object") {
128
136
  return "";
129
137
  }
138
+ if (!isValidGradient(this.colors.bgColor)) {
139
+ throw new Error(`Invalid gradient: ${this.colors.bgColor.join(",")}`);
140
+ }
130
141
  const gradients = this.colors.bgColor.slice(1);
131
- return typeof this.colors.bgColor === "object"
132
- ? `
142
+ return `
133
143
  <defs>
134
144
  <linearGradient
135
145
  id="gradient"
@@ -137,15 +147,14 @@ class Card {
137
147
  gradientUnits="userSpaceOnUse"
138
148
  >
139
149
  ${gradients
140
- .map((grad, index) => {
141
- const offset = (index * 100) / (gradients.length - 1);
142
- return `<stop offset="${offset}%" stop-color="#${grad}" />`;
143
- })
144
- .join(",")}
150
+ .map((grad, index) => {
151
+ const offset = (index * 100) / (gradients.length - 1);
152
+ return `<stop offset="${offset}%" stop-color="#${grad}" />`;
153
+ })
154
+ .join(",")}
145
155
  </linearGradient>
146
156
  </defs>
147
- `
148
- : "";
157
+ `;
149
158
  }
150
159
  /**
151
160
  * Retrieves css animations for a card.
@@ -174,10 +183,29 @@ class Card {
174
183
  `;
175
184
  };
176
185
  /**
177
- * @param body The inner body of the 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.
178
189
  * @returns The rendered card.
179
190
  */
180
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
+ }
181
209
  return `
182
210
  <svg
183
211
  width="${this.width}"
@@ -188,8 +216,8 @@ class Card {
188
216
  role="img"
189
217
  aria-labelledby="descId"
190
218
  >
191
- <title id="titleId">${this.a11yTitle}</title>
192
- <desc id="descId">${this.a11yDesc}</desc>
219
+ <title id="titleId">${encodeHTML(this.a11yTitle)}</title>
220
+ <desc id="descId">${encodeHTML(this.a11yDesc)}</desc>
193
221
  <style>
194
222
  .header {
195
223
  font: 600 18px 'Segoe UI', Ubuntu, Sans-Serif;
@@ -1,3 +1,37 @@
1
+ /**
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.
8
+ */
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;
1
35
  /**
2
36
  * Retrieves a gradient if color has more than one valid hex codes else a single color.
3
37
  *
@@ -31,13 +65,13 @@ interface CardColors {
31
65
  * @returns Card colors.
32
66
  */
33
67
  declare const getCardColors: ({ title_color, text_color, icon_color, bg_color, border_color, ring_color, theme, }: {
34
- title_color?: string;
35
- text_color?: string;
36
- icon_color?: string;
37
- bg_color?: string;
38
- border_color?: string;
39
- ring_color?: string;
40
- theme?: string;
68
+ title_color?: string | undefined;
69
+ text_color?: string | undefined;
70
+ icon_color?: string | undefined;
71
+ bg_color?: string | undefined;
72
+ border_color?: string | undefined;
73
+ ring_color?: string | undefined;
74
+ theme?: string | undefined;
41
75
  }) => CardColors;
42
- export { fallbackColor, getCardColors };
76
+ export { fallbackColor, getCardColors, findInvalidColor, isValidGradient, isBareHexColor, isPrefixedHexColor, };
43
77
  //# sourceMappingURL=color.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../src/common/color.ts"],"names":[],"mappings":"AA2BA;;;;;;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,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,KAAG,UAuDH,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC"}
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,22 +1,71 @@
1
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})$/;
2
4
  /**
3
- * 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.
4
8
  *
5
- * @param hexColor String to check.
6
- * @returns 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.
7
11
  */
8
- const isValidHexColor = (hexColor) => {
9
- 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);
10
14
  };
11
15
  /**
12
- * 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.
13
19
  *
14
- * @param colors Array of colors.
15
- * @returns 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.
16
22
  */
17
- const isValidGradient = (colors) => {
18
- return (colors.length > 2 &&
19
- 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;
20
69
  };
21
70
  /**
22
71
  * Retrieves a gradient if color has more than one valid hex codes else a single color.
@@ -30,7 +79,7 @@ const fallbackColor = (color, fallbackColor) => {
30
79
  if (colors.length > 1 && isValidGradient(colors)) {
31
80
  return colors;
32
81
  }
33
- if (color !== undefined && isValidHexColor(color)) {
82
+ if (color !== undefined && isBareHexColor(color)) {
34
83
  return `#${color}`;
35
84
  }
36
85
  return fallbackColor;
@@ -77,4 +126,4 @@ const getCardColors = ({ title_color, text_color, icon_color, bg_color, border_c
77
126
  }
78
127
  return { titleColor, iconColor, textColor, bgColor, borderColor, ringColor };
79
128
  };
80
- export { fallbackColor, getCardColors };
129
+ export { fallbackColor, getCardColors, findInvalidColor, isValidGradient, isBareHexColor, isPrefixedHexColor, };
@@ -5,7 +5,7 @@
5
5
  */
6
6
  const encodeHTML = (str) => {
7
7
  return (str
8
- .replace(/[\u00A0-\u9999<>&](?!#)/gim, (i) => {
8
+ .replace(/[\u00A0-\u9999<>&"'](?!#)/gim, (i) => {
9
9
  return `&#${i.charCodeAt(0)};`;
10
10
  })
11
11
  // eslint-disable-next-line no-control-regex
@@ -1,9 +1,18 @@
1
+ import type { AxiosRequestConfig, AxiosResponse } from "axios";
2
+ /** Body of a GraphQL request sent to the GitHub API. */
3
+ interface GraphQLRequest {
4
+ /** The GraphQL query. */
5
+ query: string;
6
+ /** Variables referenced by the query. */
7
+ variables: Record<string, unknown>;
8
+ }
1
9
  /**
2
10
  * Send GraphQL request to GitHub API.
3
11
  *
4
- * @param {import('axios').AxiosRequestConfig['data']} data Request data.
5
- * @param {import('axios').AxiosRequestConfig['headers']} headers Request headers.
6
- * @returns {Promise<any>} Request response.
12
+ * @param data Request data.
13
+ * @param headers Request headers.
14
+ * @returns Request response.
7
15
  */
8
- export function request(data: import("axios").AxiosRequestConfig["data"], headers: import("axios").AxiosRequestConfig["headers"]): Promise<any>;
16
+ declare const request: (data: GraphQLRequest, headers: NonNullable<AxiosRequestConfig["headers"]>) => Promise<AxiosResponse>;
17
+ export { request };
9
18
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/common/http.js"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,8BAJW,OAAO,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC,WAC1C,OAAO,OAAO,EAAE,kBAAkB,CAAC,SAAS,CAAC,GAC3C,OAAO,CAAC,GAAG,CAAC,CASxB"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/common/http.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE/D,wDAAwD;AACxD,UAAU,cAAc;IACtB,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;;;;;GAMG;AACH,QAAA,MAAM,OAAO,GACX,MAAM,cAAc,EACpB,SAAS,WAAW,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,KAClD,OAAO,CAAC,aAAa,CAOvB,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -2,9 +2,9 @@ import axios from "axios";
2
2
  /**
3
3
  * Send GraphQL request to GitHub API.
4
4
  *
5
- * @param {import('axios').AxiosRequestConfig['data']} data Request data.
6
- * @param {import('axios').AxiosRequestConfig['headers']} headers Request headers.
7
- * @returns {Promise<any>} Request response.
5
+ * @param data Request data.
6
+ * @param headers Request headers.
7
+ * @returns Request response.
8
8
  */
9
9
  const request = (data, headers) => {
10
10
  return axios({