Skip to content

Commit

Permalink
refactor: jsdoc in utils & minor changes (anuraghazra#1377)
Browse files Browse the repository at this point in the history
* refactor: jsdoc in utils & minor changes

* chore: jsdoc Card class

* chore: jsdoc for getStyles
  • Loading branch information
anuraghazra authored Oct 10, 2021
1 parent d0ab2ff commit 02ebd32
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 41 deletions.
4 changes: 1 addition & 3 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ module.exports = async (req, res) => {
border_radius,
border_color,
} = req.query;
let stats;

res.setHeader("Content-Type", "image/svg+xml");

if (blacklist.includes(username)) {
Expand All @@ -47,7 +45,7 @@ module.exports = async (req, res) => {
}

try {
stats = await fetchStats(
const stats = await fetchStats(
username,
parseBoolean(count_private),
parseBoolean(include_all_commits),
Expand Down
4 changes: 1 addition & 3 deletions api/pin.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ module.exports = async (req, res) => {
border_color,
} = req.query;

let repoData;

res.setHeader("Content-Type", "image/svg+xml");

if (blacklist.includes(username)) {
Expand All @@ -40,7 +38,7 @@ module.exports = async (req, res) => {
}

try {
repoData = await fetchRepo(username, repo);
const repoData = await fetchRepo(username, repo);

let cacheSeconds = clampValue(
parseInt(cache_seconds || CONSTANTS.TWO_HOURS, 10),
Expand Down
4 changes: 1 addition & 3 deletions api/top-langs.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ module.exports = async (req, res) => {
border_radius,
border_color,
} = req.query;
let topLangs;

res.setHeader("Content-Type", "image/svg+xml");

if (blacklist.includes(username)) {
Expand All @@ -44,7 +42,7 @@ module.exports = async (req, res) => {
}

try {
topLangs = await fetchTopLanguages(
const topLangs = await fetchTopLanguages(
username,
parseArray(exclude_repo),
parseArray(hide),
Expand Down
35 changes: 14 additions & 21 deletions src/cards/repo-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,14 @@ const renderRepoCard = (repo, options = {}) => {
});

// 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 colors = getCardColors({
title_color,
icon_color,
text_color,
bg_color,
border_color,
theme,
});

const svgLanguage = primaryLanguage
? createLanguageNode(langName, langColor)
Expand All @@ -145,32 +144,26 @@ const renderRepoCard = (repo, options = {}) => {
width: 400,
height,
border_radius,
colors: {
titleColor,
textColor,
iconColor,
bgColor,
borderColor,
},
colors,
});

card.disableAnimations();
card.setHideBorder(hide_border);
card.setHideTitle(false);
card.setCSS(`
.description { font: 400 13px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
.gray { font: 400 12px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
.icon { fill: ${iconColor} }
.description { font: 400 13px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${colors.textColor} }
.gray { font: 400 12px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${colors.textColor} }
.icon { fill: ${colors.iconColor} }
.badge { font: 600 11px 'Segoe UI', Ubuntu, Sans-Serif; }
.badge rect { opacity: 0.2 }
`);

return card.render(`
${
isTemplate
? getBadgeSVG(i18n.t("repocard.template"), textColor)
? getBadgeSVG(i18n.t("repocard.template"), colors.textColor)
: isArchived
? getBadgeSVG(i18n.t("repocard.archived"), textColor)
? getBadgeSVG(i18n.t("repocard.archived"), colors.textColor)
: ""
}
Expand Down
25 changes: 25 additions & 0 deletions src/common/Card.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ const { getAnimations } = require("../getStyles");
const { flexLayout, encodeHTML } = require("../common/utils");

class Card {
/**
* @param {object} args
* @param {number?=} args.width
* @param {number?=} args.height
* @param {number?=} args.border_radius
* @param {string?=} args.customTitle
* @param {string?=} args.defaultTitle
* @param {string?=} args.titlePrefixIcon
* @param {ReturnType<import('../common/utils').getCardColors>?=} args.colors
*/
constructor({
width = 100,
height = 100,
Expand Down Expand Up @@ -38,21 +48,33 @@ class Card {
this.animations = false;
}

/**
* @param {string} value
*/
setCSS(value) {
this.css = value;
}

/**
* @param {boolean} value
*/
setHideBorder(value) {
this.hideBorder = value;
}

/**
* @param {boolean} value
*/
setHideTitle(value) {
this.hideTitle = value;
if (value) {
this.height -= 30;
}
}

/**
* @param {string} text
*/
setTitle(text) {
this.title = text;
}
Expand Down Expand Up @@ -114,6 +136,9 @@ class Card {
: "";
}

/**
* @param {string} body
*/
render(body) {
return `
<svg
Expand Down
88 changes: 81 additions & 7 deletions src/common/utils.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
// @ts-check
const axios = require("axios");
const wrap = require("word-wrap");
const themes = require("../../themes");
const toEmoji = require("emoji-name-map");

/**
* @param {string} message
* @param {string} secondaryMessage
* @returns {string}
*/
const renderError = (message, secondaryMessage = "") => {
return `
<svg width="495" height="120" viewBox="0 0 495 120" fill="none" xmlns="http://www.w3.org/2000/svg">
Expand All @@ -21,7 +27,11 @@ const renderError = (message, secondaryMessage = "") => {
`;
};

// https://stackoverflow.com/a/48073476/10629172
/**
* @see https://stackoverflow.com/a/48073476/10629172
* @param {string} str
* @returns {string}
*/
function encodeHTML(str) {
return str
.replace(/[\u00A0-\u9999<>&](?!#)/gim, (i) => {
Expand All @@ -30,18 +40,29 @@ function encodeHTML(str) {
.replace(/\u0008/gim, "");
}

/**
* @param {number} num
*/
function kFormatter(num) {
return Math.abs(num) > 999
? Math.sign(num) * (Math.abs(num) / 1000).toFixed(1) + "k"
? Math.sign(num) * parseFloat((Math.abs(num) / 1000).toFixed(1)) + "k"
: Math.sign(num) * Math.abs(num);
}

/**
* @param {string} hexColor
* @returns {boolean}
*/
function isValidHexColor(hexColor) {
return new RegExp(
/^([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{4})$/,
).test(hexColor);
}

/**
* @param {string} value
* @returns {boolean | string}
*/
function parseBoolean(value) {
if (value === "true") {
return true;
Expand All @@ -52,19 +73,37 @@ function parseBoolean(value) {
}
}

/**
* @param {string} str
*/
function parseArray(str) {
if (!str) return [];
return str.split(",");
}

/**
* @param {number} number
* @param {number} min
* @param {number} max
*/
function clampValue(number, min, max) {
// @ts-ignore
if (Number.isNaN(parseInt(number))) return min;
return Math.max(min, Math.min(number, max));
}

/**
* @param {string[]} colors
*/
function isValidGradient(colors) {
return isValidHexColor(colors[1]) && isValidHexColor(colors[2]);
}

/**
* @param {string} color
* @param {string} fallbackColor
* @returns {string | string[]}
*/
function fallbackColor(color, fallbackColor) {
let colors = color.split(",");
let gradient = null;
Expand All @@ -79,7 +118,12 @@ function fallbackColor(color, fallbackColor) {
);
}

/**
* @param {import('axios').AxiosRequestConfig['data']} data
* @param {import('axios').AxiosRequestConfig['headers']} headers
*/
function request(data, headers) {
// @ts-ignore
return axios({
url: "https://api.github.com/graphql",
method: "post",
Expand All @@ -92,8 +136,8 @@ function request(data, headers) {
* @param {object} props
* @param {string[]} props.items
* @param {number} props.gap
* @param {number[]} props.sizes
* @param {"column" | "row"} props.direction
* @param {number[]?=} props.sizes
* @param {"column" | "row"?=} props.direction
*
* @returns {string[]}
*
Expand All @@ -115,14 +159,27 @@ function flexLayout({ items, gap, direction, sizes = [] }) {
});
}

// returns theme based colors with proper overrides and defaults
/**
* @typedef {object} CardColors
* @prop {string} title_color
* @prop {string} text_color
* @prop {string} icon_color
* @prop {string} bg_color
* @prop {string} border_color
* @prop {keyof typeof import('../../themes')?=} fallbackTheme
* @prop {keyof typeof import('../../themes')?=} theme
*/
/**
* returns theme based colors with proper overrides and defaults
* @param {CardColors} options
*/
function getCardColors({
title_color,
text_color,
icon_color,
bg_color,
theme,
border_color,
theme,
fallbackTheme = "default",
}) {
const defaultTheme = themes[fallbackTheme];
Expand Down Expand Up @@ -157,6 +214,12 @@ function getCardColors({
return { titleColor, iconColor, textColor, bgColor, borderColor };
}

/**
* @param {string} text
* @param {number} width
* @param {number} maxLines
* @returns {string[]}
*/
function wrapTextMultiline(text, width = 60, maxLines = 3) {
const wrapped = wrap(encodeHTML(text), { width })
.split("\n") // Split wrapped lines to get an array of lines
Expand Down Expand Up @@ -193,6 +256,10 @@ const SECONDARY_ERROR_MESSAGES = {
};

class CustomError extends Error {
/**
* @param {string} message
* @param {string} type
*/
constructor(message, type) {
super(message);
this.type = type;
Expand All @@ -203,7 +270,12 @@ class CustomError extends Error {
static USER_NOT_FOUND = "USER_NOT_FOUND";
}

// https://stackoverflow.com/a/48172630/10629172
/**
* @see https://stackoverflow.com/a/48172630/10629172
* @param {string} str
* @param {number} fontSize
* @returns
*/
function measureText(str, fontSize = 10) {
// prettier-ignore
const widths = [
Expand Down Expand Up @@ -237,6 +309,8 @@ function measureText(str, fontSize = 10) {
.reduce((cur, acc) => acc + cur) * fontSize
);
}

/** @param {string} name */
const lowercaseTrim = (name) => name.toLowerCase().trim();

/**
Expand Down
Loading

0 comments on commit 02ebd32

Please sign in to comment.