diff --git a/api/wakatime.js b/api/wakatime.js index 4b9ce1f8404fe..86c26b8104dbd 100644 --- a/api/wakatime.js +++ b/api/wakatime.js @@ -34,6 +34,7 @@ export default async (req, res) => { border_color, display_format, disable_animations, + ordering, } = req.query; res.setHeader("Content-Type", "image/svg+xml"); @@ -107,6 +108,7 @@ export default async (req, res) => { langs_count, display_format, disable_animations: parseBoolean(disable_animations), + ordering, }), ); } catch (err) { @@ -126,4 +128,4 @@ export default async (req, res) => { }), ); } -}; +}; \ No newline at end of file diff --git a/readme.md b/readme.md index 00eb0a135d9c9..b2a3d485d75ea 100644 --- a/readme.md +++ b/readme.md @@ -657,6 +657,7 @@ You can customize the appearance and behavior of the WakaTime stats card using t | `api_domain` | Sets a custom API domain for the card, e.g. to use services like [Hakatime](https://github.com/mujx/hakatime) or [Wakapi](https://github.com/muety/wakapi) | string | `wakatime.com` | | `display_format` | Sets the WakaTime stats display format. Choose `time` to display time-based stats or `percent` to show percentages. | enum | `time` | | `disable_animations` | Disables all animations in the card. | boolean | `false` | +| `ordering` | Only effective when `layout=compact`. Sets the ordering algorithm for the languages in a two-column layout. `horizontal` alternates items left and right (zig-zag pattern), while `vertical` fills the left column first, then the right column. | enum | `horizontal` | ### Demo @@ -915,4 +916,4 @@ Thanks! :heart: Contributions are welcome! <3 -Made with :heart: and JavaScript. +Made with :heart: and JavaScript. \ No newline at end of file diff --git a/src/cards/wakatime.js b/src/cards/wakatime.js index 64ded83d41692..fd78fec371c88 100644 --- a/src/cards/wakatime.js +++ b/src/cards/wakatime.js @@ -1,5 +1,4 @@ // @ts-check - import { Card } from "../common/Card.js"; import { createProgressNode } from "../common/createProgressNode.js"; import { I18n } from "../common/I18n.js"; @@ -90,23 +89,46 @@ const createCompactLangNode = ({ lang, x, y, display_format }) => { * @param {number} args.y The y position of the language node. * @param {"time" | "percent"} args.display_format The display format of the language node. * @param {number} args.card_width Width in px of the card. + * @param {number} args.lineHeight The line height for spacing. + * @param {"horizontal" | "vertical"} args.ordering The ordering of the languages. * @returns {string[]} The language text node items. */ -const createLanguageTextNode = ({ langs, y, display_format, card_width }) => { +const createLanguageTextNode = ({ langs = [], y, display_format, card_width = 495, lineHeight = 25, ordering = "horizontal" }) => { const LEFT_X = 25; const RIGHT_X_BASE = 230; const rightOffset = (card_width - DEFAULT_CARD_WIDTH) / 2; const RIGHT_X = RIGHT_X_BASE + rightOffset; - return langs.map((lang, index) => { - const isLeft = index % 2 === 0; - return createCompactLangNode({ - lang, - x: isLeft ? LEFT_X : RIGHT_X, - y: isLeft ? 12.5 * index + y : 12.5 + 12.5 * index, - display_format, + if (ordering === "horizontal") { + return langs.map((lang, index) => { + const row = Math.floor(index / 2); + const col = index % 2; + return createCompactLangNode({ + lang, + x: col === 0 ? LEFT_X : RIGHT_X, + y: y + lineHeight * row, + display_format, + }); }); - }); + } + + else if (ordering === "vertical") { + const halfLength = Math.ceil(langs.length / 2); + + return langs.map((lang, index) => { + const inLeft = index < halfLength; + const col = inLeft ? 0 : 1; + const row = inLeft ? index : index - halfLength; + return createCompactLangNode({ + lang, + x: col === 0 ? LEFT_X : RIGHT_X, + y: y + lineHeight * row, + display_format, + }); + }); + } + + return []; }; /** @@ -264,6 +286,7 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { border_color, display_format = "time", disable_animations, + ordering = "horizontal", } = options; const normalizedWidth = normalizeCardWidth({ value: card_width, layout }); @@ -319,7 +342,7 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { // RENDER COMPACT LAYOUT if (layout === "compact") { let width = normalizedWidth - 5; - height = 90 + Math.round(filteredLanguages.length / 2) * 25; + height = 90 + Math.round(filteredLanguages.length / 2) * lheight; // 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: [--][----][---] @@ -359,6 +382,8 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { langs: filteredLanguages, display_format, card_width: normalizedWidth, + lineHeight: lheight, + ordering, }).join("") : noCodingActivityNode({ // @ts-ignore @@ -474,4 +499,4 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { }; export { renderWakatimeCard }; -export default renderWakatimeCard; +export default renderWakatimeCard; \ No newline at end of file