feat(apps/docs): fix contributors path
This commit is contained in:
parent
924edc017a
commit
26e099e2cf
1 changed files with 129 additions and 114 deletions
|
@ -1,66 +1,66 @@
|
||||||
---
|
---
|
||||||
// fetch all commits for just this page's path
|
// fetch all commits for just this page's path
|
||||||
type Props = {
|
type Props = {
|
||||||
path: string;
|
path: string;
|
||||||
};
|
};
|
||||||
const { path } = Astro.props as Props;
|
const { path } = Astro.props as Props;
|
||||||
const resolvedPath = `examples/docs/${path}`;
|
const resolvedPath = `apps/docs/${path}`;
|
||||||
const url = `https://api.github.com/repos/ayoayco/astro-reactive-library/commits?path=${resolvedPath}`;
|
const url = `https://api.github.com/repos/ayoayco/astro-reactive-library/commits?path=${resolvedPath}`;
|
||||||
const commitsURL = `https://github.com/ayoayco/astro-reactive-library/commits/main/${resolvedPath}`;
|
const commitsURL = `https://github.com/ayoayco/astro-reactive-library/commits/main/${resolvedPath}`;
|
||||||
|
|
||||||
type Commit = {
|
type Commit = {
|
||||||
author: {
|
author: {
|
||||||
id: string;
|
id: string;
|
||||||
login: string;
|
login: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getCommits(url: string) {
|
async function getCommits(url: string) {
|
||||||
try {
|
try {
|
||||||
const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN ?? 'hello';
|
const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN ?? "hello";
|
||||||
if (!token) {
|
if (!token) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.'
|
'Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auth = `Basic ${Buffer.from(token, 'binary').toString('base64')}`;
|
const auth = `Basic ${Buffer.from(token, "binary").toString("base64")}`;
|
||||||
|
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: 'GET',
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: auth,
|
Authorization: auth,
|
||||||
'User-Agent': 'astro-docs/1.0',
|
"User-Agent": "astro-docs/1.0",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Request to fetch commits failed. Reason: ${res.statusText}
|
`Request to fetch commits failed. Reason: ${res.statusText}
|
||||||
Message: ${data.message}`
|
Message: ${data.message}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data as Commit[];
|
return data as Commit[];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(`[error] /src/components/AvatarList.astro
|
console.warn(`[error] /src/components/AvatarList.astro
|
||||||
${(e as any)?.message ?? e}`);
|
${(e as any)?.message ?? e}`);
|
||||||
return [] as Commit[];
|
return [] as Commit[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeDups(arr: Commit[]) {
|
function removeDups(arr: Commit[]) {
|
||||||
const map = new Map<string, Commit['author']>();
|
const map = new Map<string, Commit["author"]>();
|
||||||
|
|
||||||
for (let item of arr) {
|
for (let item of arr) {
|
||||||
const author = item.author;
|
const author = item.author;
|
||||||
// Deduplicate based on author.id
|
// Deduplicate based on author.id
|
||||||
map.set(author.id, { login: author.login, id: author.id });
|
map.set(author.id, { login: author.login, id: author.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...map.values()];
|
return [...map.values()];
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await getCommits(url);
|
const data = await getCommits(url);
|
||||||
|
@ -71,97 +71,112 @@ const additionalContributors = unique.length - recentContributors.length; // lis
|
||||||
|
|
||||||
<!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! -->
|
<!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! -->
|
||||||
<div class="contributors">
|
<div class="contributors">
|
||||||
<ul class="avatar-list" style={`--avatar-count: ${recentContributors.length}`}>
|
<ul
|
||||||
{recentContributors.map((item) => (
|
class="avatar-list"
|
||||||
<li>
|
style={`--avatar-count: ${recentContributors.length}`}
|
||||||
<a href={`https://github.com/${item.login}`}>
|
>
|
||||||
<img
|
{
|
||||||
alt={`Contributor ${item.login}`}
|
recentContributors.map((item) => (
|
||||||
title={`Contributor ${item.login}`}
|
<li>
|
||||||
width="64"
|
<a href={`https://github.com/${item.login}`}>
|
||||||
height="64"
|
<img
|
||||||
src={`https://avatars.githubusercontent.com/u/${item.id}`}
|
alt={`Contributor ${item.login}`}
|
||||||
/>
|
title={`Contributor ${item.login}`}
|
||||||
</a>
|
width="64"
|
||||||
</li>
|
height="64"
|
||||||
))}
|
src={`https://avatars.githubusercontent.com/u/${item.id}`}
|
||||||
</ul>
|
/>
|
||||||
{additionalContributors > 0 && (
|
</a>
|
||||||
<span>
|
</li>
|
||||||
<a href={commitsURL}>{`and ${additionalContributors} additional contributor${
|
))
|
||||||
additionalContributors > 1 ? 's' : ''
|
}
|
||||||
}.`}</a>
|
</ul>
|
||||||
</span>
|
{
|
||||||
)}
|
additionalContributors > 0 && (
|
||||||
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
|
<span>
|
||||||
|
<a
|
||||||
|
href={commitsURL}
|
||||||
|
>{`and ${additionalContributors} additional contributor${
|
||||||
|
additionalContributors > 1 ? "s" : ""
|
||||||
|
}.`}</a>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.avatar-list {
|
.avatar-list {
|
||||||
--avatar-size: 2.5rem;
|
--avatar-size: 2.5rem;
|
||||||
--avatar-count: 3;
|
--avatar-count: 3;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
/* Default to displaying most of the avatar to
|
/* Default to displaying most of the avatar to
|
||||||
enable easier access on touch devices, ensuring
|
enable easier access on touch devices, ensuring
|
||||||
the WCAG touch target size is met or exceeded */
|
the WCAG touch target size is met or exceeded */
|
||||||
grid-template-columns: repeat(var(--avatar-count), max(44px, calc(var(--avatar-size) / 1.15)));
|
grid-template-columns: repeat(
|
||||||
/* `padding` matches added visual dimensions of
|
var(--avatar-count),
|
||||||
|
max(44px, calc(var(--avatar-size) / 1.15))
|
||||||
|
);
|
||||||
|
/* `padding` matches added visual dimensions of
|
||||||
the `box-shadow` to help create a more accurate
|
the `box-shadow` to help create a more accurate
|
||||||
computed component size */
|
computed component size */
|
||||||
padding: 0.08em;
|
padding: 0.08em;
|
||||||
font-size: var(--avatar-size);
|
font-size: var(--avatar-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (any-hover: hover) and (any-pointer: fine) {
|
@media (any-hover: hover) and (any-pointer: fine) {
|
||||||
.avatar-list {
|
.avatar-list {
|
||||||
/* We create 1 extra cell to enable the computed
|
/* We create 1 extra cell to enable the computed
|
||||||
width to match the final visual width */
|
width to match the final visual width */
|
||||||
grid-template-columns: repeat(calc(var(--avatar-count) + 1), calc(var(--avatar-size) / 1.75));
|
grid-template-columns: repeat(
|
||||||
}
|
calc(var(--avatar-count) + 1),
|
||||||
}
|
calc(var(--avatar-size) / 1.75)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.avatar-list li {
|
.avatar-list li {
|
||||||
width: var(--avatar-size);
|
width: var(--avatar-size);
|
||||||
height: var(--avatar-size);
|
height: var(--avatar-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-list li:hover ~ li a,
|
.avatar-list li:hover ~ li a,
|
||||||
.avatar-list li:focus-within ~ li a {
|
.avatar-list li:focus-within ~ li a {
|
||||||
transform: translateX(33%);
|
transform: translateX(33%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-list img,
|
.avatar-list img,
|
||||||
.avatar-list a {
|
.avatar-list a {
|
||||||
display: block;
|
display: block;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-list a {
|
.avatar-list a {
|
||||||
transition: transform 180ms ease-in-out;
|
transition: transform 180ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-list img {
|
.avatar-list img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
|
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-list a:focus {
|
.avatar-list a:focus {
|
||||||
outline: 2px solid transparent;
|
outline: 2px solid transparent;
|
||||||
/* Double-layer trick to work for dark and light backgrounds */
|
/* Double-layer trick to work for dark and light backgrounds */
|
||||||
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
|
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contributors {
|
.contributors {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contributors > * + * {
|
.contributors > * + * {
|
||||||
margin-left: 0.75rem;
|
margin-left: 0.75rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue