From e74b5436019a7f4c425e5f3acb88137187caec0c Mon Sep 17 00:00:00 2001 From: Pranav2612000 Date: Sat, 1 Oct 2022 17:20:47 +0530 Subject: [PATCH 1/4] fix: prevent crash if undefined color is passed to func fallbackColor --- src/common/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/utils.js b/src/common/utils.js index 7660bbd1355d1..7a4beea72df3d 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -105,10 +105,10 @@ function isValidGradient(colors) { * @returns {string | string[]} */ function fallbackColor(color, fallbackColor) { - let colors = color.split(","); + let colors = color?.split(","); let gradient = null; - if (colors.length > 1 && isValidGradient(colors)) { + if (colors?.length > 1 && isValidGradient(colors)) { gradient = colors; } From 603794cd3d994986e6a3e90620f934a700d625b3 Mon Sep 17 00:00:00 2001 From: Pranav2612000 Date: Sat, 1 Oct 2022 17:23:36 +0530 Subject: [PATCH 2/4] feat: allow users to pass ring_color param Before this commit, the ring color was always equal to the title color. This commit allows the user to pass a ring_color property to allow him to style the ring color the way he pleases to. If no ring_color is passed we default to the title color. --- api/index.js | 2 ++ readme.md | 1 + src/cards/stats-card.js | 5 ++++- src/cards/wakatime-card.js | 1 + src/common/utils.js | 10 +++++++++- src/getStyles.js | 5 +++-- tests/api.test.js | 35 +++++++++++++++++++++++++++++++++++ tests/renderStatsCard.test.js | 31 +++++++++++++++++++++++++++++++ tests/utils.test.js | 23 +++++++++++++++++++++++ 9 files changed, 109 insertions(+), 4 deletions(-) diff --git a/api/index.js b/api/index.js index 10dd48478ec6b..d986685440923 100644 --- a/api/index.js +++ b/api/index.js @@ -26,6 +26,7 @@ export default async (req, res) => { include_all_commits, line_height, title_color, + ring_color, icon_color, text_color, text_bold, @@ -76,6 +77,7 @@ export default async (req, res) => { include_all_commits: parseBoolean(include_all_commits), line_height, title_color, + ring_color, icon_color, text_color, text_bold: parseBoolean(text_bold), diff --git a/readme.md b/readme.md index 3ef407248312e..69b7dd20c57ee 100644 --- a/readme.md +++ b/readme.md @@ -197,6 +197,7 @@ You can provide multiple comma-separated values in the bg_color option to render - `custom_title` - Sets a custom title for the card - `text_bold` - Use bold text _(boolean)_ - `disable_animations` - Disables all animations in the card _(boolean)_ +- `ring_color` - Color of the rank circle _(hex color)_ #### Repo Card Exclusive Options: diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js index 4b0cd33a49a21..b178230fbd1eb 100644 --- a/src/cards/stats-card.js +++ b/src/cards/stats-card.js @@ -74,6 +74,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { include_all_commits = false, line_height = 25, title_color, + ring_color, icon_color, text_color, text_bold = true, @@ -89,9 +90,10 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { const lheight = parseInt(String(line_height), 10); // returns theme based colors with proper overrides and defaults - const { titleColor, textColor, iconColor, bgColor, borderColor } = + const { titleColor, ringColor, textColor, iconColor, bgColor, borderColor } = getCardColors({ title_color, + ring_color, icon_color, text_color, bg_color, @@ -185,6 +187,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { const progress = 100 - rank.score; const cssStyles = getStyles({ titleColor, + ringColor, textColor, iconColor, show_icons, diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js index 24571e7fffe82..e5ecacf4fc69b 100644 --- a/src/cards/wakatime-card.js +++ b/src/cards/wakatime-card.js @@ -215,6 +215,7 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { const cssStyles = getStyles({ titleColor, textColor, + ringColor: titleColor, iconColor, }); diff --git a/src/common/utils.js b/src/common/utils.js index 7a4beea72df3d..eb8ddd6c028fe 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -175,6 +175,7 @@ function flexLayout({ items, gap, direction, sizes = [] }) { */ function getCardColors({ title_color, + ring_color, text_color, icon_color, bg_color, @@ -193,6 +194,13 @@ function getCardColors({ title_color || selectedTheme.title_color, "#" + defaultTheme.title_color, ); + + // get the color provided by the user else the theme color + // finally if both colors are invalid we use the titleColor + const ringColor = fallbackColor( + ring_color || selectedTheme.ring_color, + titleColor + ); const iconColor = fallbackColor( icon_color || selectedTheme.icon_color, "#" + defaultTheme.icon_color, @@ -211,7 +219,7 @@ function getCardColors({ "#" + defaultBorderColor, ); - return { titleColor, iconColor, textColor, bgColor, borderColor }; + return { titleColor, ringColor, iconColor, textColor, bgColor, borderColor }; } /** diff --git a/src/getStyles.js b/src/getStyles.js index 3c77787e7e655..f169ccb12a15a 100644 --- a/src/getStyles.js +++ b/src/getStyles.js @@ -63,6 +63,7 @@ const getAnimations = () => { */ const getStyles = ({ titleColor, + ringColor, textColor, iconColor, show_icons, @@ -93,13 +94,13 @@ const getStyles = ({ } .rank-circle-rim { - stroke: ${titleColor}; + stroke: ${ringColor}; fill: none; stroke-width: 6; opacity: 0.2; } .rank-circle { - stroke: ${titleColor}; + stroke: ${ringColor}; stroke-dasharray: 250; fill: none; stroke-width: 6; diff --git a/tests/api.test.js b/tests/api.test.js index b0dfc59f17e2e..5f8a338bc12f1 100644 --- a/tests/api.test.js +++ b/tests/api.test.js @@ -222,4 +222,39 @@ describe("Test /api/", () => { ), ); }); + + it("should allow changing ring_color", async () => { + const { req, res } = faker( + { + username: "anuraghazra", + hide: "issues,prs,contribs", + show_icons: true, + hide_border: true, + line_height: 100, + title_color: "fff", + ring_color: "0000ff", + icon_color: "fff", + text_color: "fff", + bg_color: "fff", + }, + data, + ); + + await api(req, res); + + expect(res.setHeader).toBeCalledWith("Content-Type", "image/svg+xml"); + expect(res.send).toBeCalledWith( + renderStatsCard(stats, { + hide: ["issues", "prs", "contribs"], + show_icons: true, + hide_border: true, + line_height: 100, + title_color: "fff", + ring_color: "0000ff", + icon_color: "fff", + text_color: "fff", + bg_color: "fff", + }), + ); + }); }); diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js index d3155986d0402..3fbdb9b7a3109 100644 --- a/tests/renderStatsCard.test.js +++ b/tests/renderStatsCard.test.js @@ -239,6 +239,37 @@ describe("Test renderStatsCard", () => { ); }); + it("should render custom ring_color properly", () => { + const customColors = { + title_color: "5a0", + ring_color: "0000ff", + icon_color: "1b998b", + text_color: "9991", + bg_color: "252525", + }; + + document.body.innerHTML = renderStatsCard(stats, { ...customColors }); + + const styleTag = document.querySelector("style"); + const stylesObject = cssToObject(styleTag.innerHTML); + + const headerClassStyles = stylesObject[":host"][".header "]; + const statClassStyles = stylesObject[":host"][".stat "]; + const iconClassStyles = stylesObject[":host"][".icon "]; + const rankCircleStyles = stylesObject[":host"][".rank-circle "]; + const rankCircleRimStyles = stylesObject[":host"][".rank-circle-rim "]; + + expect(headerClassStyles.fill.trim()).toBe(`#${customColors.title_color}`); + expect(statClassStyles.fill.trim()).toBe(`#${customColors.text_color}`); + expect(iconClassStyles.fill.trim()).toBe(`#${customColors.icon_color}`); + expect(rankCircleStyles.stroke.trim()).toBe(`#${customColors.ring_color}`); + expect(rankCircleRimStyles.stroke.trim()).toBe(`#${customColors.ring_color}`); + expect(queryByTestId(document.body, "card-bg")).toHaveAttribute( + "fill", + "#252525", + ); + }); + it("should render icons correctly", () => { document.body.innerHTML = renderStatsCard(stats, { show_icons: true, diff --git a/tests/utils.test.js b/tests/utils.test.js index b6e4a3be3f9f9..5f6231cceff2d 100644 --- a/tests/utils.test.js +++ b/tests/utils.test.js @@ -48,6 +48,7 @@ describe("Test utils.js", () => { let colors = getCardColors({ title_color: "f00", text_color: "0f0", + ring_color: "0000ff", icon_color: "00f", bg_color: "fff", border_color: "fff", @@ -57,6 +58,7 @@ describe("Test utils.js", () => { titleColor: "#f00", textColor: "#0f0", iconColor: "#00f", + ringColor: "#0000ff", bgColor: "#fff", borderColor: "#fff", }); @@ -75,6 +77,7 @@ describe("Test utils.js", () => { titleColor: "#2f80ed", textColor: "#0f0", iconColor: "#00f", + ringColor: "#2f80ed", bgColor: "#fff", borderColor: "#e4e2e2", }); @@ -87,11 +90,31 @@ describe("Test utils.js", () => { expect(colors).toStrictEqual({ titleColor: "#fff", textColor: "#9f9f9f", + ringColor: "#fff", iconColor: "#79ff97", bgColor: "#151515", borderColor: "#e4e2e2", }); }); + + it("getCardColors: should return ring color equal to title color if not ring color is defined", () => { + let colors = getCardColors({ + title_color: "f00", + text_color: "0f0", + icon_color: "00f", + bg_color: "fff", + border_color: "fff", + theme: "dark", + }); + expect(colors).toStrictEqual({ + titleColor: "#f00", + textColor: "#0f0", + iconColor: "#00f", + ringColor: "#f00", + bgColor: "#fff", + borderColor: "#fff", + }); + }); }); describe("wrapTextMultiline", () => { From 5d1b6f2e339fa05944ef31ebad6685cd651ad25e Mon Sep 17 00:00:00 2001 From: rickstaa Date: Sat, 8 Oct 2022 17:51:58 +0200 Subject: [PATCH 3/4] docs: improves ring color documentation --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 72d98b35101b4..18f5df5894053 100644 --- a/readme.md +++ b/readme.md @@ -195,7 +195,7 @@ You can provide multiple comma-separated values in the bg_color option to render - `custom_title` - Sets a custom title for the card. Default: ` Github Stats`. - `text_bold` - Use bold text _(boolean)_. Default: `true`. - `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`. -- `ring_color` - Color of the rank circle _(hex color)_ +- `ring_color` - Color of the rank circle _(hex color)_. Defaults to the theme ring color if it exists and otherwise the title color. > **Note** > When hide_rank=`true`, the minimum card width is 270 px + the title length and padding. From 852d97918a68281c479f1aed726f1efde716df97 Mon Sep 17 00:00:00 2001 From: rickstaa Date: Sat, 8 Oct 2022 18:36:42 +0200 Subject: [PATCH 4/4] fix: improve code style --- src/cards/stats-card.js | 6 +++--- src/cards/wakatime-card.js | 1 - src/common/utils.js | 8 ++++---- src/getStyles.js | 2 +- tests/__snapshots__/renderWakatimeCard.test.js.snap | 4 ++-- tests/renderStatsCard.test.js | 4 +++- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js index 0b0632b489a5b..5b21eba19b249 100644 --- a/src/cards/stats-card.js +++ b/src/cards/stats-card.js @@ -105,14 +105,14 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { const lheight = parseInt(String(line_height), 10); // returns theme based colors with proper overrides and defaults - const { titleColor, ringColor, textColor, iconColor, bgColor, borderColor } = + const { titleColor, iconColor, textColor, bgColor, borderColor, ringColor } = getCardColors({ title_color, - ring_color, - icon_color, text_color, + icon_color, bg_color, border_color, + ring_color, theme, }); diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js index 81a7166e654f2..8b042fd2f1a69 100644 --- a/src/cards/wakatime-card.js +++ b/src/cards/wakatime-card.js @@ -221,7 +221,6 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { const cssStyles = getStyles({ titleColor, textColor, - ringColor: titleColor, iconColor, }); diff --git a/src/common/utils.js b/src/common/utils.js index 25218bc59e139..79810f21e0842 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -133,10 +133,10 @@ function isValidGradient(colors) { * @returns {string | string[]} The gradient or color. */ function fallbackColor(color, fallbackColor) { - let colors = color?.split(","); let gradient = null; - if (colors?.length > 1 && isValidGradient(colors)) { + let colors = color ? color.split(",") : []; + if (colors.length > 1 && isValidGradient(colors)) { gradient = colors; } @@ -203,11 +203,11 @@ function flexLayout({ items, gap, direction, sizes = [] }) { */ function getCardColors({ title_color, - ring_color, text_color, icon_color, bg_color, border_color, + ring_color, theme, fallbackTheme = "default", }) { @@ -247,7 +247,7 @@ function getCardColors({ "#" + defaultBorderColor, ); - return { titleColor, ringColor, iconColor, textColor, bgColor, borderColor }; + return { titleColor, iconColor, textColor, bgColor, borderColor, ringColor }; } /** diff --git a/src/getStyles.js b/src/getStyles.js index b2888ee3582d5..f7b90f4adc7b4 100644 --- a/src/getStyles.js +++ b/src/getStyles.js @@ -75,9 +75,9 @@ const getAnimations = () => { */ const getStyles = ({ titleColor, - ringColor, textColor, iconColor, + ringColor, show_icons, progress, }) => { diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap index dd9ffd318a61a..8a73b01eba863 100644 --- a/tests/__snapshots__/renderWakatimeCard.test.js.snap +++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap @@ -51,13 +51,13 @@ exports[`Test Render Wakatime Card should render correctly with compact layout 1 } .rank-circle-rim { - stroke: #2f80ed; + stroke: undefined; fill: none; stroke-width: 6; opacity: 0.2; } .rank-circle { - stroke: #2f80ed; + stroke: undefined; stroke-dasharray: 250; fill: none; stroke-width: 6; diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js index 3fbdb9b7a3109..21ff1a3f269fb 100644 --- a/tests/renderStatsCard.test.js +++ b/tests/renderStatsCard.test.js @@ -263,7 +263,9 @@ describe("Test renderStatsCard", () => { expect(statClassStyles.fill.trim()).toBe(`#${customColors.text_color}`); expect(iconClassStyles.fill.trim()).toBe(`#${customColors.icon_color}`); expect(rankCircleStyles.stroke.trim()).toBe(`#${customColors.ring_color}`); - expect(rankCircleRimStyles.stroke.trim()).toBe(`#${customColors.ring_color}`); + expect(rankCircleRimStyles.stroke.trim()).toBe( + `#${customColors.ring_color}`, + ); expect(queryByTestId(document.body, "card-bg")).toHaveAttribute( "fill", "#252525",