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", () => {