diff --git a/api/wakatime.js b/api/wakatime.js
index c626cacb54c27..36446bbd9a4f1 100644
--- a/api/wakatime.js
+++ b/api/wakatime.js
@@ -24,6 +24,7 @@ module.exports = async (req, res) => {
hide_progress,
custom_title,
locale,
+ layout,
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");
@@ -60,6 +61,7 @@ module.exports = async (req, res) => {
theme,
hide_progress,
locale: locale ? locale.toLowerCase() : null,
+ layout,
}),
);
} catch (err) {
diff --git a/readme.md b/readme.md
index 87e2fdeada1a6..974ec92532a1a 100644
--- a/readme.md
+++ b/readme.md
@@ -190,6 +190,7 @@ You can provide multiple comma-separated values in bg_color option to render a g
- `line_height` - Sets the line-height between text _(number)_
- `hide_progress` - Hides the progress bar and percentage _(boolean)_
- `custom_title` - Sets a custom title for the card
+- `layout` - Switch between two available layouts `default` & `compact`
---
@@ -287,6 +288,10 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+- Compact layout
+
+[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
+
---
### All Demos
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index d6470758c1bc5..5d8789e12678d 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -4,6 +4,7 @@ const { getStyles } = require("../getStyles");
const { wakatimeCardLocales } = require("../translations");
const { getCardColors, FlexLayout } = require("../common/utils");
const { createProgressNode } = require("../common/createProgressNode");
+const languageColors = require("../common/languageColors.json");
const noCodingActivityNode = ({ color, text }) => {
return `
@@ -11,6 +12,40 @@ const noCodingActivityNode = ({ color, text }) => {
`;
};
+const createCompactLangNode = ({ lang, totalSize, x, y }) => {
+ const color = languageColors[lang.name] || "#858585";
+
+ return `
+
+
+
+ ${lang.name} - ${lang.text}
+
+
+ `;
+};
+
+const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
+ return langs.map((lang, index) => {
+ if (index % 2 === 0) {
+ return createCompactLangNode({
+ lang,
+ x: 25,
+ y: 12.5 * index + y,
+ totalSize,
+ index,
+ });
+ }
+ return createCompactLangNode({
+ lang,
+ x: 230,
+ y: 12.5 + 12.5 * index,
+ totalSize,
+ index,
+ });
+ });
+};
+
const createTextNode = ({
id,
label,
@@ -63,6 +98,7 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
hide_progress,
custom_title,
locale,
+ layout,
} = options;
const i18n = new I18n({
@@ -107,6 +143,68 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
iconColor,
});
+ let finalLayout = "";
+
+ let width = 440;
+
+ // RENDER COMPACT LAYOUT
+ if (layout === "compact") {
+ width = width + 50;
+ height = 90 + Math.round(languages.length / 2) * 25;
+
+ // progressOffset holds the previous language's width and used to offset the next language
+ // so that we can stack them one after another, like this: [--][----][---]
+ let progressOffset = 0;
+ const compactProgressBar = languages
+ .map((lang) => {
+ // const progress = (width * lang.percent) / 100;
+ const progress = ((width - 50) * lang.percent) / 100;
+
+ const languageColor = languageColors[lang.name] || "#858585";
+
+ const output = `
+
+ `;
+ progressOffset += progress;
+ return output;
+ })
+ .join("");
+
+ finalLayout = `
+
+
+
+ ${compactProgressBar}
+ ${createLanguageTextNode({
+ x: 0,
+ y: 25,
+ langs: languages,
+ totalSize: 100,
+ }).join("")}
+ `;
+ } else {
+ finalLayout = FlexLayout({
+ items: statItems.length
+ ? statItems
+ : [
+ noCodingActivityNode({
+ color: textColor,
+ text: i18n.t("wakatimecard.nocodingactivity"),
+ }),
+ ],
+ gap: lheight,
+ direction: "column",
+ }).join("");
+ }
+
const card = new Card({
customTitle: custom_title,
defaultTitle: i18n.t("wakatimecard.title"),
@@ -131,18 +229,7 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
return card.render(`
`);
};
diff --git a/src/common/languageColors.json b/src/common/languageColors.json
new file mode 100644
index 0000000000000..932883ff029c4
--- /dev/null
+++ b/src/common/languageColors.json
@@ -0,0 +1,430 @@
+{
+ "1C Enterprise": "#814CCC",
+ "4D": null,
+ "ABAP": "#E8274B",
+ "ActionScript": "#882B0F",
+ "Ada": "#02f88c",
+ "Agda": "#315665",
+ "AGS Script": "#B9D9FF",
+ "AL": "#3AA2B5",
+ "Alloy": "#64C800",
+ "Alpine Abuild": null,
+ "AMPL": "#E6EFBB",
+ "AngelScript": "#C7D7DC",
+ "ANTLR": "#9DC3FF",
+ "Apex": "#1797c0",
+ "API Blueprint": "#2ACCA8",
+ "APL": "#5A8164",
+ "Apollo Guidance Computer": "#0B3D91",
+ "AppleScript": "#101F1F",
+ "Arc": "#aa2afe",
+ "ASL": null,
+ "ASP.NET": "#9400ff",
+ "AspectJ": "#a957b0",
+ "Assembly": "#6E4C13",
+ "Asymptote": "#ff0000",
+ "ATS": "#1ac620",
+ "Augeas": null,
+ "AutoHotkey": "#6594b9",
+ "AutoIt": "#1C3552",
+ "Awk": null,
+ "Ballerina": "#FF5000",
+ "Batchfile": "#C1F12E",
+ "Befunge": null,
+ "Bison": "#6A463F",
+ "BitBake": null,
+ "Blade": "#f7523f",
+ "BlitzBasic": null,
+ "BlitzMax": "#cd6400",
+ "Bluespec": null,
+ "Boo": "#d4bec1",
+ "Brainfuck": "#2F2530",
+ "Brightscript": null,
+ "C": "#555555",
+ "C#": "#178600",
+ "C++": "#f34b7d",
+ "C2hs Haskell": null,
+ "Cap'n Proto": null,
+ "CartoCSS": null,
+ "Ceylon": "#dfa535",
+ "Chapel": "#8dc63f",
+ "Charity": null,
+ "ChucK": null,
+ "Cirru": "#ccccff",
+ "Clarion": "#db901e",
+ "Classic ASP": "#6a40fd",
+ "Clean": "#3F85AF",
+ "Click": "#E4E6F3",
+ "CLIPS": null,
+ "Clojure": "#db5855",
+ "CMake": null,
+ "COBOL": null,
+ "CodeQL": null,
+ "CoffeeScript": "#244776",
+ "ColdFusion": "#ed2cd6",
+ "ColdFusion CFC": "#ed2cd6",
+ "Common Lisp": "#3fb68b",
+ "Common Workflow Language": "#B5314C",
+ "Component Pascal": "#B0CE4E",
+ "Cool": null,
+ "Coq": null,
+ "Crystal": "#000100",
+ "CSON": "#244776",
+ "Csound": null,
+ "Csound Document": null,
+ "Csound Score": null,
+ "CSS": "#563d7c",
+ "Cuda": "#3A4E3A",
+ "CWeb": null,
+ "Cycript": null,
+ "Cython": null,
+ "D": "#ba595e",
+ "Dafny": "#FFEC25",
+ "Dart": "#00B4AB",
+ "DataWeave": "#003a52",
+ "Dhall": "#dfafff",
+ "DIGITAL Command Language": null,
+ "DM": "#447265",
+ "Dockerfile": "#384d54",
+ "Dogescript": "#cca760",
+ "DTrace": null,
+ "Dylan": "#6c616e",
+ "E": "#ccce35",
+ "eC": "#913960",
+ "ECL": "#8a1267",
+ "ECLiPSe": null,
+ "Eiffel": "#4d6977",
+ "EJS": "#a91e50",
+ "Elixir": "#6e4a7e",
+ "Elm": "#60B5CC",
+ "Emacs Lisp": "#c065db",
+ "EmberScript": "#FFF4F3",
+ "EQ": "#a78649",
+ "Erlang": "#B83998",
+ "F#": "#b845fc",
+ "F*": "#572e30",
+ "Factor": "#636746",
+ "Fancy": "#7b9db4",
+ "Fantom": "#14253c",
+ "Faust": "#c37240",
+ "Filebench WML": null,
+ "Filterscript": null,
+ "fish": null,
+ "FLUX": "#88ccff",
+ "Forth": "#341708",
+ "Fortran": "#4d41b1",
+ "Fortran Free Form": null,
+ "FreeMarker": "#0050b2",
+ "Frege": "#00cafe",
+ "Futhark": "#5f021f",
+ "G-code": "#D08CF2",
+ "Game Maker Language": "#71b417",
+ "GAML": "#FFC766",
+ "GAMS": null,
+ "GAP": null,
+ "GCC Machine Description": null,
+ "GDB": null,
+ "GDScript": "#355570",
+ "Genie": "#fb855d",
+ "Genshi": null,
+ "Gentoo Ebuild": null,
+ "Gentoo Eclass": null,
+ "Gherkin": "#5B2063",
+ "GLSL": null,
+ "Glyph": "#c1ac7f",
+ "Gnuplot": "#f0a9f0",
+ "Go": "#00ADD8",
+ "Golo": "#88562A",
+ "Gosu": "#82937f",
+ "Grace": null,
+ "Grammatical Framework": "#ff0000",
+ "GraphQL": "#e10098",
+ "Groovy": "#e69f56",
+ "Groovy Server Pages": null,
+ "Hack": "#878787",
+ "Haml": "#ece2a9",
+ "Handlebars": "#f7931e",
+ "Harbour": "#0e60e3",
+ "Haskell": "#5e5086",
+ "Haxe": "#df7900",
+ "HCL": null,
+ "HiveQL": "#dce200",
+ "HLSL": null,
+ "HolyC": "#ffefaf",
+ "HTML": "#e34c26",
+ "Hy": "#7790B2",
+ "HyPhy": null,
+ "IDL": "#a3522f",
+ "Idris": "#b30000",
+ "IGOR Pro": "#0000cc",
+ "Inform 7": null,
+ "Inno Setup": null,
+ "Io": "#a9188d",
+ "Ioke": "#078193",
+ "Isabelle": "#FEFE00",
+ "Isabelle ROOT": null,
+ "J": "#9EEDFF",
+ "Jasmin": null,
+ "Java": "#b07219",
+ "Java Server Pages": null,
+ "JavaScript": "#f1e05a",
+ "JavaScript+ERB": null,
+ "JFlex": "#DBCA00",
+ "Jison": null,
+ "Jison Lex": null,
+ "Jolie": "#843179",
+ "JSONiq": "#40d47e",
+ "Jsonnet": "#0064bd",
+ "JSX": null,
+ "Julia": "#a270ba",
+ "Jupyter Notebook": "#DA5B0B",
+ "Kaitai Struct": "#773b37",
+ "Kotlin": "#F18E33",
+ "KRL": "#28430A",
+ "LabVIEW": null,
+ "Lasso": "#999999",
+ "Latte": "#f2a542",
+ "Lean": null,
+ "Less": "#1d365d",
+ "Lex": "#DBCA00",
+ "LFE": "#4C3023",
+ "LilyPond": null,
+ "Limbo": null,
+ "Literate Agda": null,
+ "Literate CoffeeScript": null,
+ "Literate Haskell": null,
+ "LiveScript": "#499886",
+ "LLVM": "#185619",
+ "Logos": null,
+ "Logtalk": null,
+ "LOLCODE": "#cc9900",
+ "LookML": "#652B81",
+ "LoomScript": null,
+ "LSL": "#3d9970",
+ "Lua": "#000080",
+ "M": null,
+ "M4": null,
+ "M4Sugar": null,
+ "Macaulay2": "#d8ffff",
+ "Makefile": "#427819",
+ "Mako": null,
+ "Markdown": "#083fa1",
+ "Marko": "#42bff2",
+ "Mask": "#f97732",
+ "Mathematica": null,
+ "MATLAB": "#e16737",
+ "Max": "#c4a79c",
+ "MAXScript": "#00a6a6",
+ "mcfunction": "#E22837",
+ "Mercury": "#ff2b2b",
+ "Meson": "#007800",
+ "Metal": "#8f14e9",
+ "MiniD": null,
+ "Mirah": "#c7a938",
+ "mIRC Script": "#3d57c3",
+ "MLIR": "#5EC8DB",
+ "Modelica": null,
+ "Modula-2": null,
+ "Modula-3": "#223388",
+ "Module Management System": null,
+ "Monkey": null,
+ "Moocode": null,
+ "MoonScript": null,
+ "Motorola 68K Assembly": null,
+ "MQL4": "#62A8D6",
+ "MQL5": "#4A76B8",
+ "MTML": "#b7e1f4",
+ "MUF": null,
+ "mupad": null,
+ "Myghty": null,
+ "NASL": null,
+ "NCL": "#28431f",
+ "Nearley": "#990000",
+ "Nemerle": "#3d3c6e",
+ "nesC": "#94B0C7",
+ "NetLinx": "#0aa0ff",
+ "NetLinx+ERB": "#747faa",
+ "NetLogo": "#ff6375",
+ "NewLisp": "#87AED7",
+ "Nextflow": "#3ac486",
+ "Nim": "#ffc200",
+ "Nit": "#009917",
+ "Nix": "#7e7eff",
+ "NSIS": null,
+ "Nu": "#c9df40",
+ "NumPy": "#9C8AF9",
+ "Objective-C": "#438eff",
+ "Objective-C++": "#6866fb",
+ "Objective-J": "#ff0c5a",
+ "ObjectScript": "#424893",
+ "OCaml": "#3be133",
+ "Odin": "#60AFFE",
+ "Omgrofl": "#cabbff",
+ "ooc": "#b0b77e",
+ "Opa": null,
+ "Opal": "#f7ede0",
+ "Open Policy Agent": null,
+ "OpenCL": null,
+ "OpenEdge ABL": null,
+ "OpenQASM": "#AA70FF",
+ "OpenRC runscript": null,
+ "OpenSCAD": null,
+ "Ox": null,
+ "Oxygene": "#cdd0e3",
+ "Oz": "#fab738",
+ "P4": "#7055b5",
+ "Pan": "#cc0000",
+ "Papyrus": "#6600cc",
+ "Parrot": "#f3ca0a",
+ "Parrot Assembly": null,
+ "Parrot Internal Representation": null,
+ "Pascal": "#E3F171",
+ "Pawn": "#dbb284",
+ "Pep8": "#C76F5B",
+ "Perl": "#0298c3",
+ "PHP": "#4F5D95",
+ "PicoLisp": null,
+ "PigLatin": "#fcd7de",
+ "Pike": "#005390",
+ "PLpgSQL": null,
+ "PLSQL": "#dad8d8",
+ "PogoScript": "#d80074",
+ "Pony": null,
+ "PostScript": "#da291c",
+ "POV-Ray SDL": null,
+ "PowerBuilder": "#8f0f8d",
+ "PowerShell": "#012456",
+ "Prisma": "#0c344b",
+ "Processing": "#0096D8",
+ "Prolog": "#74283c",
+ "Propeller Spin": "#7fa2a7",
+ "Pug": "#a86454",
+ "Puppet": "#302B6D",
+ "PureBasic": "#5a6986",
+ "PureScript": "#1D222D",
+ "Python": "#3572A5",
+ "Python console": null,
+ "q": "#0040cd",
+ "Q#": "#fed659",
+ "QMake": null,
+ "QML": "#44a51c",
+ "Qt Script": "#00b841",
+ "Quake": "#882233",
+ "R": "#198CE7",
+ "Racket": "#3c5caa",
+ "Ragel": "#9d5200",
+ "Raku": "#0000fb",
+ "RAML": "#77d9fb",
+ "Rascal": "#fffaa0",
+ "REALbasic": null,
+ "Reason": "#ff5847",
+ "Rebol": "#358a5b",
+ "Red": "#f50000",
+ "Redcode": null,
+ "Ren'Py": "#ff7f7f",
+ "RenderScript": null,
+ "REXX": null,
+ "Ring": "#2D54CB",
+ "Riot": "#A71E49",
+ "RobotFramework": null,
+ "Roff": "#ecdebe",
+ "Rouge": "#cc0088",
+ "RPC": null,
+ "Ruby": "#701516",
+ "RUNOFF": "#665a4e",
+ "Rust": "#dea584",
+ "Sage": null,
+ "SaltStack": "#646464",
+ "SAS": "#B34936",
+ "Sass": "#a53b70",
+ "Scala": "#c22d40",
+ "Scheme": "#1e4aec",
+ "Scilab": null,
+ "SCSS": "#c6538c",
+ "sed": "#64b970",
+ "Self": "#0579aa",
+ "ShaderLab": null,
+ "Shell": "#89e051",
+ "ShellSession": null,
+ "Shen": "#120F14",
+ "Sieve": null,
+ "Slash": "#007eff",
+ "Slice": "#003fa2",
+ "Slim": "#2b2b2b",
+ "Smali": null,
+ "Smalltalk": "#596706",
+ "Smarty": null,
+ "SmPL": "#c94949",
+ "SMT": null,
+ "Solidity": "#AA6746",
+ "SourcePawn": "#f69e1d",
+ "SQF": "#3F3F3F",
+ "SQLPL": null,
+ "Squirrel": "#800000",
+ "SRecode Template": "#348a34",
+ "Stan": "#b2011d",
+ "Standard ML": "#dc566d",
+ "Starlark": "#76d275",
+ "Stata": null,
+ "Stylus": "#ff6347",
+ "SuperCollider": "#46390b",
+ "Svelte": "#ff3e00",
+ "SVG": "#ff9900",
+ "Swift": "#ffac45",
+ "SWIG": null,
+ "SystemVerilog": "#DAE1C2",
+ "Tcl": "#e4cc98",
+ "Tcsh": null,
+ "Terra": "#00004c",
+ "TeX": "#3D6117",
+ "Thrift": null,
+ "TI Program": "#A0AA87",
+ "TLA": null,
+ "TSQL": null,
+ "TSX": null,
+ "Turing": "#cf142b",
+ "Twig": "#c1d026",
+ "TXL": null,
+ "TypeScript": "#2b7489",
+ "Unified Parallel C": "#4e3617",
+ "Unix Assembly": null,
+ "Uno": "#9933cc",
+ "UnrealScript": "#a54c4d",
+ "UrWeb": null,
+ "V": "#4f87c4",
+ "Vala": "#fbe5cd",
+ "VBA": "#867db1",
+ "VBScript": "#15dcdc",
+ "VCL": "#148AA8",
+ "Verilog": "#b2b7f8",
+ "VHDL": "#adb2cb",
+ "Vim script": "#199f4b",
+ "Visual Basic .NET": "#945db7",
+ "Volt": "#1F1F1F",
+ "Vue": "#2c3e50",
+ "wdl": "#42f1f4",
+ "WebAssembly": "#04133b",
+ "WebIDL": null,
+ "wisp": "#7582D1",
+ "Wollok": "#a23738",
+ "X10": "#4B6BEF",
+ "xBase": "#403a40",
+ "XC": "#99DA07",
+ "Xojo": null,
+ "XProc": null,
+ "XQuery": "#5232e7",
+ "XS": null,
+ "XSLT": "#EB8CEB",
+ "Xtend": null,
+ "Yacc": "#4B6C4B",
+ "YAML": "#cb171e",
+ "YARA": "#220000",
+ "YASnippet": "#32AB90",
+ "ZAP": "#0d665e",
+ "Zeek": null,
+ "ZenScript": "#00BCD1",
+ "Zephir": "#118f9e",
+ "Zig": "#ec915c",
+ "ZIL": "#dc75e5",
+ "Zimpl": null
+}
\ No newline at end of file
diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap
new file mode 100644
index 0000000000000..706fcd9fa9514
--- /dev/null
+++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap
@@ -0,0 +1,312 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Test Render Wakatime Card should render correctly 1`] = `
+"
+
+ "
+`;
+
+exports[`Test Render Wakatime Card should render correctly with compact layout 1`] = `
+"
+
+
+
+ undefined
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Other - 19 mins
+
+
+
+
+
+
+ TypeScript - 1 min
+
+
+
+
+
+
+ YAML - 0 secs
+
+
+
+
+
+
+
+
+ "
+`;
diff --git a/tests/renderWakatimeCard.test.js b/tests/renderWakatimeCard.test.js
index 5ea26f1fcda65..2d21c99f48df1 100644
--- a/tests/renderWakatimeCard.test.js
+++ b/tests/renderWakatimeCard.test.js
@@ -5,113 +5,15 @@ const { wakaTimeData } = require("./fetchWakatime.test");
describe("Test Render Wakatime Card", () => {
it("should render correctly", () => {
- const card = renderWakatimeCard(wakaTimeData);
+ const card = renderWakatimeCard(wakaTimeData.data);
- expect(card).toMatchInlineSnapshot(`
- "
-
-
-
- undefined
-
-
+ expect(card).toMatchSnapshot();
+ });
-
-
-
-
-
-
-
+ it("should render correctly with compact layout", () => {
+ const card = renderWakatimeCard(wakaTimeData.data, { layout: "compact" });
-
-
-
-
- No coding activity this week
-
-
-
-
-
- "
- `);
+ expect(card).toMatchSnapshot();
});
it("should render translations", () => {