mirror of
https://github.com/anuraghazra/github-readme-stats.git
synced 2024-12-21 06:11:29 +08:00
Merge pull request #100 from anuraghazra/refactor-flex
refactor: added FlexLayout for flex layouts
This commit is contained in:
commit
e9dc35318b
@ -1,4 +1,9 @@
|
|||||||
const { kFormatter, encodeHTML, fallbackColor } = require("../src/utils");
|
const {
|
||||||
|
kFormatter,
|
||||||
|
encodeHTML,
|
||||||
|
fallbackColor,
|
||||||
|
FlexLayout,
|
||||||
|
} = require("../src/utils");
|
||||||
const icons = require("./icons");
|
const icons = require("./icons");
|
||||||
|
|
||||||
const renderRepoCard = (repo, options = {}) => {
|
const renderRepoCard = (repo, options = {}) => {
|
||||||
@ -42,6 +47,31 @@ const renderRepoCard = (repo, options = {}) => {
|
|||||||
`
|
`
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
|
const svgLanguage = `
|
||||||
|
<g transform="translate(30, 100)">
|
||||||
|
<circle data-testid="lang-color" cx="0" cy="-5" r="6" fill="${langColor}" />
|
||||||
|
<text data-testid="lang" class="gray" x="15">${langName}</text>
|
||||||
|
</g>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const svgStars =
|
||||||
|
stargazers.totalCount > 0 &&
|
||||||
|
`
|
||||||
|
<svg class="icon" y="-12" viewBox="0 0 16 16" version="1.1" width="16" height="16">
|
||||||
|
${icons.star}
|
||||||
|
</svg>
|
||||||
|
<text data-testid="stargazers" class="gray" x="25">${totalStars}</text>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const svgForks =
|
||||||
|
totalForks > 0 &&
|
||||||
|
`
|
||||||
|
<svg class="icon" y="-12" viewBox="0 0 16 16" version="1.1" width="16" height="16">
|
||||||
|
${icons.fork}
|
||||||
|
</svg>
|
||||||
|
<text data-testid="forkcount" class="gray" x="25">${totalForks}</text>
|
||||||
|
`;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<svg version="1.1" width="400" height="${height}" viewBox="0 0 400 ${height}" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg version="1.1" width="400" height="${height}" viewBox="0 0 400 ${height}" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<style>
|
<style>
|
||||||
@ -62,28 +92,12 @@ const renderRepoCard = (repo, options = {}) => {
|
|||||||
<text x="50" y="38" class="header">${header}</text>
|
<text x="50" y="38" class="header">${header}</text>
|
||||||
<text class="description" x="25" y="70">${encodeHTML(desc)}</text>
|
<text class="description" x="25" y="70">${encodeHTML(desc)}</text>
|
||||||
|
|
||||||
<g transform="translate(30, 100)">
|
${svgLanguage}
|
||||||
<circle data-testid="lang-color" cx="0" cy="-5" r="6" fill="${langColor}" />
|
|
||||||
<text data-testid="lang" class="gray" x="15">${langName}</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
${(stargazers.totalCount > 0) ? `
|
|
||||||
<g transform="translate(${155 - shiftText}, 100)">
|
<g transform="translate(${155 - shiftText}, 100)">
|
||||||
<svg class="icon" y="-12" viewBox="0 0 16 16" version="1.1" width="16" height="16">
|
${FlexLayout({ items: [svgStars, svgForks], gap: 65 }).join("")}
|
||||||
${icons.star}
|
|
||||||
</svg>
|
|
||||||
<text data-testid="stargazers" class="gray" x="25">${totalStars}</text>
|
|
||||||
</g>
|
</g>
|
||||||
` : ''}
|
|
||||||
|
|
||||||
${(totalForks > 0) ? `
|
|
||||||
<g transform="translate(${stargazers.totalCount === 0 ? 155 - shiftText : 220 - shiftText}, 100)">
|
|
||||||
<svg class="icon" y="-12" viewBox="0 0 16 16" version="1.1" width="16" height="16">
|
|
||||||
${icons.fork}
|
|
||||||
</svg>
|
|
||||||
<text data-testid="forkcount" class="gray" x="25">${totalForks}</text>
|
|
||||||
</g>
|
|
||||||
` : ''}
|
|
||||||
</svg>
|
</svg>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
@ -1,22 +1,11 @@
|
|||||||
const { kFormatter, fallbackColor } = require("../src/utils");
|
const { kFormatter, fallbackColor, FlexLayout } = require("../src/utils");
|
||||||
const getStyles = require("./getStyles");
|
const getStyles = require("./getStyles");
|
||||||
const icons = require("./icons");
|
const icons = require("./icons");
|
||||||
|
|
||||||
const createTextNode = ({
|
const createTextNode = ({ icon, label, value, id, index, showIcons }) => {
|
||||||
icon,
|
|
||||||
label,
|
|
||||||
value,
|
|
||||||
id,
|
|
||||||
index,
|
|
||||||
lineHeight,
|
|
||||||
showIcons,
|
|
||||||
}) => {
|
|
||||||
const kValue = kFormatter(value);
|
const kValue = kFormatter(value);
|
||||||
const staggerDelay = (index + 3) * 150;
|
const staggerDelay = (index + 3) * 150;
|
||||||
// manually calculating lineHeight based on index instead of using <tspan dy="" />
|
|
||||||
// to fix firefox layout bug
|
|
||||||
const lheight = lineHeight * (index + 1);
|
|
||||||
const translateY = lheight - lineHeight / 2;
|
|
||||||
const labelOffset = showIcons ? `x="25"` : "";
|
const labelOffset = showIcons ? `x="25"` : "";
|
||||||
const iconSvg = showIcons
|
const iconSvg = showIcons
|
||||||
? `
|
? `
|
||||||
@ -26,7 +15,7 @@ const createTextNode = ({
|
|||||||
`
|
`
|
||||||
: "";
|
: "";
|
||||||
return `
|
return `
|
||||||
<g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, ${translateY})">
|
<g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">
|
||||||
${iconSvg}
|
${iconSvg}
|
||||||
<text class="stat bold" ${labelOffset} y="12.5">${label}:</text>
|
<text class="stat bold" ${labelOffset} y="12.5">${label}:</text>
|
||||||
<text class="stat" x="135" y="12.5" data-testid="${id}">${kValue}</text>
|
<text class="stat" x="135" y="12.5" data-testid="${id}">${kValue}</text>
|
||||||
@ -106,7 +95,6 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
|||||||
createTextNode({
|
createTextNode({
|
||||||
...STATS[key],
|
...STATS[key],
|
||||||
index,
|
index,
|
||||||
lineHeight: lheight,
|
|
||||||
showIcons: show_icons,
|
showIcons: show_icons,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -188,8 +176,12 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
|||||||
})">
|
})">
|
||||||
${rankCircle}
|
${rankCircle}
|
||||||
|
|
||||||
<svg x="0" y="45">
|
<svg x="0" y="55">
|
||||||
${statItems.toString().replace(/\,/gm, "")}
|
${FlexLayout({
|
||||||
|
items: statItems,
|
||||||
|
gap: lheight,
|
||||||
|
direction: "column",
|
||||||
|
}).join("")}
|
||||||
</svg>
|
</svg>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
22
src/utils.js
22
src/utils.js
@ -56,6 +56,27 @@ function request(data, headers) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {String[]} items
|
||||||
|
* @param {Number} gap
|
||||||
|
* @param {string} direction
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Auto layout utility, allows us to layout things
|
||||||
|
* vertically or horizontally with proper gaping
|
||||||
|
*/
|
||||||
|
function FlexLayout({ items, gap, direction }) {
|
||||||
|
// filter() for filtering out empty strings
|
||||||
|
return items.filter(Boolean).map((item, i) => {
|
||||||
|
let transform = `translate(${gap * i}, 0)`;
|
||||||
|
if (direction === "column") {
|
||||||
|
transform = `translate(0, ${gap * i})`;
|
||||||
|
}
|
||||||
|
return `<g transform="${transform}">${item}</g>`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
renderError,
|
renderError,
|
||||||
kFormatter,
|
kFormatter,
|
||||||
@ -64,4 +85,5 @@ module.exports = {
|
|||||||
request,
|
request,
|
||||||
parseBoolean,
|
parseBoolean,
|
||||||
fallbackColor,
|
fallbackColor,
|
||||||
|
FlexLayout,
|
||||||
};
|
};
|
||||||
|
@ -158,4 +158,32 @@ describe("Test renderRepoCard", () => {
|
|||||||
"Archived"
|
"Archived"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not render star count or fork count if either of the are zero", () => {
|
||||||
|
document.body.innerHTML = renderRepoCard({
|
||||||
|
...data_repo.repository,
|
||||||
|
stargazers: { totalCount: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(queryByTestId(document.body, "stargazers")).toBeNull();
|
||||||
|
expect(queryByTestId(document.body, "forkcount")).toBeDefined();
|
||||||
|
|
||||||
|
document.body.innerHTML = renderRepoCard({
|
||||||
|
...data_repo.repository,
|
||||||
|
stargazers: { totalCount: 1 },
|
||||||
|
forkCount: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(queryByTestId(document.body, "stargazers")).toBeDefined();
|
||||||
|
expect(queryByTestId(document.body, "forkcount")).toBeNull();
|
||||||
|
|
||||||
|
document.body.innerHTML = renderRepoCard({
|
||||||
|
...data_repo.repository,
|
||||||
|
stargazers: { totalCount: 0 },
|
||||||
|
forkCount: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(queryByTestId(document.body, "stargazers")).toBeNull();
|
||||||
|
expect(queryByTestId(document.body, "forkcount")).toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -70,7 +70,6 @@ describe("Test renderStatsCard", () => {
|
|||||||
document.body.innerHTML = renderStatsCard(stats);
|
document.body.innerHTML = renderStatsCard(stats);
|
||||||
|
|
||||||
const styleTag = document.querySelector("style");
|
const styleTag = document.querySelector("style");
|
||||||
console.log(styleTag.textContent);
|
|
||||||
const stylesObject = cssToObject(styleTag.textContent);
|
const stylesObject = cssToObject(styleTag.textContent);
|
||||||
|
|
||||||
const headerClassStyles = stylesObject[".header"];
|
const headerClassStyles = stylesObject[".header"];
|
||||||
@ -157,7 +156,6 @@ describe("Test renderStatsCard", () => {
|
|||||||
it("should not have icons if show_icons is false", () => {
|
it("should not have icons if show_icons is false", () => {
|
||||||
document.body.innerHTML = renderStatsCard(stats, { show_icons: false });
|
document.body.innerHTML = renderStatsCard(stats, { show_icons: false });
|
||||||
|
|
||||||
console.log(queryAllByTestId(document.body, "icon"));
|
|
||||||
expect(queryAllByTestId(document.body, "icon")[0]).not.toBeDefined();
|
expect(queryAllByTestId(document.body, "icon")[0]).not.toBeDefined();
|
||||||
expect(queryByTestId(document.body, "stars")).toBeDefined();
|
expect(queryByTestId(document.body, "stars")).toBeDefined();
|
||||||
expect(
|
expect(
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
const { kFormatter, encodeHTML, renderError } = require("../src/utils");
|
const {
|
||||||
|
kFormatter,
|
||||||
|
encodeHTML,
|
||||||
|
renderError,
|
||||||
|
FlexLayout,
|
||||||
|
} = require("../src/utils");
|
||||||
|
|
||||||
describe("Test utils.js", () => {
|
describe("Test utils.js", () => {
|
||||||
it("should test kFormatter", () => {
|
it("should test kFormatter", () => {
|
||||||
@ -23,4 +28,25 @@ describe("Test utils.js", () => {
|
|||||||
"Something went wrong"
|
"Something went wrong"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should test FlexLayout", () => {
|
||||||
|
const layout = FlexLayout({
|
||||||
|
items: ["<text>1</text>", "<text>2</text>"],
|
||||||
|
gap: 60,
|
||||||
|
}).join("");
|
||||||
|
|
||||||
|
expect(layout).toBe(
|
||||||
|
`<g transform=\"translate(0, 0)\"><text>1</text></g><g transform=\"translate(60, 0)\"><text>2</text></g>`
|
||||||
|
);
|
||||||
|
|
||||||
|
const columns = FlexLayout({
|
||||||
|
items: ["<text>1</text>", "<text>2</text>"],
|
||||||
|
gap: 60,
|
||||||
|
direction: "column",
|
||||||
|
}).join("");
|
||||||
|
|
||||||
|
expect(columns).toBe(
|
||||||
|
`<g transform=\"translate(0, 0)\"><text>1</text></g><g transform=\"translate(0, 60)\"><text>2</text></g>`
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user