refactor(cards): added typings for cards and fetchers (#1596)
* refactor(cards): added typings for cards and fetchers * chore: move types to separate file
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// @ts-check
|
||||
const {
|
||||
kFormatter,
|
||||
encodeHTML,
|
||||
@@ -65,6 +66,11 @@ const iconWithLabel = (icon, label, testid) => {
|
||||
return flexLayout({ items: [iconSvg, text], gap: 20 }).join("");
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('../fetchers/types').RepositoryData} repo
|
||||
* @param {Partial<import("./types").RepoCardOptions>} options
|
||||
* @returns {string}
|
||||
*/
|
||||
const renderRepoCard = (repo, options = {}) => {
|
||||
const {
|
||||
name,
|
||||
@@ -161,8 +167,10 @@ const renderRepoCard = (repo, options = {}) => {
|
||||
return card.render(`
|
||||
${
|
||||
isTemplate
|
||||
// @ts-ignore
|
||||
? getBadgeSVG(i18n.t("repocard.template"), colors.textColor)
|
||||
: isArchived
|
||||
// @ts-ignore
|
||||
? getBadgeSVG(i18n.t("repocard.archived"), colors.textColor)
|
||||
: ""
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// @ts-check
|
||||
const I18n = require("../common/I18n");
|
||||
const Card = require("../common/Card");
|
||||
const icons = require("../common/icons");
|
||||
@@ -45,6 +46,12 @@ const createTextNode = ({
|
||||
`;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Partial<import('../fetchers/types').StatsData>} stats
|
||||
* @param {Partial<import("./types").StatCardOptions>} options
|
||||
* @returns {string}
|
||||
*/
|
||||
const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
||||
const {
|
||||
name,
|
||||
@@ -75,7 +82,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
||||
disable_animations = false,
|
||||
} = options;
|
||||
|
||||
const lheight = parseInt(line_height, 10);
|
||||
const lheight = parseInt(String(line_height), 10);
|
||||
|
||||
// returns theme based colors with proper overrides and defaults
|
||||
const { titleColor, textColor, iconColor, bgColor, borderColor } =
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// @ts-check
|
||||
const Card = require("../common/Card");
|
||||
const I18n = require("../common/I18n");
|
||||
const { langCardLocales } = require("../translations");
|
||||
@@ -16,6 +17,28 @@ const DEFAULT_LANGS_COUNT = 5;
|
||||
const DEFAULT_LANG_COLOR = "#858585";
|
||||
const CARD_PADDING = 25;
|
||||
|
||||
/**
|
||||
* @typedef {import("../fetchers/types").Lang} Lang
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {Lang[]} arr
|
||||
*/
|
||||
const getLongestLang = (arr) =>
|
||||
arr.reduce(
|
||||
(savedLang, lang) =>
|
||||
lang.name.length > savedLang.name.length ? lang : savedLang,
|
||||
{ name: "", size: null, color: "" },
|
||||
);
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
* width: number,
|
||||
* color: string,
|
||||
* name: string,
|
||||
* progress: string
|
||||
* }} props
|
||||
*/
|
||||
const createProgressTextNode = ({ width, color, name, progress }) => {
|
||||
const paddingRight = 95;
|
||||
const progressTextX = width - paddingRight + 10;
|
||||
@@ -35,6 +58,9 @@ const createProgressTextNode = ({ width, color, name, progress }) => {
|
||||
`;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {{ lang: Lang, totalSize: number }} props
|
||||
*/
|
||||
const createCompactLangNode = ({ lang, totalSize }) => {
|
||||
const percentage = ((lang.size / totalSize) * 100).toFixed(2);
|
||||
const color = lang.color || "#858585";
|
||||
@@ -49,21 +75,19 @@ const createCompactLangNode = ({ lang, totalSize }) => {
|
||||
`;
|
||||
};
|
||||
|
||||
const getLongestLang = (arr) =>
|
||||
arr.reduce(
|
||||
(savedLang, lang) =>
|
||||
lang.name.length > savedLang.name.length ? lang : savedLang,
|
||||
{ name: "" },
|
||||
);
|
||||
|
||||
/**
|
||||
* @param {{ langs: Lang[], totalSize: number }} props
|
||||
*/
|
||||
const createLanguageTextNode = ({ langs, totalSize }) => {
|
||||
const longestLang = getLongestLang(langs);
|
||||
const chunked = chunkArray(langs, langs.length / 2);
|
||||
const layouts = chunked.map((array) => {
|
||||
// @ts-ignore
|
||||
const items = array.map((lang, index) =>
|
||||
createCompactLangNode({
|
||||
lang,
|
||||
totalSize,
|
||||
// @ts-ignore
|
||||
index,
|
||||
}),
|
||||
);
|
||||
@@ -84,8 +108,7 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {any[]} langs
|
||||
* @param {Lang[]} langs
|
||||
* @param {number} width
|
||||
* @param {number} totalLanguageSize
|
||||
* @returns {string}
|
||||
@@ -106,8 +129,7 @@ const renderNormalLayout = (langs, width, totalLanguageSize) => {
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {any[]} langs
|
||||
* @param {Lang[]} langs
|
||||
* @param {number} width
|
||||
* @param {number} totalLanguageSize
|
||||
* @returns {string}
|
||||
@@ -152,7 +174,6 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => {
|
||||
${createLanguageTextNode({
|
||||
langs,
|
||||
totalSize: totalLanguageSize,
|
||||
width,
|
||||
})}
|
||||
</g>
|
||||
`;
|
||||
@@ -174,6 +195,12 @@ const calculateNormalLayoutHeight = (totalLangs) => {
|
||||
return 45 + (totalLangs + 1) * 40;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Record<string, Lang>} topLangs
|
||||
* @param {string[]} hide
|
||||
* @param {string} langs_count
|
||||
*/
|
||||
const useLanguages = (topLangs, hide, langs_count) => {
|
||||
let langs = Object.values(topLangs);
|
||||
let langsToHide = {};
|
||||
@@ -200,6 +227,11 @@ const useLanguages = (topLangs, hide, langs_count) => {
|
||||
return { langs, totalLanguageSize };
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('../fetchers/types').TopLangData} topLangs
|
||||
* @param {Partial<import("./types").TopLangOptions>} options
|
||||
* @returns {string}
|
||||
*/
|
||||
const renderTopLanguages = (topLangs, options = {}) => {
|
||||
const {
|
||||
hide_title,
|
||||
@@ -226,7 +258,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
||||
const { langs, totalLanguageSize } = useLanguages(
|
||||
topLangs,
|
||||
hide,
|
||||
langs_count,
|
||||
String(langs_count),
|
||||
);
|
||||
|
||||
let width = isNaN(card_width) ? DEFAULT_CARD_WIDTH : card_width;
|
||||
|
||||
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
type ThemeNames = keyof typeof import("../../themes");
|
||||
|
||||
export type CommonOptions = {
|
||||
title_color: string;
|
||||
icon_color: string;
|
||||
text_color: string;
|
||||
bg_color: string;
|
||||
theme: ThemeNames;
|
||||
border_radius: number;
|
||||
border_color: string;
|
||||
locale: string;
|
||||
};
|
||||
|
||||
export type StatCardOptions = CommonOptions & {
|
||||
hide: string[];
|
||||
show_icons: boolean;
|
||||
hide_title: boolean;
|
||||
hide_border: boolean;
|
||||
hide_rank: boolean;
|
||||
include_all_commits: boolean;
|
||||
line_height: number | string;
|
||||
custom_title: string;
|
||||
disable_animations: boolean;
|
||||
};
|
||||
|
||||
export type RepoCardOptions = CommonOptions & {
|
||||
hide_border: boolean;
|
||||
show_owner: boolean;
|
||||
};
|
||||
|
||||
export type TopLangOptions = CommonOptions & {
|
||||
hide_title: boolean;
|
||||
hide_border: boolean;
|
||||
card_width: number;
|
||||
hide: string[];
|
||||
layout: "compact" | "normal";
|
||||
custom_title: string;
|
||||
langs_count: number;
|
||||
};
|
||||
|
||||
type WakaTimeOptions = CommonOptions & {
|
||||
hide_title: boolean;
|
||||
hide_border: boolean;
|
||||
hide: string[];
|
||||
line_height: string;
|
||||
hide_progress: boolean;
|
||||
custom_title: string;
|
||||
layout: "compact" | "normal";
|
||||
langs_count: number;
|
||||
};
|
||||
+59
-20
@@ -1,3 +1,4 @@
|
||||
// @ts-check
|
||||
const Card = require("../common/Card");
|
||||
const I18n = require("../common/I18n");
|
||||
const { getStyles } = require("../getStyles");
|
||||
@@ -11,12 +12,24 @@ const {
|
||||
lowercaseTrim,
|
||||
} = require("../common/utils");
|
||||
|
||||
/**
|
||||
* @param {{color: string, text: string}} param0
|
||||
*/
|
||||
const noCodingActivityNode = ({ color, text }) => {
|
||||
return `
|
||||
<text x="25" y="11" class="stat bold" fill="${color}">${text}</text>
|
||||
`;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {{
|
||||
* lang: import("../fetchers/types").WakaTimeLang,
|
||||
* totalSize: number,
|
||||
* x: number,
|
||||
* y: number
|
||||
* }} props
|
||||
*/
|
||||
const createCompactLangNode = ({ lang, totalSize, x, y }) => {
|
||||
const color = languageColors[lang.name] || "#858585";
|
||||
|
||||
@@ -30,6 +43,14 @@ const createCompactLangNode = ({ lang, totalSize, x, y }) => {
|
||||
`;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
* langs: import("../fetchers/types").WakaTimeLang[],
|
||||
* totalSize: number,
|
||||
* x: number,
|
||||
* y: number
|
||||
* }} props
|
||||
*/
|
||||
const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
|
||||
return langs.map((lang, index) => {
|
||||
if (index % 2 === 0) {
|
||||
@@ -38,7 +59,6 @@ const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
|
||||
x: 25,
|
||||
y: 12.5 * index + y,
|
||||
totalSize,
|
||||
index,
|
||||
});
|
||||
}
|
||||
return createCompactLangNode({
|
||||
@@ -46,11 +66,23 @@ const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
|
||||
x: 230,
|
||||
y: 12.5 + 12.5 * index,
|
||||
totalSize,
|
||||
index,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {{
|
||||
* id: string;
|
||||
* label: string;
|
||||
* value: string;
|
||||
* index: number;
|
||||
* percent: number;
|
||||
* hideProgress: boolean;
|
||||
* progressBarColor: string;
|
||||
* progressBarBackgroundColor: string
|
||||
* }} props
|
||||
*/
|
||||
const createTextNode = ({
|
||||
id,
|
||||
label,
|
||||
@@ -71,6 +103,7 @@ const createTextNode = ({
|
||||
progress: percent,
|
||||
color: progressBarColor,
|
||||
width: 220,
|
||||
// @ts-ignore
|
||||
name: label,
|
||||
progressBarBackgroundColor,
|
||||
});
|
||||
@@ -88,6 +121,9 @@ const createTextNode = ({
|
||||
`;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import("../fetchers/types").WakaTimeLang[]} languages
|
||||
*/
|
||||
const recalculatePercentages = (languages) => {
|
||||
// recalculating percentages so that,
|
||||
// compact layout's progress bar does not break when hiding languages
|
||||
@@ -95,12 +131,17 @@ const recalculatePercentages = (languages) => {
|
||||
(totalSum, language) => totalSum + language.percent,
|
||||
0,
|
||||
);
|
||||
const weight = (100 / totalSum).toFixed(2);
|
||||
const weight = +(100 / totalSum).toFixed(2);
|
||||
languages.forEach((language) => {
|
||||
language.percent = (language.percent * weight).toFixed(2);
|
||||
language.percent = +(language.percent * weight).toFixed(2);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Partial<import('../fetchers/types').WakaTimeData>} stats
|
||||
* @param {Partial<import('./types').WakaTimeOptions>} options
|
||||
* @returns {string}
|
||||
*/
|
||||
const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
|
||||
let { languages } = stats;
|
||||
const {
|
||||
@@ -136,25 +177,20 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
|
||||
translations: wakatimeCardLocales,
|
||||
});
|
||||
|
||||
const lheight = parseInt(line_height, 10);
|
||||
const lheight = parseInt(String(line_height), 10);
|
||||
|
||||
const langsCount = clampValue(parseInt(langs_count), 1, langs_count);
|
||||
const langsCount = clampValue(parseInt(String(langs_count)), 1, langs_count);
|
||||
|
||||
// returns theme based colors with proper overrides and defaults
|
||||
const {
|
||||
titleColor,
|
||||
textColor,
|
||||
iconColor,
|
||||
bgColor,
|
||||
borderColor,
|
||||
} = getCardColors({
|
||||
title_color,
|
||||
icon_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
border_color,
|
||||
theme,
|
||||
});
|
||||
const { titleColor, textColor, iconColor, bgColor, borderColor } =
|
||||
getCardColors({
|
||||
title_color,
|
||||
icon_color,
|
||||
text_color,
|
||||
bg_color,
|
||||
border_color,
|
||||
theme,
|
||||
});
|
||||
|
||||
const filteredLanguages = languages
|
||||
? languages
|
||||
@@ -228,13 +264,16 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
|
||||
label: language.name,
|
||||
value: language.text,
|
||||
percent: language.percent,
|
||||
// @ts-ignore
|
||||
progressBarColor: titleColor,
|
||||
// @ts-ignore
|
||||
progressBarBackgroundColor: textColor,
|
||||
hideProgress: hide_progress,
|
||||
});
|
||||
})
|
||||
: [
|
||||
noCodingActivityNode({
|
||||
// @ts-ignore
|
||||
color: textColor,
|
||||
text: i18n.t("wakatimecard.nocodingactivity"),
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user