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(` - ${FlexLayout({ - items: statItems.length - ? statItems - : [ - noCodingActivityNode({ - color: textColor, - text: i18n.t("wakatimecard.nocodingactivity"), - }), - ], - gap: lheight, - direction: "column", - }).join("")} + ${finalLayout} `); }; 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`] = ` +" + + + + undefined + + + + + + + Wakatime Week Stats + + + + + + + + + + Other: + 19 mins + + + + + + + + + + + TypeScript: + 1 min + + + + + + + + + + + + + + " +`; + +exports[`Test Render Wakatime Card should render correctly with compact layout 1`] = ` +" + + + + undefined + + + + + + + Wakatime Week Stats + + + + + + + + + + + + + + + + + + + + + + + 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(); + }); - - - - Wakatime Week Stats - - - + 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", () => {