更新
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
addEventListener('fetch', event => {
|
||||
event.respondWith(handleRequest(event.request));
|
||||
});
|
||||
|
||||
async function handleRequest(request) {
|
||||
const response = await fetch('https://cdn.jsdelivr.net/gh/YangguangZhou/some-stars@main/data.json'); //这里的xxx修改为自己仓库的json raw文件
|
||||
const data = await response.json();
|
||||
|
||||
const html = generateHTML(data);
|
||||
|
||||
return new Response(html, {
|
||||
headers: { 'content-type': 'text/html' },
|
||||
});
|
||||
}
|
||||
|
||||
function generateHTML(data) {
|
||||
const repoCardsHtml = (repos, language) => {
|
||||
return repos.map((repo) => {
|
||||
const truncatedDescription = repo.description && repo.description.length > 200 ? repo.description.slice(0, 200) + '...' : repo.description;
|
||||
const topics = repo.topics.map(topic => topic.toLowerCase());
|
||||
if (!topics.includes(language.toLowerCase())) {
|
||||
topics.push(language.toLowerCase());
|
||||
}
|
||||
return `
|
||||
<div class="repo-card max-w-sm rounded-2xl overflow-hidden shadow-lg m-4 bg-white transition-transform transform hover:scale-105">
|
||||
<div class="h-48 overflow-hidden flex items-center justify-center mt-4 rounded-t-2xl">
|
||||
<img class="object-contain h-full w-full rounded-t-2xl" src="${repo.owner.avatar_url}">
|
||||
</div>
|
||||
<div class="px-6 py-4">
|
||||
<div class="font-bold text-xl mb-2">
|
||||
<a href="${repo.html_url}" class="text-blue-500">${repo.full_name}</a>
|
||||
</div>
|
||||
<p class="text-gray-700 text-base">${truncatedDescription}</p>
|
||||
</div>
|
||||
<div class="px-6 pt-4 pb-2">
|
||||
${topics.map(topic => `<span class="topic inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">#${topic}</span>`).join('')}
|
||||
</div>
|
||||
<div class="px-6 pt-4 pb-2">
|
||||
<span class="inline-block bg-blue-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">Stars: ${repo.stargazers_count}</span>
|
||||
<span class="inline-block bg-green-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">Watchers: ${repo.watchers_count}</span>
|
||||
</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
};
|
||||
|
||||
const categoriesHtml = Object.keys(data).map(language => `
|
||||
<div id="${language}" class="mb-8 category">
|
||||
<h2 class="text-2xl font-bold mb-4">${language} Repositories</h2>
|
||||
<div class="flex flex-wrap justify-center">
|
||||
${repoCardsHtml(data[language], language)}
|
||||
</div>
|
||||
</div>`).join('');
|
||||
|
||||
const sidebarLinks = Object.keys(data).map(language => `
|
||||
<li class="mb-2"><a href="#${language}" class="text-blue-500 hover:underline">${language}</a></li>`).join('');
|
||||
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="https://jerryz.com.cn/favicon.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Jerry Zhou GitHub Stars 导航</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2597042766299857"
|
||||
crossorigin="anonymous"></script>
|
||||
<style>
|
||||
.container {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 1800px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.repo-card {
|
||||
flex-basis: calc(25% - 1rem);
|
||||
min-width: 300px;
|
||||
max-width: 350px;
|
||||
}
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
top: 80px;
|
||||
left: 20px; /* Adjust left position as needed */
|
||||
bottom: 0;
|
||||
overflow-y: auto;
|
||||
width: 200px;
|
||||
}
|
||||
@media (max-width: 1024px) {
|
||||
.repo-card {
|
||||
flex-basis: calc(50% - 1rem);
|
||||
}
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.repo-card {
|
||||
flex-basis: calc(100% - 1rem);
|
||||
}
|
||||
|
||||
.container{
|
||||
padding: 0;
|
||||
}
|
||||
#main-content {
|
||||
margin-left: 0 !important; /* Ensure no margin for main content on mobile */
|
||||
padding-left: 8px; /* Add padding to adjust for fixed sidebar */
|
||||
}
|
||||
#categories-container{
|
||||
padding-top:76px;
|
||||
}
|
||||
.sticky-header h1 {
|
||||
display: none; /* Hide header title on mobile */
|
||||
}
|
||||
#search {
|
||||
width: 100%; /* Make search input full width on mobile */
|
||||
}
|
||||
}
|
||||
.highlight {
|
||||
background-color: yellow;
|
||||
}
|
||||
.sticky-header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
background-color: white;
|
||||
}
|
||||
#main-content {
|
||||
margin-left: 200px;
|
||||
}
|
||||
|
||||
#back-to-top {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
background-color: #1a202c;
|
||||
color: white;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0;
|
||||
border-radius: 50%;
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
#back-to-top:hover {
|
||||
background-color: #2d3748;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-100">
|
||||
<div class="sticky-header flex justify-between items-center px-4 py-2 bg-white shadow-md">
|
||||
<h1 class="text-2xl font-bold">
|
||||
<a href="https://jerryz.com.cn" class="hidden md:block">Jerry Zhou GitHub Stars 导航</a>
|
||||
</h1>
|
||||
<input id="search" type="text" placeholder="Search repositories..." class="p-2 border rounded md:w-1/3 w-full mx-auto">
|
||||
</div>
|
||||
<div class="container mx-auto p-4 py-16">
|
||||
<div class="block md:flex">
|
||||
<div id="sidebar" class="hidden md:block">
|
||||
<h2 class="text-xl font-bold mb-4">语言分类</h2>
|
||||
<ul>${sidebarLinks}</ul>
|
||||
</div>
|
||||
<div id="main-content">
|
||||
<div id="categories-container">${categoriesHtml}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button id="back-to-top">↑</button>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const searchInput = document.getElementById('search');
|
||||
const categoriesContainer = document.getElementById('categories-container');
|
||||
const backToTopButton = document.getElementById('back-to-top');
|
||||
const data = ${JSON.stringify(data)};
|
||||
|
||||
function repoCardsHtml(repos, language) {
|
||||
return repos.map(function(repo) {
|
||||
const truncatedDescription = repo.description && repo.description.length > 200 ? repo.description.slice(0, 200) + '...' : repo.description;
|
||||
const topics = repo.topics.map(topic => topic.toLowerCase());
|
||||
if (!topics.includes(language.toLowerCase())) {
|
||||
topics.push(language.toLowerCase());
|
||||
}
|
||||
|
||||
return \`
|
||||
<div class="repo-card max-w-sm rounded-2xl overflow-hidden shadow-lg m-4 bg-white transition-transform transform hover:scale-105">
|
||||
<div class="h-48 overflow-hidden flex items-center justify-center mt-4 rounded-t-2xl">
|
||||
<img class="object-contain h-full w-full rounded-t-2xl" src="\${repo.owner.avatar_url}">
|
||||
</div>
|
||||
<div class="px-6 py-4">
|
||||
<div class="font-bold text-xl mb-2">
|
||||
<a href="\${repo.html_url}" class="text-blue-500">\${repo.full_name}</a>
|
||||
</div>
|
||||
<p class="text-gray-700 text-base">\${truncatedDescription}</p>
|
||||
</div>
|
||||
<div class="px-6 pt-4 pb-2">
|
||||
\${topics.map(topic => \`<span class="topic inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">#\${topic}</span>\`).join('')}
|
||||
</div>
|
||||
<div class="px-6 pt-4 pb-2">
|
||||
<span class="inline-block bg-blue-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">Stars: \${repo.stargazers_count}</span>
|
||||
<span class="inline-block bg-green-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">Watchers: \${repo.watchers_count}</span>
|
||||
</div>
|
||||
</div>\`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', function() {
|
||||
if (window.scrollY > 200) {
|
||||
backToTopButton.style.display = 'block';
|
||||
} else {
|
||||
backToTopButton.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
backToTopButton.addEventListener('click', function() {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
});
|
||||
|
||||
function highlightText(text, query) {
|
||||
const regex = new RegExp('(' + query + ')', 'gi');
|
||||
return text.replace(regex, '<span class="highlight">$1</span>');
|
||||
}
|
||||
|
||||
function searchRepositories(query) {
|
||||
const normalizedQuery = query.toLowerCase();
|
||||
return Object.entries(data).flatMap(([language, repos]) =>
|
||||
repos.filter(repo => {
|
||||
repo.language = language;
|
||||
return repo.full_name.toLowerCase().includes(normalizedQuery) ||
|
||||
(repo.description && repo.description.toLowerCase().includes(normalizedQuery)) ||
|
||||
repo.topics.some(topic => topic.toLowerCase().includes(normalizedQuery));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
searchInput.addEventListener('input', function() {
|
||||
const query = this.value.trim();
|
||||
if (query) {
|
||||
const matchedRepos = searchRepositories(query);
|
||||
const highlightedHtml = matchedRepos.map(repo =>
|
||||
repoCardsHtml([repo], repo.language).replace(new RegExp('(?<=^|>)[^<]*?(' + escapeRegExp(query) + ')(?=<|$)', 'gi'), function(match) {
|
||||
return match.replace(new RegExp(escapeRegExp(query), 'gi'), '<span class="highlight">$&</span>');
|
||||
})
|
||||
).join('');
|
||||
|
||||
categoriesContainer.innerHTML = '<div class="mb-8"><h2 class="text-2xl font-bold mb-4">Search Results</h2><div class="flex flex-wrap justify-center">' + highlightedHtml + '</div></div>';
|
||||
} else {
|
||||
const categoriesHtml = Object.keys(data).map(function(language) {
|
||||
return '<div id="' + language + '" class="mb-8 category">' +
|
||||
'<h2 class="text-2xl font-bold mb-4">' + language + ' Repositories</h2>' +
|
||||
'<div class="flex flex-wrap justify-center">' +
|
||||
repoCardsHtml(data[language], language) +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
|
||||
categoriesContainer.innerHTML = categoriesHtml;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^$()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
}
|
||||
Reference in New Issue
Block a user