init
This commit is contained in:
95
src/GithubCard.astro
Normal file
95
src/GithubCard.astro
Normal 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>
|
@@ -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
2558
src/colors.json
Normal file
File diff suppressed because it is too large
Load Diff
94
src/github_dynamic_fetch.ts
Normal file
94
src/github_dynamic_fetch.ts
Normal 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";
|
||||
}
|
||||
}
|
35
src/github_static_fetch.ts
Normal file
35
src/github_static_fetch.ts
Normal 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;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user