Skip to content

Commit 4ccec46

Browse files
fix warnings (#342)
Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
1 parent b81abe0 commit 4ccec46

24 files changed

Lines changed: 1094 additions & 120 deletions

.github/workflows/repeat-recent-requests.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ on:
1313
- cron: "15,45 * * * *"
1414
workflow_dispatch:
1515

16+
permissions: {}
17+
1618
jobs:
1719
triggerRepeatRecent:
1820
if: |

packages/core/src/api/gist.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { renderGistCard } from "../cards/gist.js";
2+
import { findInvalidColor } from "../common/color.js";
23
import {
34
MissingParamError,
45
retrieveSecondaryMessage,
@@ -26,6 +27,23 @@ export default async (
2627
},
2728
pat = null,
2829
) => {
30+
const invalidColorInput = findInvalidColor({
31+
title_color,
32+
icon_color,
33+
text_color,
34+
bg_color,
35+
border_color,
36+
});
37+
if (invalidColorInput) {
38+
return {
39+
status: "error - permanent",
40+
content: renderError({
41+
message: "Something went wrong",
42+
secondaryMessage: `Invalid color input for parameter "${invalidColorInput}"`,
43+
}),
44+
};
45+
}
46+
2947
if (locale && !isLocaleAvailable(locale)) {
3048
return {
3149
status: "error - permanent",

packages/core/src/api/index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { renderStatsCard } from "../cards/stats.js";
2+
import { findInvalidColor } from "../common/color.js";
23
import {
34
MissingParamError,
45
retrieveSecondaryMessage,
@@ -44,6 +45,24 @@ export default async (
4445
},
4546
pat = null,
4647
) => {
48+
const invalidColorInput = findInvalidColor({
49+
title_color,
50+
ring_color,
51+
icon_color,
52+
text_color,
53+
bg_color,
54+
border_color,
55+
});
56+
if (invalidColorInput) {
57+
return {
58+
status: "error - permanent",
59+
content: renderError({
60+
message: "Something went wrong",
61+
secondaryMessage: `Invalid color input for parameter "${invalidColorInput}"`,
62+
}),
63+
};
64+
}
65+
4766
if (locale && !isLocaleAvailable(locale)) {
4867
return {
4968
status: "error - permanent",

packages/core/src/api/pin.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { renderRepoCard } from "../cards/repo.js";
2+
import { findInvalidColor } from "../common/color.js";
23
import {
34
MissingParamError,
45
retrieveSecondaryMessage,
@@ -34,6 +35,23 @@ export default async (
3435
},
3536
pat = null,
3637
) => {
38+
const invalidColorInput = findInvalidColor({
39+
title_color,
40+
icon_color,
41+
text_color,
42+
bg_color,
43+
border_color,
44+
});
45+
if (invalidColorInput) {
46+
return {
47+
status: "error - permanent",
48+
content: renderError({
49+
message: "Something went wrong",
50+
secondaryMessage: `Invalid color input for parameter "${invalidColorInput}"`,
51+
}),
52+
};
53+
}
54+
3755
if (locale && !isLocaleAvailable(locale)) {
3856
return {
3957
status: "error - permanent",

packages/core/src/api/top-langs.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { renderTopLanguages } from "../cards/top-languages.js";
2+
import { findInvalidColor } from "../common/color.js";
23
import {
34
MissingParamError,
45
retrieveSecondaryMessage,
@@ -38,6 +39,23 @@ export default async (
3839
},
3940
pat = null,
4041
) => {
42+
const invalidColorInput = findInvalidColor({
43+
title_color,
44+
text_color,
45+
bg_color,
46+
prog_bar_bg_color,
47+
border_color,
48+
});
49+
if (invalidColorInput) {
50+
return {
51+
status: "error - permanent",
52+
content: renderError({
53+
message: "Something went wrong",
54+
secondaryMessage: `Invalid color input for parameter "${invalidColorInput}"`,
55+
}),
56+
};
57+
}
58+
4159
if (locale && !isLocaleAvailable(locale)) {
4260
return {
4361
status: "error - permanent",

packages/core/src/api/wakatime.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { renderWakatimeCard } from "../cards/wakatime.js";
2+
import { findInvalidColor } from "../common/color.js";
23
import {
34
MissingParamError,
45
retrieveSecondaryMessage,
@@ -32,6 +33,23 @@ export default async ({
3233
display_format,
3334
disable_animations,
3435
}) => {
36+
const invalidColorInput = findInvalidColor({
37+
title_color,
38+
icon_color,
39+
text_color,
40+
bg_color,
41+
border_color,
42+
});
43+
if (invalidColorInput) {
44+
return {
45+
status: "error - permanent",
46+
content: renderError({
47+
message: "Something went wrong",
48+
secondaryMessage: `Invalid color input for parameter "${invalidColorInput}"`,
49+
}),
50+
};
51+
}
52+
3553
if (locale && !isLocaleAvailable(locale)) {
3654
return {
3755
status: "error - permanent",

packages/core/src/cards/repo.js

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Card } from "../common/Card.js";
22
import { I18n } from "../common/I18n.js";
3-
import { getCardColors } from "../common/color.js";
3+
import { getCardColors, isPrefixedHexColor } from "../common/color.js";
44
import { kFormatter, wrapTextMultiline } from "../common/fmt.js";
55
import { encodeHTML } from "../common/html.js";
66
import { icons } from "../common/icons.js";
@@ -32,20 +32,29 @@ const DESCRIPTION_MAX_LINES = 3;
3232
* @param {string} textColor The color of the text.
3333
* @returns {string} Wrapped repo description SVG object.
3434
*/
35-
const getBadgeSVG = (label, textColor, xOffset = 0) => `
36-
<g data-testid="badge" class="badge" transform="translate(${320 + xOffset}, -18)">
37-
<rect stroke="${textColor}" stroke-width="1" width="70" height="20" x="-12" y="-14" ry="10" rx="10"></rect>
38-
<text
39-
x="23" y="-5"
40-
alignment-baseline="central"
41-
dominant-baseline="central"
42-
text-anchor="middle"
43-
fill="${textColor}"
44-
>
45-
${label}
46-
</text>
47-
</g>
48-
`;
35+
const getBadgeSVG = (label, textColor, xOffset = 0) => {
36+
if (!isPrefixedHexColor(textColor)) {
37+
throw new Error(`Invalid text color: "${textColor}"`);
38+
}
39+
if (!Number.isFinite(xOffset)) {
40+
throw new Error(`Invalid xOffset: "${xOffset}"`);
41+
}
42+
43+
return `
44+
<g data-testid="badge" class="badge" transform="translate(${320 + xOffset}, -18)">
45+
<rect stroke="${textColor}" stroke-width="1" width="70" height="20" x="-12" y="-14" ry="10" rx="10"></rect>
46+
<text
47+
x="23" y="-5"
48+
alignment-baseline="central"
49+
dominant-baseline="central"
50+
text-anchor="middle"
51+
fill="${textColor}"
52+
>
53+
${encodeHTML(label)}
54+
</text>
55+
</g>
56+
`;
57+
};
4958

5059
/**
5160
* @typedef {import("../fetchers/types").RepositoryData} RepositoryData Repository data.
@@ -110,14 +119,15 @@ const renderRepoCard = (repo, options = {}) => {
110119
});
111120

112121
let repoFilter = encodeURIComponent(buildSearchFilter([nameWithOwner], []));
122+
const encodedUsername = encodeURIComponent(username);
113123
const STATS = {};
114124
if (show.includes("prs_authored")) {
115125
STATS.prs_authored = {
116126
icon: icons.prs,
117127
label: i18n.t("repocard.prs-authored"),
118128
value: totalPRsAuthored,
119129
id: "prs_authored",
120-
link: `https://github.com/search?q=${repoFilter}author%3A${username}&amp;type=pullrequests`,
130+
link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&amp;type=pullrequests`,
121131
};
122132
}
123133
if (show.includes("prs_commented")) {
@@ -126,7 +136,7 @@ const renderRepoCard = (repo, options = {}) => {
126136
label: i18n.t("repocard.prs-commented"),
127137
value: totalPRsCommented,
128138
id: "prs_commented",
129-
link: `https://github.com/search?q=${repoFilter}commenter%3A${username}+-author%3A${username}&amp;type=pullrequests`,
139+
link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=pullrequests`,
130140
};
131141
}
132142
if (show.includes("prs_reviewed")) {
@@ -135,7 +145,7 @@ const renderRepoCard = (repo, options = {}) => {
135145
label: i18n.t("repocard.prs-reviewed"),
136146
value: totalPRsReviewed,
137147
id: "prs_reviewed",
138-
link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${username}+-author%3A${username}&amp;type=pullrequests`,
148+
link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=pullrequests`,
139149
};
140150
}
141151
if (show.includes("issues_authored")) {
@@ -144,7 +154,7 @@ const renderRepoCard = (repo, options = {}) => {
144154
label: i18n.t("repocard.issues-authored"),
145155
value: totalIssuesAuthored,
146156
id: "issues_authored",
147-
link: `https://github.com/search?q=${repoFilter}author%3A${username}&amp;type=issues`,
157+
link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&amp;type=issues`,
148158
};
149159
}
150160
if (show.includes("issues_commented")) {
@@ -153,7 +163,7 @@ const renderRepoCard = (repo, options = {}) => {
153163
label: i18n.t("repocard.issues-commented"),
154164
value: totalIssuesCommented,
155165
id: "issues_commented",
156-
link: `https://github.com/search?q=${repoFilter}commenter%3A${username}+-author%3A${username}&amp;type=issues`,
166+
link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=issues`,
157167
};
158168
}
159169

packages/core/src/cards/stats.js

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { I18n } from "../common/I18n.js";
33
import { getCardColors } from "../common/color.js";
44
import { CustomError } from "../common/error.js";
55
import { kFormatter } from "../common/fmt.js";
6+
import { encodeHTML } from "../common/html.js";
67
import { icons, rankIcon } from "../common/icons.js";
78
import { buildSearchFilter, clampValue } from "../common/ops.js";
89
import { flexLayout, measureText } from "../common/render.js";
@@ -52,8 +53,10 @@ const LONG_LOCALES = [
5253
/**
5354
* Create a stats card text item.
5455
*
56+
* The caller must ensure that the passed `icon` and `link` are properly sanitized!
57+
*
5558
* @param {object} params Object that contains the createTextNode parameters.
56-
* @param {string} params.icon The icon to display.
59+
* @param {string} params.icon The sanitized icon to display.
5760
* @param {string} params.label The label to display.
5861
* @param {number} params.value The value to display.
5962
* @param {string} params.id The id of the stat.
@@ -64,7 +67,7 @@ const LONG_LOCALES = [
6467
* @param {boolean} params.bold Whether to bold the label.
6568
* @param {string} params.numberFormat The format of numbers on card.
6669
* @param {number=} params.numberPrecision The precision of numbers on card.
67-
* @param {string} params.link Url to link to.
70+
* @param {string} params.link Sanitized url to link to.
6871
* @param {number} params.labelXOffset horizontal offset for label.
6972
* @returns {string} The stats card text item SVG object.
7073
*/
@@ -83,6 +86,16 @@ const createTextNode = ({
8386
link,
8487
labelXOffset = 25,
8588
}) => {
89+
if (!Number.isFinite(labelXOffset)) {
90+
throw new Error(`Invalid labelXOffset: "${labelXOffset}"`);
91+
}
92+
if (!Number.isFinite(shiftValuePos)) {
93+
throw new Error(`Invalid shiftValuePos: "${shiftValuePos}"`);
94+
}
95+
if (!Number.isFinite(index)) {
96+
throw new Error(`Invalid index: "${index}"`);
97+
}
98+
8699
const precision =
87100
typeof numberPrecision === "number" && !isNaN(numberPrecision)
88101
? clampValue(numberPrecision, 0, 2)
@@ -109,7 +122,7 @@ const createTextNode = ({
109122
${iconSvg}
110123
<text class="stat ${
111124
bold ? " bold" : "not_bold"
112-
}" ${labelOffset} y="12.5">${label}:</text>
125+
}" ${labelOffset} y="12.5">${encodeHTML(label)}:</text>
113126
<text
114127
class="stat ${bold ? " bold" : "not_bold"}"
115128
x="${(showIcons ? 140 : 120) + (bold ? 5 : 0) + shiftValuePos}"
@@ -422,13 +435,14 @@ const renderStatsCard = (
422435
}
423436

424437
let repoFilter = encodeURIComponent(buildSearchFilter(repo, owner));
438+
const encodedUsername = encodeURIComponent(username);
425439
if (show.includes("prs_authored")) {
426440
STATS.prs_authored = {
427441
icon: icons.prs,
428442
label: i18n.t("statcard.prs-authored"),
429443
value: totalPRsAuthored,
430444
id: "prs_authored",
431-
link: `https://github.com/search?q=${repoFilter}author%3A${username}&amp;type=pullrequests`,
445+
link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&amp;type=pullrequests`,
432446
};
433447
}
434448
if (show.includes("prs_commented")) {
@@ -437,7 +451,7 @@ const renderStatsCard = (
437451
label: i18n.t("statcard.prs-commented"),
438452
value: totalPRsCommented,
439453
id: "prs_commented",
440-
link: `https://github.com/search?q=${repoFilter}commenter%3A${username}+-author%3A${username}&amp;type=pullrequests`,
454+
link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=pullrequests`,
441455
};
442456
}
443457
if (show.includes("prs_reviewed")) {
@@ -446,7 +460,7 @@ const renderStatsCard = (
446460
label: i18n.t("statcard.prs-reviewed"),
447461
value: totalPRsReviewed,
448462
id: "prs_reviewed",
449-
link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${username}+-author%3A${username}&amp;type=pullrequests`,
463+
link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=pullrequests`,
450464
};
451465
}
452466
if (show.includes("issues_authored")) {
@@ -455,7 +469,7 @@ const renderStatsCard = (
455469
label: i18n.t("statcard.issues-authored"),
456470
value: totalIssuesAuthored,
457471
id: "issues_authored",
458-
link: `https://github.com/search?q=${repoFilter}author%3A${username}&amp;type=issues`,
472+
link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&amp;type=issues`,
459473
};
460474
}
461475
if (show.includes("issues_commented")) {
@@ -464,7 +478,7 @@ const renderStatsCard = (
464478
label: i18n.t("statcard.issues-commented"),
465479
value: totalIssuesCommented,
466480
id: "issues_commented",
467-
link: `https://github.com/search?q=${repoFilter}commenter%3A${username}+-author%3A${username}&amp;type=issues`,
481+
link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&amp;type=issues`,
468482
};
469483
}
470484

0 commit comments

Comments
 (0)