forked from mirrored/github-readme-stats
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3705f73b97 | ||
|
|
99571df33f | ||
|
|
9575f2ea95 | ||
|
|
03d7f85d77 | ||
|
|
075add2e59 | ||
|
|
d4b16d2935 | ||
|
|
5bfccb0faf |
@@ -3,6 +3,7 @@ import { blacklist } from "../src/common/blacklist.js";
|
||||
import {
|
||||
clampValue,
|
||||
CONSTANTS,
|
||||
getBase64URIFromImage,
|
||||
parseBoolean,
|
||||
renderError,
|
||||
} from "../src/common/utils.js";
|
||||
@@ -24,6 +25,7 @@ export default async (req, res) => {
|
||||
locale,
|
||||
border_radius,
|
||||
border_color,
|
||||
show_image,
|
||||
} = req.query;
|
||||
|
||||
res.setHeader("Content-Type", "image/svg+xml");
|
||||
@@ -68,6 +70,10 @@ export default async (req, res) => {
|
||||
}, s-maxage=${cacheSeconds}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
||||
);
|
||||
|
||||
repoData.stringifiedRepoImage = await getBase64URIFromImage(
|
||||
repoData.openGraphImageUrl,
|
||||
);
|
||||
|
||||
return res.send(
|
||||
renderRepoCard(repoData, {
|
||||
hide_border: parseBoolean(hide_border),
|
||||
@@ -80,6 +86,7 @@ export default async (req, res) => {
|
||||
border_color,
|
||||
show_owner: parseBoolean(show_owner),
|
||||
locale: locale ? locale.toLowerCase() : null,
|
||||
show_image: parseBoolean(show_image),
|
||||
}),
|
||||
);
|
||||
} catch (err) {
|
||||
|
||||
@@ -386,6 +386,7 @@ If we don't support your language, please consider contributing! You can find mo
|
||||
#### Repo Card Exclusive Options
|
||||
|
||||
* `show_owner` - Shows the repo's owner name *(boolean)*. Default: `false`.
|
||||
* `show_image` - Shows the repo's social preview image *(boolean)*. Default: `false`.
|
||||
|
||||
#### Gist Card Exclusive Options
|
||||
|
||||
@@ -447,6 +448,11 @@ Use [show\_owner](#repo-card-exclusive-options) query option to include the repo
|
||||
|
||||

|
||||
|
||||
|
||||
Use [show\_image](#repo-card-exclusive-options) query option to include the repo's social preview image header
|
||||
|
||||

|
||||
|
||||
# GitHub Gist Pins
|
||||
|
||||
GitHub gist pins allow you to pin gists in your GitHub profile using a GitHub readme profile.
|
||||
|
||||
@@ -61,6 +61,7 @@ const renderRepoCard = (repo, options = {}) => {
|
||||
isTemplate,
|
||||
starCount,
|
||||
forkCount,
|
||||
stringifiedRepoImage,
|
||||
} = repo;
|
||||
const {
|
||||
hide_border = false,
|
||||
@@ -73,6 +74,7 @@ const renderRepoCard = (repo, options = {}) => {
|
||||
border_radius,
|
||||
border_color,
|
||||
locale,
|
||||
show_image = false,
|
||||
} = options;
|
||||
|
||||
const lineHeight = 10;
|
||||
@@ -141,6 +143,7 @@ const renderRepoCard = (repo, options = {}) => {
|
||||
height,
|
||||
border_radius,
|
||||
colors,
|
||||
stringifiedRepoImage: show_image ? stringifiedRepoImage : "",
|
||||
});
|
||||
|
||||
card.disableAnimations();
|
||||
|
||||
Vendored
+1
@@ -32,6 +32,7 @@ export type StatCardOptions = CommonOptions & {
|
||||
|
||||
export type RepoCardOptions = CommonOptions & {
|
||||
show_owner: boolean;
|
||||
show_image: boolean;
|
||||
};
|
||||
|
||||
export type TopLangOptions = CommonOptions & {
|
||||
|
||||
@@ -11,6 +11,8 @@ class Card {
|
||||
* @param {string?=} args.customTitle Card custom title.
|
||||
* @param {string?=} args.defaultTitle Card default title.
|
||||
* @param {string?=} args.titlePrefixIcon Card title prefix icon.
|
||||
* @param {string?=} args.stringifiedRepoImage Card preview image.
|
||||
* @param {number?=} args.imageHeight Card preview image.
|
||||
* @param {object?=} args.colors Card colors arguments.
|
||||
* @param {string} args.colors.titleColor Card title color.
|
||||
* @param {string} args.colors.textColor Card text color.
|
||||
@@ -27,6 +29,8 @@ class Card {
|
||||
customTitle,
|
||||
defaultTitle = "",
|
||||
titlePrefixIcon,
|
||||
stringifiedRepoImage = "",
|
||||
imageHeight = 200,
|
||||
}) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
@@ -36,6 +40,9 @@ class Card {
|
||||
|
||||
this.border_radius = border_radius;
|
||||
|
||||
this.imageHeight = imageHeight;
|
||||
this.stringifiedRepoImage = stringifiedRepoImage;
|
||||
|
||||
// returns theme based colors with proper overrides and defaults
|
||||
this.colors = colors;
|
||||
this.title =
|
||||
@@ -51,6 +58,10 @@ class Card {
|
||||
this.animations = true;
|
||||
this.a11yTitle = "";
|
||||
this.a11yDesc = "";
|
||||
if (this.stringifiedRepoImage) {
|
||||
this.height += this.imageHeight;
|
||||
this.paddingY += this.imageHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,6 +210,21 @@ class Card {
|
||||
`;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {string} Renders social preview image
|
||||
*/
|
||||
renderImage = () => {
|
||||
if (!this.stringifiedRepoImage) {
|
||||
return "";
|
||||
}
|
||||
return `
|
||||
<g data-testid="card-image" transform="translate(0, 0)">
|
||||
<image x="0" y="0" width="${this.width}" height="${this.imageHeight}"
|
||||
href="${this.stringifiedRepoImage}">
|
||||
</image>
|
||||
</g>`;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} body The inner body of the card.
|
||||
* @returns {string} The rendered card.
|
||||
@@ -264,6 +290,7 @@ class Card {
|
||||
>
|
||||
${body}
|
||||
</g>
|
||||
${this.renderImage()}
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -569,6 +569,27 @@ const dateDiff = (d1, d2) => {
|
||||
return Math.round(diff / (1000 * 60));
|
||||
};
|
||||
|
||||
const getBase64URIFromImage = async (imageURL) => {
|
||||
try {
|
||||
const response = await axios.get(imageURL, {
|
||||
responseType: "arraybuffer",
|
||||
});
|
||||
|
||||
if (response.status === 200) {
|
||||
const base64Image = Buffer.from(response.data, "binary").toString(
|
||||
"base64",
|
||||
);
|
||||
const mimeType = response.headers["content-type"];
|
||||
return `data:${mimeType};base64,${base64Image}`;
|
||||
} else {
|
||||
throw new Error("Failed to fetch the image.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
ERROR_CARD_LENGTH,
|
||||
renderError,
|
||||
@@ -595,4 +616,5 @@ export {
|
||||
chunkArray,
|
||||
parseEmojis,
|
||||
dateDiff,
|
||||
getBase64URIFromImage,
|
||||
};
|
||||
|
||||
@@ -34,6 +34,7 @@ const fetcher = (variables, token) => {
|
||||
name
|
||||
}
|
||||
forkCount
|
||||
openGraphImageUrl
|
||||
}
|
||||
query getRepo($login: String!, $repo: String!) {
|
||||
user(login: $login) {
|
||||
|
||||
Vendored
+1
@@ -22,6 +22,7 @@ export type RepositoryData = {
|
||||
};
|
||||
forkCount: number;
|
||||
starCount: number;
|
||||
stringifiedRepoImage: string;
|
||||
};
|
||||
|
||||
export type StatsData = {
|
||||
|
||||
@@ -150,6 +150,7 @@ exports[`Test Render WakaTime Card should render correctly with compact layout 1
|
||||
</svg>
|
||||
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
"
|
||||
`;
|
||||
@@ -302,6 +303,7 @@ exports[`Test Render WakaTime Card should render correctly with compact layout w
|
||||
</svg>
|
||||
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -18,6 +18,7 @@ const data_repo = {
|
||||
},
|
||||
starCount: 38000,
|
||||
forkCount: 100,
|
||||
stringifiedRepoImage: "data:image/png;base64,base64/image/string",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -339,4 +340,21 @@ describe("Test renderRepoCard", () => {
|
||||
"No description provided",
|
||||
);
|
||||
});
|
||||
|
||||
it("should render repo's social preview image, when show_image is true", () => {
|
||||
document.body.innerHTML = renderRepoCard(data_repo.repository, {
|
||||
show_image: true,
|
||||
});
|
||||
|
||||
expect(queryByTestId(document.body, "card-image")).toBeInTheDocument();
|
||||
expect(
|
||||
queryByTestId(document.body, "card-image").children[0],
|
||||
).toHaveAttribute("href", data_repo.repository.stringifiedRepoImage);
|
||||
});
|
||||
|
||||
it("should not render repo's social preview image by default", () => {
|
||||
document.body.innerHTML = renderRepoCard(data_repo.repository);
|
||||
|
||||
expect(queryByTestId(document.body, "card-image")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user