diff --git a/scripts/preview-combined.js b/scripts/preview-combined.js
new file mode 100644
index 0000000..704e2ab
--- /dev/null
+++ b/scripts/preview-combined.js
@@ -0,0 +1,41 @@
+import { renderCombinedCard } from "../src/cards/combined.js";
+import { writeFileSync } from "fs";
+
+const mockData = {
+ overview: {
+ name: "Jason Ernst",
+ totalStars: 1878,
+ totalForks: 243,
+ totalCommits: 25963,
+ linesChanged: 9604194,
+ repoViews: 5487,
+ contributedTo: 167,
+ },
+ streak: {
+ currentStreak: 11,
+ currentStreakStart: "2026-03-09",
+ currentStreakEnd: "2026-03-19",
+ longestStreak: 39,
+ longestStreakStart: "2024-07-22",
+ longestStreakEnd: "2024-08-29",
+ },
+ langs: {
+ Kotlin: { name: "Kotlin", color: "#A97BFF", size: 5296 },
+ C: { name: "C", color: "#555555", size: 898 },
+ Shell: { name: "Shell", color: "#89e051", size: 704 },
+ TypeScript: { name: "TypeScript", color: "#3178c6", size: 663 },
+ Java: { name: "Java", color: "#b07219", size: 500 },
+ JavaScript: { name: "JavaScript", color: "#f1e05a", size: 452 },
+ Python: { name: "Python", color: "#3572A5", size: 347 },
+ Go: { name: "Go", color: "#00ADD8", size: 300 },
+ },
+};
+
+const svg = renderCombinedCard(mockData, {
+ theme: "dark",
+ langs_count: 8,
+ disable_animations: true,
+});
+
+writeFileSync("preview-combined.svg", svg);
+console.log("Written to preview-combined.svg");
diff --git a/src/cards/combined.js b/src/cards/combined.js
index c3acc6c..bf79392 100644
--- a/src/cards/combined.js
+++ b/src/cards/combined.js
@@ -5,7 +5,7 @@ import { getCardColors } from "../common/color.js";
import { icons } from "../common/icons.js";
import { clampValue } from "../common/ops.js";
-const CARD_DEFAULT_WIDTH = 800;
+const CARD_DEFAULT_WIDTH = 550;
const STREAK_COLOR = "#FB8C00";
/**
@@ -92,9 +92,8 @@ const renderCombinedCard = (data, options = {}) => {
const width =
card_width && !isNaN(card_width) ? card_width : CARD_DEFAULT_WIDTH;
- const leftColWidth = width * 0.5;
- const rightColX = leftColWidth + 10;
- const rightColWidth = width - rightColX - 25;
+ const leftColWidth = width * 0.68;
+ const rightColX = leftColWidth + 15;
// Colors.
const { titleColor, iconColor, textColor, bgColor, borderColor } =
@@ -148,8 +147,8 @@ const renderCombinedCard = (data, options = {}) => {
const statsHeight = statsData.length * lineHeight;
// Streak section.
- const streakSectionY = statsHeight + 10;
- const streakHeight = 100;
+ const streakSectionY = statsHeight;
+ const streakHeight = 148;
// Languages.
const langEntries = Object.values(langs);
@@ -175,7 +174,7 @@ const renderCombinedCard = (data, options = {}) => {
${stat.icon}
${stat.label}
- ${stat.value}
+ ${stat.value}
`;
})
@@ -194,99 +193,112 @@ const renderCombinedCard = (data, options = {}) => {
)
: "";
- const streakCenterLeft = leftColWidth * 0.3;
- const streakCenterRight = leftColWidth * 0.7;
- const streakMid = leftColWidth * 0.5;
+ const streakAreaWidth = leftColWidth - 30;
+ const streakCenterLeft = streakAreaWidth * 0.25;
+ const streakCenterRight = streakAreaWidth * 0.7;
const streakSection = `
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+ ${streak.longestStreak}
+
+ Longest Streak
+
+ ${longestDates}
-
+
+
+
+
+
+
+
-
-
-
+
- ${streak.currentStreak}
+ ${streak.currentStreak}
- Current Streak
- ${currentDates}
-
-
-
-
-
- ${streak.longestStreak}
-
- Longest Streak
-
- ${longestDates}
+ ${currentDates}
`;
// Build languages SVG.
- const progressBarWidth = rightColWidth;
- // Create stacked progress bar using SVG offsets.
- let progressOffset = 0;
- const progressSegments = topLangs
- .map((lang) => {
- const percent = (lang.size / totalSize) * progressBarWidth;
- const segment = ``;
- progressOffset += percent;
- return segment;
- })
- .join("");
-
const langItems = topLangs
.map((lang, i) => {
const percent = ((lang.size / totalSize) * 100).toFixed(2);
- const y = i * 20;
+ const y = i * 25;
const staggerDelay = (i + 3) * 150;
return `
-
- ${lang.name} ${percent}%
+
+ ${lang.name} ${percent}%
`;
})
.join("");
- const languagesSection = `
-
-
-
-
- .
+ const lastSvgClose = cardSvg.lastIndexOf("");
+ return (
+ cardSvg.slice(0, lastSvgClose) +
+ progressBarSection +
+ cardSvg.slice(lastSvgClose)
+ );
};
export { renderCombinedCard };