2 Star 0 Fork 2

think3r/myOpenSourceCollection

Create your Gitee Account
Explore and code with more than 14 million developers,Free private repositories !:)
Sign up
文件
This repository doesn't specify license. Please pay attention to the specific project description and its upstream code dependency when using it.
Clone or Download
githubStars.html 22.50 KB
Copy Edit Raw Blame History
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GitHub Stars - myOpenSourceCollection</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #151515;
color: #eaeaea;
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
font-size: 14px;
line-height: 1.5;
min-height: 100vh;
-webkit-font-smoothing: antialiased;
}
.container { width: 90%; max-width: 1400px; margin: 0 auto; padding: 20px 40px; }
header {
border-bottom: 1px dashed #b5e853;
padding-bottom: 20px;
margin-bottom: 40px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 10px;
}
h1 {
font-size: 28px;
color: #b5e853;
font-weight: bold;
letter-spacing: -1px;
text-shadow: 0 1px 1px rgba(0,0,0,0.1), 0 0 5px rgba(181,232,83,0.1), 0 0 10px rgba(181,232,83,0.1);
}
h1::before { content: "./ "; font-size: 22px; }
.back-link {
display: inline-block;
color: rgba(255,255,255,0.8);
text-decoration: none;
padding: 8px 18px;
border-radius: 50px;
border: 2px solid rgba(0,0,0,0.7);
border-top: 2px solid #000;
font-family: Helvetica, Arial, sans-serif;
font-weight: bold;
font-size: 11px;
text-shadow: 0 -1px 0 rgba(0,0,0,0.75);
background: -webkit-linear-gradient(top, rgba(40,40,40,0.3), rgba(35,35,35,0.3) 50%, rgba(10,10,10,0.3) 50%, rgba(0,0,0,0.3));
transition: all 0.3s;
}
.back-link:hover {
background: -webkit-linear-gradient(top, rgba(40,40,40,0.6), rgba(35,35,35,0.6) 50%, rgba(10,10,10,0.8) 50%, rgba(0,0,0,0.8));
}
.subtitle { color: #aaa; font-size: 16px; font-weight: 300; }
.controls { margin-bottom: 30px; }
.search-box {
width: 100%;
padding: 15px;
background: rgba(0,0,0,0.9);
border: 1px solid rgba(255,255,255,0.15);
color: #b5e853;
font-family: inherit;
font-size: 14px;
margin-bottom: 20px;
border-radius: 2px;
}
.search-box:focus { outline: none; box-shadow: 0 0 10px rgba(181,232,83,0.3); border-color: #b5e853; }
.search-box::placeholder { color: #888; }
.filter-bar { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 15px; }
.filter-btn {
background: transparent;
border: 1px dashed #b5e853;
color: #aaa;
padding: 8px 16px;
cursor: pointer;
font-family: inherit;
font-size: 0.9em;
transition: all 0.3s;
}
.filter-btn:hover { color: #b5e853; }
.filter-btn.active { background: #b5e853; color: #151515; border-color: #b5e853; border-style: solid; }
.sort-bar { display: flex; align-items: center; gap: 10px; color: #aaa; font-size: 0.9em; }
.sort-btn {
background: transparent;
border: none;
color: #aaa;
cursor: pointer;
font-family: inherit;
font-size: 1em;
padding: 5px 10px;
transition: color 0.3s;
}
.sort-btn:hover, .sort-btn.active { color: #b5e853; }
.stats { color: #aaa; margin-bottom: 20px; font-size: 0.9em; }
.repo-list { display: grid; gap: 15px; }
.repo-card {
background: rgba(0,0,0,0.9);
border: 1px solid rgba(255,255,255,0.15);
padding: 20px;
transition: all 0.3s;
text-decoration: none;
display: block;
border-radius: 2px;
}
.repo-card:hover {
border-color: #b5e853;
box-shadow: 0 0 15px rgba(181,232,83,0.2);
transform: translateY(-2px);
}
.repo-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 10px;
gap: 10px;
}
.repo-name {
color: #b5e853;
font-size: 1.1em;
font-weight: bold;
word-break: break-word;
text-shadow: 0 1px 1px rgba(0,0,0,0.1), 0 0 5px rgba(181,232,83,0.1), 0 0 10px rgba(181,232,83,0.1);
}
.repo-row { display: flex; align-items: center; gap: 15px; }
.repo-idx { color: #b5e853; font-size: 0.9em; min-width: 2em; }
.repo-stars { color: #f4bf75; white-space: nowrap; font-size: 0.9em; }
.repo-desc { color: #eaeaea; margin-bottom: 10px; font-size: 0.9em; }
.repo-meta { display: flex; flex-wrap: wrap; gap: 15px; font-size: 0.8em; color: #bbb; }
.lang-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 5px; vertical-align: middle; }
.repo-lang { color: #63c0f5; text-shadow: 0 0 5px rgba(104,182,255,0.5); }
.repo-topics { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 10px; }
.topic-tag { background: #2a2a2a; color: #bbb; padding: 2px 8px; font-size: 0.75em; border-radius: 2px; }
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
margin-top: 30px;
flex-wrap: wrap;
}
.page-btn {
background: transparent;
border: 1px solid rgba(255,255,255,0.15);
color: #aaa;
padding: 8px 14px;
cursor: pointer;
font-family: inherit;
font-size: 0.9em;
transition: all 0.3s;
border-radius: 2px;
}
.page-btn:hover { border-color: #b5e853; color: #b5e853; }
.page-btn.active { background: #b5e853; color: #151515; border-color: #b5e853; }
.page-btn.disabled { opacity: 0.3; cursor: default; pointer-events: none; }
.page-info { color: #aaa; font-size: 0.85em; }
footer {
margin-top: 40px;
padding-top: 20px;
border-top: 1px dashed #b5e853;
color: #aaa;
font-size: 0.85em;
text-align: center;
}
.loading { text-align: center; padding: 50px; color: #aaa; }
.loading::after { content: '...'; animation: dots 1.5s infinite; }
@keyframes dots {
0%, 20% { content: '.'; }
40% { content: '..'; }
60%, 100% { content: '...'; }
}
.error { text-align: center; padding: 50px; color: #ac4142; }
.no-results { text-align: center; padding: 50px; color: #aaa; }
@media (max-width: 600px) {
.container { padding: 15px; }
h1 { font-size: 1.4em; }
.repo-card { padding: 15px; }
.page-btn { padding: 6px 10px; font-size: 0.85em; }
}
</style>
</head>
<body>
<div class="container">
<header>
<div>
<h1>GitHub Stars</h1>
<div class="subtitle">@think3r's starred repositories</div>
</div>
<a href="/" class="back-link">← Back to Home</a>
</header>
<div class="controls">
<input type="text" class="search-box" id="searchInput" placeholder="Search repositories by name, description, or topics...">
<div class="filter-bar" id="filterBar">
<button class="filter-btn active" data-lang="all">All</button>
</div>
<div class="sort-bar">
<span>Sort by:</span>
<button class="sort-btn active" data-sort="stars">⭐ Stars</button>
<button class="sort-btn" data-sort="name">Name</button>
<button class="sort-btn" data-sort="pushed">Pushed</button>
<button class="sort-btn" data-sort="updated">Updated</button>
</div>
</div>
<div class="stats" id="stats"></div>
<div class="repo-list" id="repoList">
<div class="loading">Loading repositories</div>
</div>
<div class="pagination" id="pagination"></div>
<footer>
<p>Data auto-generated from GitHub API · Last updated: <span id="updateTime">-</span></p>
</footer>
</div>
<script>
const PAGE_SIZE = 50;
let allRepos = [];
let currentFilter = 'all';
let currentSort = 'stars';
let currentSearch = '';
let currentPage = 1;
let dataTimestamp = '';
const LANG_COLORS = {
'C': '#555555', 'C++': '#f34b7d', 'C#': '#178600', 'Go': '#00ADD8',
'Java': '#b07219', 'JavaScript': '#f1e05a', 'Kotlin': '#A97BFF',
'Lua': '#000080', 'Objective-C': '#438eff', 'PHP': '#4F5D95',
'Python': '#3572A5', 'R': '#198CE7', 'Ruby': '#701516',
'Rust': '#dea584', 'Scala': '#c22d40', 'Shell': '#89e051',
'Swift': '#F05138', 'TypeScript': '#2b7489', 'Vim script': '#199f4d',
'Vue': '#41b883', 'Zig': '#ec915c', 'Dart': '#00B4AB',
'Elixir': '#6e4a7e', 'Erlang': '#B83998', 'Haskell': '#29b544',
'Perl': '#0298c3', 'PowerShell': '#012456', 'SQL': '#e38c00',
'Assembly': '#6E4C13', 'Clojure': '#db5855', 'CoffeeScript': '#244776',
'F#': '#b845fc', 'Groovy': '#e69f56', 'Julia': '#a270ba',
'Matlab': '#e16737', 'OCaml': '#3be133', 'Racket': '#ae17ff',
'Sass': '#a53b70', 'Solidity': '#AA6746', 'Tcl': '#e4cc98',
'Wasm': '#654ff0', 'CSS': '#563d7c', 'HTML': '#e34c26',
'Markdown': '#083fa1', 'YAML': '#cb171e', 'JSON': '#292929',
'Makefile': '#427819', 'Nix': '#7e7eff', 'D': '#ba595e',
'Vala': '#fbe5cd', 'Apex': '#1798c1', 'WebAssembly': '#654ff0',
};
function escapeHtml(str) {
if (!str) return '';
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
}
function safeUrl(url) {
if (!url) return '';
try {
const parsed = new URL(url);
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') return '';
return url;
} catch { return ''; }
}
function formatStars(num) {
if (num >= 1000) return (num / 1000).toFixed(1) + 'k';
return num.toString();
}
function formatDate(dateStr) {
return new Date(dateStr).toISOString().split('T')[0];
}
function getLangColor(lang) {
return LANG_COLORS[lang] || '#8b8b8b';
}
function getFilteredRepos() {
let filtered = allRepos.filter(repo => {
if (currentFilter !== 'all' && (repo.language || 'Other') !== currentFilter) return false;
if (currentSearch) {
const s = currentSearch.toLowerCase();
return repo.full_name.toLowerCase().includes(s)
|| (repo.description || '').toLowerCase().includes(s)
|| (repo.topics || []).some(t => t.toLowerCase().includes(s));
}
return true;
});
filtered.sort((a, b) => {
if (currentSearch) {
const s = currentSearch.toLowerCase();
const maxStars = Math.max(...filtered.map(r => r.stargazers_count), 1);
const logMax = Math.log(maxStars + 1);
const relA = a.full_name.toLowerCase().includes(s) ? 2
: (a.description || '').toLowerCase().includes(s) ? 1 : 0;
const relB = b.full_name.toLowerCase().includes(s) ? 2
: (b.description || '').toLowerCase().includes(s) ? 1 : 0;
const starsScoreA = Math.log(a.stargazers_count + 1) / logMax;
const starsScoreB = Math.log(b.stargazers_count + 1) / logMax;
let wRel, wStars;
switch (currentSort) {
case 'stars': wRel = 3; wStars = 5; break;
case 'name': wRel = 5; wStars = 2; break;
case 'pushed': wRel = 3; wStars = 4; break;
case 'updated': wRel = 3; wStars = 4; break;
default: wRel = 3; wStars = 5; break;
}
const scoreA = relA * wRel + starsScoreA * wStars;
const scoreB = relB * wRel + starsScoreB * wStars;
if (scoreA !== scoreB) return scoreB - scoreA;
switch (currentSort) {
case 'stars': return b.stargazers_count - a.stargazers_count;
case 'name': return a.full_name.localeCompare(b.full_name);
case 'pushed': return new Date(b.pushed_at) - new Date(a.pushed_at);
case 'updated': return new Date(b.updated_at) - new Date(a.updated_at);
default: return 0;
}
}
switch (currentSort) {
case 'stars': return b.stargazers_count - a.stargazers_count;
case 'name': return a.full_name.localeCompare(b.full_name);
case 'pushed': return new Date(b.pushed_at) - new Date(a.pushed_at);
case 'updated': return new Date(b.updated_at) - new Date(a.updated_at);
default: return 0;
}
});
return filtered;
}
function saveState() {
const params = new URLSearchParams();
if (currentSearch) params.set('search', currentSearch);
if (currentFilter !== 'all') params.set('lang', currentFilter);
if (currentSort !== 'stars') params.set('sort', currentSort);
if (currentPage !== 1) params.set('page', currentPage);
const hash = params.toString();
history.replaceState(null, '', hash ? '#' + hash : location.pathname);
}
function loadState() {
const hash = location.hash.slice(1);
if (!hash) return;
const params = new URLSearchParams(hash);
if (params.has('search')) {
currentSearch = params.get('search');
document.getElementById('searchInput').value = currentSearch;
}
if (params.has('lang')) currentFilter = params.get('lang');
if (params.has('sort')) currentSort = params.get('sort');
if (params.has('page')) currentPage = parseInt(params.get('page')) || 1;
}
function applyStateToUI() {
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.lang === currentFilter);
});
document.querySelectorAll('.sort-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.sort === currentSort);
});
}
function renderFilters() {
const langs = {};
allRepos.forEach(repo => {
const lang = repo.language || 'Other';
langs[lang] = (langs[lang] || 0) + 1;
});
const sortedLangs = Object.entries(langs).sort((a, b) => b[1] - a[1]).slice(0, 8);
const filterBar = document.getElementById('filterBar');
filterBar.innerHTML = '<button class="filter-btn' + (currentFilter === 'all' ? ' active' : '') + '" data-lang="all">All (' + allRepos.length + ')</button>';
sortedLangs.forEach(([lang, count]) => {
const btn = document.createElement('button');
btn.className = 'filter-btn' + (currentFilter === lang ? ' active' : '');
btn.dataset.lang = lang;
const dot = '<span class="lang-dot" style="background:' + getLangColor(lang) + '"></span>';
btn.innerHTML = dot + escapeHtml(lang) + ' (' + count + ')';
filterBar.appendChild(btn);
});
filterBar.querySelectorAll('.filter-btn').forEach(btn => {
btn.addEventListener('click', () => {
currentFilter = btn.dataset.lang;
currentPage = 1;
saveState();
renderFilters();
renderRepos();
});
});
}
function renderPagination(filtered) {
const totalPages = Math.ceil(filtered.length / PAGE_SIZE);
const pagEl = document.getElementById('pagination');
if (totalPages <= 1) { pagEl.innerHTML = ''; return; }
let html = '';
html += '<button class="page-btn' + (currentPage === 1 ? ' disabled' : '') + '" data-page="prev">← Prev</button>';
const maxVisible = 7;
let start = Math.max(1, currentPage - Math.floor(maxVisible / 2));
let end = Math.min(totalPages, start + maxVisible - 1);
if (end - start < maxVisible - 1) start = Math.max(1, end - maxVisible + 1);
if (start > 1) {
html += '<button class="page-btn" data-page="1">1</button>';
if (start > 2) html += '<span class="page-info">...</span>';
}
for (let i = start; i <= end; i++) {
html += '<button class="page-btn' + (i === currentPage ? ' active' : '') + '" data-page="' + i + '">' + i + '</button>';
}
if (end < totalPages) {
if (end < totalPages - 1) html += '<span class="page-info">...</span>';
html += '<button class="page-btn" data-page="' + totalPages + '">' + totalPages + '</button>';
}
html += '<button class="page-btn' + (currentPage === totalPages ? ' disabled' : '') + '" data-page="next">Next →</button>';
html += '<span class="page-info">Page ' + currentPage + ' / ' + totalPages + '</span>';
pagEl.innerHTML = html;
pagEl.querySelectorAll('.page-btn:not(.disabled)').forEach(btn => {
btn.addEventListener('click', () => {
const val = btn.dataset.page;
if (val === 'prev') currentPage = Math.max(1, currentPage - 1);
else if (val === 'next') currentPage = Math.min(totalPages, currentPage + 1);
else currentPage = parseInt(val);
saveState();
renderRepos();
window.scrollTo({ top: 0, behavior: 'smooth' });
});
});
}
function renderRepos() {
const filtered = getFilteredRepos();
const totalPages = Math.ceil(filtered.length / PAGE_SIZE);
if (currentPage > totalPages && totalPages > 0) currentPage = totalPages;
const startIdx = (currentPage - 1) * PAGE_SIZE;
const pageItems = filtered.slice(startIdx, startIdx + PAGE_SIZE);
document.getElementById('stats').textContent = 'Showing ' + (filtered.length === 0 ? 0 : startIdx + 1) + '-' + Math.min(startIdx + PAGE_SIZE, filtered.length) + ' of ' + filtered.length + ' repositories (total: ' + allRepos.length + ')';
const repoList = document.getElementById('repoList');
if (filtered.length === 0) {
repoList.innerHTML = '<div class="no-results">No repositories found</div>';
renderPagination(filtered);
return;
}
repoList.innerHTML = pageItems.map((repo, i) => {
const topics = (repo.topics || []).slice(0, 5)
.map(t => '<span class="topic-tag">' + escapeHtml(t) + '</span>').join('');
const lang = repo.language || 'Other';
const langColor = getLangColor(lang);
return '<div class="repo-row">'
+ '<span class="repo-idx">' + (i + 1) + '.</span>'
+ '<a href="' + escapeHtml(safeUrl(repo.html_url)) + '" target="_blank" class="repo-card">'
+ '<div class="repo-header">'
+ '<span class="repo-name">' + escapeHtml(repo.full_name) + '</span>'
+ '<span class="repo-stars">⭐ ' + formatStars(repo.stargazers_count) + '</span>'
+ '</div>'
+ '<div class="repo-desc">' + escapeHtml(repo.description || 'No description') + '</div>'
+ '<div class="repo-meta">'
+ '<span class="repo-lang"><span class="lang-dot" style="background:' + langColor + '"></span>' + escapeHtml(lang) + '</span>'
+ '<span>Pushed: ' + formatDate(repo.pushed_at) + '</span>'
+ '<span>Updated: ' + formatDate(repo.updated_at) + '</span>'
+ '</div>'
+ (topics ? '<div class="repo-topics">' + topics + '</div>' : '')
+ '</a>'
+ '</div>';
}).join('');
renderPagination(filtered);
saveState();
}
document.getElementById('searchInput').addEventListener('input', e => {
currentSearch = e.target.value;
currentPage = 1;
saveState();
renderRepos();
});
document.querySelectorAll('.sort-btn').forEach(btn => {
btn.addEventListener('click', () => {
currentSort = btn.dataset.sort;
currentPage = 1;
saveState();
applyStateToUI();
renderRepos();
});
});
fetch('./stars-data.json')
.then(res => {
if (!res.ok) throw new Error('Failed to load data');
return res.json();
})
.then(data => {
allRepos = data.repos;
dataTimestamp = data.timestamp;
document.getElementById('updateTime').textContent = new Date(dataTimestamp).toISOString().slice(0, 16).replace("T", " ");
loadState();
applyStateToUI();
renderFilters();
renderRepos();
})
.catch(err => {
document.getElementById('repoList').innerHTML =
'<div class="error">Failed to load repositories: ' + err.message + '</div>';
});
</script>
</body>
</html>
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
other
1
https://gitee.com/think3r/myOpenSourceCollection.git
git@gitee.com:think3r/myOpenSourceCollection.git
think3r
myOpenSourceCollection
myOpenSourceCollection
master

Search