test version fetcher
All checks were successful
Deploy to Production / deploy (push) Successful in 6s
All checks were successful
Deploy to Production / deploy (push) Successful in 6s
This commit is contained in:
parent
aeccf99ad3
commit
0dca4e8ddc
43
index.html
43
index.html
@ -5,6 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>pyserve - Documentation</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="scripts/version-fetcher.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
@ -13,7 +14,8 @@
|
||||
<div class="tagline">python application orchestrator</div>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<div id="main-wrapper">
|
||||
<div id="content">
|
||||
<h2>About</h2>
|
||||
<p>
|
||||
pyserve is a Python application orchestrator and HTTP server.
|
||||
@ -102,7 +104,7 @@
|
||||
</ul>
|
||||
|
||||
<h2>Version</h2>
|
||||
<p>Current version: <strong>0.9.10</strong></p>
|
||||
<p>Current version: <strong id="current-version">0.9.10</strong></p>
|
||||
|
||||
<h2>Requirements</h2>
|
||||
<ul class="indent">
|
||||
@ -110,6 +112,43 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- <aside id="sidebar">
|
||||
<div class="partner-block">
|
||||
<h3>Sponsors & Partners</h3>
|
||||
|
||||
<div class="partner-card">
|
||||
<div class="partner-icon">🚀</div>
|
||||
<h4>Cloud Hosting</h4>
|
||||
<p>Deploy your pyserve applications with enterprise-grade reliability.</p>
|
||||
<a href="#" class="partner-link">Learn More →</a>
|
||||
</div>
|
||||
|
||||
<div class="partner-card">
|
||||
<div class="partner-icon">📊</div>
|
||||
<h4>Monitoring</h4>
|
||||
<p>Real-time monitoring and analytics for your production apps.</p>
|
||||
<a href="#" class="partner-link">Get Started →</a>
|
||||
</div>
|
||||
|
||||
<div class="partner-card">
|
||||
<div class="partner-icon">🔐</div>
|
||||
<h4>Security</h4>
|
||||
<p>Advanced security scanning and vulnerability detection.</p>
|
||||
<a href="#" class="partner-link">Secure Now →</a>
|
||||
</div>
|
||||
|
||||
<div class="community-block">
|
||||
<h4>Community</h4>
|
||||
<ul class="community-links">
|
||||
<li><a href="https://git.pyserve.org">Git Repository</a></li>
|
||||
<li><a href="#">Discord Server</a></li>
|
||||
<li><a href="#">Stack Overflow</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside> -->
|
||||
</div>
|
||||
|
||||
<div id="footer">
|
||||
<p>pyserve © 2024-2025 | MIT License</p>
|
||||
</div>
|
||||
|
||||
149
scripts/version-fetcher.js
Normal file
149
scripts/version-fetcher.js
Normal file
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Version Fetcher - Automatically fetches and displays latest pyserveX version
|
||||
* from Gitea releases page
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
const RELEASES_URL = 'https://git.pyserve.org/Shifty/pyserveX/releases/latest';
|
||||
const VERSION_ELEMENT_ID = 'current-version';
|
||||
const CACHE_KEY = 'pyserve_version_cache';
|
||||
const CACHE_DURATION = 3600000; // 1 hour
|
||||
const FALLBACK_VERSION = 'offline';
|
||||
|
||||
async function fetchLatestVersion() {
|
||||
try {
|
||||
const response = await fetch(RELEASES_URL, {
|
||||
method: 'GET',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Accept': 'text/html'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
console.warn(`Failed to fetch: ${response.status}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const html = await response.text();
|
||||
|
||||
const patterns = [
|
||||
/<title>PyServeX\s+v([\d.]+)/i,
|
||||
/releases\/tag\/v([\d.]+)/,
|
||||
/aria-label="PyServeX\s+v([\d.]+)/i,
|
||||
/<h4[^>]*>.*?v([\d.]+).*?<\/h4>/i
|
||||
];
|
||||
|
||||
for (const pattern of patterns) {
|
||||
const match = html.match(pattern);
|
||||
if (match && match[1]) {
|
||||
console.log(`✓ Version found: ${match[1]}`);
|
||||
return match[1];
|
||||
}
|
||||
}
|
||||
|
||||
console.warn('Version not found in HTML');
|
||||
return null;
|
||||
|
||||
} catch (error) {
|
||||
console.warn('Fetch error:', error.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getCachedVersion() {
|
||||
try {
|
||||
const cached = localStorage.getItem(CACHE_KEY);
|
||||
if (!cached) return null;
|
||||
|
||||
const data = JSON.parse(cached);
|
||||
const now = Date.now();
|
||||
|
||||
if (now - data.timestamp < CACHE_DURATION) {
|
||||
return data.version;
|
||||
}
|
||||
|
||||
localStorage.removeItem(CACHE_KEY);
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('Cache read error:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function cacheVersion(version) {
|
||||
try {
|
||||
const data = {
|
||||
version: version,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
localStorage.setItem(CACHE_KEY, JSON.stringify(data));
|
||||
} catch (error) {
|
||||
console.error('Cache write error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function updateVersionDisplay(version) {
|
||||
const element = document.getElementById(VERSION_ELEMENT_ID);
|
||||
if (!element) {
|
||||
console.warn('Version element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const versionLink = document.createElement('a');
|
||||
versionLink.href = 'https://git.pyserve.org/Shifty/pyserveX/releases/tag/v' + version;
|
||||
versionLink.textContent = version;
|
||||
versionLink.target = '_blank';
|
||||
versionLink.rel = 'noopener noreferrer';
|
||||
versionLink.className = 'version-link';
|
||||
|
||||
element.innerHTML = '';
|
||||
element.appendChild(versionLink);
|
||||
|
||||
const badge = document.createElement('span');
|
||||
badge.textContent = 'latest';
|
||||
badge.className = 'version-badge';
|
||||
badge.title = 'Fetched from Git repository';
|
||||
element.appendChild(document.createTextNode(' '));
|
||||
element.appendChild(badge);
|
||||
|
||||
element.style.opacity = '1';
|
||||
}
|
||||
function showLoadingState() {
|
||||
const element = document.getElementById(VERSION_ELEMENT_ID);
|
||||
if (element) {
|
||||
element.style.opacity = '0.6';
|
||||
}
|
||||
}
|
||||
|
||||
async function init() {
|
||||
showLoadingState();
|
||||
|
||||
const cachedVersion = getCachedVersion();
|
||||
if (cachedVersion) {
|
||||
updateVersionDisplay(cachedVersion);
|
||||
}
|
||||
|
||||
const latestVersion = await fetchLatestVersion();
|
||||
if (latestVersion) {
|
||||
cacheVersion(latestVersion);
|
||||
updateVersionDisplay(latestVersion);
|
||||
} else if (!cachedVersion) {
|
||||
const element = document.getElementById(VERSION_ELEMENT_ID);
|
||||
if (element) {
|
||||
element.textContent = FALLBACK_VERSION;
|
||||
element.style.opacity = '1';
|
||||
element.style.color = '#c9c9c9';
|
||||
element.title = 'Version fetch failed (CORS or network issue)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
|
||||
})();
|
||||
209
style.css
209
style.css
@ -13,7 +13,7 @@ body {
|
||||
}
|
||||
|
||||
#container {
|
||||
max-width: 800px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
@ -38,7 +38,7 @@ body {
|
||||
}
|
||||
|
||||
#content {
|
||||
margin-bottom: 30px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@ -235,3 +235,208 @@ dd {
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Main wrapper for two-column layout */
|
||||
#main-wrapper {
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
#content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
#sidebar {
|
||||
width: 300px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.partner-block {
|
||||
position: sticky;
|
||||
top: 20px;
|
||||
background: #0d0d0d;
|
||||
border: 1px solid #333;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.partner-block h3 {
|
||||
color: #3cb371;
|
||||
font-size: 16px;
|
||||
margin: 0 0 15px 0;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 2px solid #2e8b57;
|
||||
}
|
||||
|
||||
.partner-card {
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #2a2a2a;
|
||||
border-radius: 6px;
|
||||
padding: 15px;
|
||||
margin-bottom: 15px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.partner-card:hover {
|
||||
border-color: #3cb371;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(60, 179, 113, 0.1);
|
||||
}
|
||||
|
||||
.partner-icon {
|
||||
font-size: 32px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.partner-card h4 {
|
||||
color: #e0e0e0;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.partner-card p {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.partner-link {
|
||||
display: inline-block;
|
||||
color: #5fba7d;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.partner-link:hover {
|
||||
color: #7ccd9a;
|
||||
}
|
||||
|
||||
.community-block {
|
||||
background: #1a2a1a;
|
||||
border: 1px solid #2e4a2e;
|
||||
border-radius: 6px;
|
||||
padding: 15px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.community-block h4 {
|
||||
color: #3cb371;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.community-links {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.community-links li {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.community-links li:before {
|
||||
content: "► ";
|
||||
color: #2e8b57;
|
||||
font-size: 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.community-links a {
|
||||
color: #5fba7d;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.community-links a:hover {
|
||||
color: #7ccd9a;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Responsive design */
|
||||
@media (max-width: 1024px) {
|
||||
#container {
|
||||
max-width: 900px;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
width: 250px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
#main-wrapper {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
width: 100%;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.partner-block {
|
||||
position: static;
|
||||
}
|
||||
|
||||
/* On mobile, show partner cards in a more compact grid */
|
||||
.partner-card {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
#container {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.partner-block {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.partner-card {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.partner-icon {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
#current-version {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.version-link {
|
||||
color: #5fba7d;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.version-link:hover {
|
||||
color: #7ccd9a;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.version-badge {
|
||||
display: inline-block;
|
||||
background: linear-gradient(135deg, #2e8b57 0%, #3cb371 100%);
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
letter-spacing: 0.5px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user