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 {
|
import {
|
||||||
clampValue,
|
clampValue,
|
||||||
CONSTANTS,
|
CONSTANTS,
|
||||||
|
getBase64URIFromImage,
|
||||||
parseBoolean,
|
parseBoolean,
|
||||||
renderError,
|
renderError,
|
||||||
} from "../src/common/utils.js";
|
} from "../src/common/utils.js";
|
||||||
@@ -24,6 +25,7 @@ export default async (req, res) => {
|
|||||||
locale,
|
locale,
|
||||||
border_radius,
|
border_radius,
|
||||||
border_color,
|
border_color,
|
||||||
|
show_image,
|
||||||
} = req.query;
|
} = req.query;
|
||||||
|
|
||||||
res.setHeader("Content-Type", "image/svg+xml");
|
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}`,
|
}, s-maxage=${cacheSeconds}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
repoData.stringifiedRepoImage = await getBase64URIFromImage(
|
||||||
|
repoData.openGraphImageUrl,
|
||||||
|
);
|
||||||
|
|
||||||
return res.send(
|
return res.send(
|
||||||
renderRepoCard(repoData, {
|
renderRepoCard(repoData, {
|
||||||
hide_border: parseBoolean(hide_border),
|
hide_border: parseBoolean(hide_border),
|
||||||
@@ -80,6 +86,7 @@ export default async (req, res) => {
|
|||||||
border_color,
|
border_color,
|
||||||
show_owner: parseBoolean(show_owner),
|
show_owner: parseBoolean(show_owner),
|
||||||
locale: locale ? locale.toLowerCase() : null,
|
locale: locale ? locale.toLowerCase() : null,
|
||||||
|
show_image: parseBoolean(show_image),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -386,6 +386,7 @@ If we don't support your language, please consider contributing! You can find mo
|
|||||||
#### Repo Card Exclusive Options
|
#### Repo Card Exclusive Options
|
||||||
|
|
||||||
* `show_owner` - Shows the repo's owner name *(boolean)*. Default: `false`.
|
* `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
|
#### 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
|
||||||
|
|
||||||
GitHub gist pins allow you to pin gists in your GitHub profile using a GitHub readme profile.
|
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,
|
isTemplate,
|
||||||
starCount,
|
starCount,
|
||||||
forkCount,
|
forkCount,
|
||||||
|
stringifiedRepoImage,
|
||||||
} = repo;
|
} = repo;
|
||||||
const {
|
const {
|
||||||
hide_border = false,
|
hide_border = false,
|
||||||
@@ -73,6 +74,7 @@ const renderRepoCard = (repo, options = {}) => {
|
|||||||
border_radius,
|
border_radius,
|
||||||
border_color,
|
border_color,
|
||||||
locale,
|
locale,
|
||||||
|
show_image = false,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const lineHeight = 10;
|
const lineHeight = 10;
|
||||||
@@ -141,6 +143,7 @@ const renderRepoCard = (repo, options = {}) => {
|
|||||||
height,
|
height,
|
||||||
border_radius,
|
border_radius,
|
||||||
colors,
|
colors,
|
||||||
|
stringifiedRepoImage: show_image ? stringifiedRepoImage : "",
|
||||||
});
|
});
|
||||||
|
|
||||||
card.disableAnimations();
|
card.disableAnimations();
|
||||||
|
|||||||
Vendored
+1
@@ -32,6 +32,7 @@ export type StatCardOptions = CommonOptions & {
|
|||||||
|
|
||||||
export type RepoCardOptions = CommonOptions & {
|
export type RepoCardOptions = CommonOptions & {
|
||||||
show_owner: boolean;
|
show_owner: boolean;
|
||||||
|
show_image: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TopLangOptions = CommonOptions & {
|
export type TopLangOptions = CommonOptions & {
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ class Card {
|
|||||||
* @param {string?=} args.customTitle Card custom title.
|
* @param {string?=} args.customTitle Card custom title.
|
||||||
* @param {string?=} args.defaultTitle Card default title.
|
* @param {string?=} args.defaultTitle Card default title.
|
||||||
* @param {string?=} args.titlePrefixIcon Card title prefix icon.
|
* @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 {object?=} args.colors Card colors arguments.
|
||||||
* @param {string} args.colors.titleColor Card title color.
|
* @param {string} args.colors.titleColor Card title color.
|
||||||
* @param {string} args.colors.textColor Card text color.
|
* @param {string} args.colors.textColor Card text color.
|
||||||
@@ -27,6 +29,8 @@ class Card {
|
|||||||
customTitle,
|
customTitle,
|
||||||
defaultTitle = "",
|
defaultTitle = "",
|
||||||
titlePrefixIcon,
|
titlePrefixIcon,
|
||||||
|
stringifiedRepoImage = "",
|
||||||
|
imageHeight = 200,
|
||||||
}) {
|
}) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
@@ -36,6 +40,9 @@ class Card {
|
|||||||
|
|
||||||
this.border_radius = border_radius;
|
this.border_radius = border_radius;
|
||||||
|
|
||||||
|
this.imageHeight = imageHeight;
|
||||||
|
this.stringifiedRepoImage = stringifiedRepoImage;
|
||||||
|
|
||||||
// returns theme based colors with proper overrides and defaults
|
// returns theme based colors with proper overrides and defaults
|
||||||
this.colors = colors;
|
this.colors = colors;
|
||||||
this.title =
|
this.title =
|
||||||
@@ -51,6 +58,10 @@ class Card {
|
|||||||
this.animations = true;
|
this.animations = true;
|
||||||
this.a11yTitle = "";
|
this.a11yTitle = "";
|
||||||
this.a11yDesc = "";
|
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.
|
* @param {string} body The inner body of the card.
|
||||||
* @returns {string} The rendered card.
|
* @returns {string} The rendered card.
|
||||||
@@ -264,6 +290,7 @@ class Card {
|
|||||||
>
|
>
|
||||||
${body}
|
${body}
|
||||||
</g>
|
</g>
|
||||||
|
${this.renderImage()}
|
||||||
</svg>
|
</svg>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -569,6 +569,27 @@ const dateDiff = (d1, d2) => {
|
|||||||
return Math.round(diff / (1000 * 60));
|
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 {
|
export {
|
||||||
ERROR_CARD_LENGTH,
|
ERROR_CARD_LENGTH,
|
||||||
renderError,
|
renderError,
|
||||||
@@ -595,4 +616,5 @@ export {
|
|||||||
chunkArray,
|
chunkArray,
|
||||||
parseEmojis,
|
parseEmojis,
|
||||||
dateDiff,
|
dateDiff,
|
||||||
|
getBase64URIFromImage,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ const fetcher = (variables, token) => {
|
|||||||
name
|
name
|
||||||
}
|
}
|
||||||
forkCount
|
forkCount
|
||||||
|
openGraphImageUrl
|
||||||
}
|
}
|
||||||
query getRepo($login: String!, $repo: String!) {
|
query getRepo($login: String!, $repo: String!) {
|
||||||
user(login: $login) {
|
user(login: $login) {
|
||||||
|
|||||||
Vendored
+1
@@ -22,6 +22,7 @@ export type RepositoryData = {
|
|||||||
};
|
};
|
||||||
forkCount: number;
|
forkCount: number;
|
||||||
starCount: number;
|
starCount: number;
|
||||||
|
stringifiedRepoImage: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type StatsData = {
|
export type StatsData = {
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ exports[`Test Render WakaTime Card should render correctly with compact layout 1
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
</svg>
|
</svg>
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
@@ -302,6 +303,7 @@ exports[`Test Render WakaTime Card should render correctly with compact layout w
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
</svg>
|
</svg>
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const data_repo = {
|
|||||||
},
|
},
|
||||||
starCount: 38000,
|
starCount: 38000,
|
||||||
forkCount: 100,
|
forkCount: 100,
|
||||||
|
stringifiedRepoImage: "data:image/png;base64,base64/image/string",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -339,4 +340,21 @@ describe("Test renderRepoCard", () => {
|
|||||||
"No description provided",
|
"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