This commit is contained in:
2024-05-15 15:07:03 +02:00
parent 9cdee98114
commit d561dc2452
21 changed files with 9972 additions and 15 deletions

95
src/GithubCard.astro Normal file
View File

@@ -0,0 +1,95 @@
---
interface Props {
owner: string;
repo: string;
target?: string;
auth?: string;
}
const { owner, repo, target = "_blank", auth = "" } = Astro.props;
const iconColor: string = "#6b6b6b";
import { fetchGithubStaticData } from "./github_static_fetch";
import type { Repository } from "./github_static_fetch";
const repository: Repository = await fetchGithubStaticData(owner, repo, auth);
---
<style>
gh-card {
background-color: #00000030;
padding: 20px;
border-radius: 0.375rem;
border: solid 1px #4d4d4d8f;
display: inline-block;
width: 480px;
max-width: 100%;
.iconbox {
display: flex;
align-items: center;
svg {
margin-right: 5px;
margin-bottom: -5px;
}
}
.gh_language_color {
position: relative;
top: 1px;
display: inline-block;
width: 12px;
height: 12px;
border: 1px solid #30363db3;
border-radius: 50%;
}
a::after {
content: "" !important;
}
}
</style>
<script src="./github_dynamic_fetch.ts"></script>
<gh-card owner={owner} repo={repo}>
<div class="iconbox">
<svg
aria-hidden="true"
height="16"
viewBox="0 0 16 16"
version="1.1"
width="16"
data-view-component="true"
>
<path
fill={iconColor}
d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z"
></path>
</svg>
<a href={"https://github.com/" + owner + "/" + repo} target={target}>
{repo}
</a>
</div>
<p style="font-size: 13px; margin:0;">{repository.description}</p>
<div class="iconbox" style="font-size: 13px; margin:0;">
<span
class="gh_language_color"
style={"background-color: " + repository.color + "; margin-right:5px;"}
></span>
<span>{repository.language}</span>
<span id="gh_star_icon" style="margin-left: 15px; visibility: hidden;"
><svg height="16" viewBox="0 0 16 16" width="16">
<path
fill={iconColor}
d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"
></path>
</svg>
</span>
<span id="gh_stars"></span>
<span id="gh_fork_icon" style="margin-left: 15px; visibility: hidden;"
><svg height="16" viewBox="0 0 16 16" width="16">
<path
fill={iconColor}
d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z"
></path>
</svg>
</span>
<span id="gh_forks"></span>
</div>
</gh-card>

View File

@@ -1,8 +0,0 @@
---
// Write your component code in this file!
interface Props {
prefix?: string;
}
---
<div>{Astro.props.prefix} My special component</div>

2558
src/colors.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
interface Repository {
stargazers_count: number;
forks_count: number;
}
class GithubCard extends HTMLElement {
public owner: string;
public repo: string;
private cachedData: Repository | null = null;
public cached: boolean;
constructor() {
super();
this.repo = this.getAttribute("repo") as string;
this.owner = this.getAttribute("owner") as string;
}
static async fetchRepository(owner: string, repo: string): Promise<Repository | null> {
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}`);
if (!response.ok) {
console.log('Failed to fetch repository');
return null;
} else {
const data: Repository = await response.json();
return data;
}
}
update_string() {
if (this.cachedData) {
if (this.cachedData.forks_count != 0) {
showElement(this, "gh_fork_icon");
setString(this, "gh_forks", this.cachedData.forks_count.toString());
}
if (this.cachedData.stargazers_count != 0) {
showElement(this, "gh_star_icon");
setString(this, "gh_stars", this.cachedData.stargazers_count.toString());
}
}
}
async update(): Promise<void> {
const cachedDataKey = `githubCardData_${this.owner}_${this.repo}`;
let cachedData = localStorage.getItem(cachedDataKey);
if (cachedData) {
this.cached = true
this.cachedData = JSON.parse(cachedData);
this.update_string();
}
try {
const freshData = await GithubCard.fetchRepository(this.owner, this.repo);
if (freshData) {
this.cachedData = freshData;
localStorage.setItem(cachedDataKey, JSON.stringify(freshData));
this.update_string();
}
} catch (error) {
console.log('Failed to fetch repository data:', error);
}
}
}
customElements.define('gh-card', GithubCard);
async function updateCards() {
const notCachedCards = Array.from(document.querySelectorAll('gh-card') as NodeListOf<GithubCard>).filter(card =>
!card.cached
);
await Promise.all(notCachedCards.map(async (card) => {
await card.update();
}));
const cachedCards = Array.from(document.querySelectorAll('gh-card') as NodeListOf<GithubCard>).filter(card =>
card.cached
);
await Promise.all(cachedCards.map(async (card) => {
await card.update();
}));
}
updateCards()
function setString(card: GithubCard, elementID: string, value: string | number) {
const element = card.querySelector(`#${elementID}`);
if (element) {
element.textContent = value.toString();
}
}
function showElement(card: GithubCard, elementID: string) {
const element: HTMLElement = card.querySelector(`#${elementID}`);
if (element) {
element.style.visibility = "initial";
}
}

View File

@@ -0,0 +1,35 @@
import colors from './colors.json';
export interface Repository {
color: string;
description: string;
language: string;
}
export const fetchGithubStaticData = async (owner: string, repo: string, token: string = ""): Promise<Repository> => {
const empty_data: Repository = {
color: "#fff",
description: "",
language: "Other",
}
try {
var headers: RequestInit
if (token != "") {
headers = {
headers: {
'Authorization': `Bearer ${token}`
}
}
}
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}`, headers);
const data: Repository = await response.json();
if (!response.ok) {
return empty_data;
}
data.color = colors[data.language].color
return data;
} catch {
return empty_data;
}
}