Skip to content

Commit a08cc11

Browse files
author
patj
committed
Auto-highlight the download card matching the visitor's OS
- assets/js/os-detect.js: same-origin script (keeps CSP script-src 'self') detects macOS/Windows/Linux via userAgentData/platform+UA and adds .is-recommended + reveals a 'Your platform' badge on the matching card - Progressive enhancement: no JS = all three cards show equally - dl-cards gain data-os; CSS for highlight + gradient badge - build.py inlines the script into the single-file artifact bundle
1 parent c19a0a4 commit a08cc11

4 files changed

Lines changed: 60 additions & 3 deletions

File tree

‎assets/js/os-detect.js‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* Highlight the download card matching the visitor's OS.
2+
Progressive enhancement: if this doesn't run, all three cards show equally. */
3+
(function () {
4+
function detectOS() {
5+
var uaData = navigator.userAgentData;
6+
var platform = (uaData && uaData.platform) || navigator.platform || '';
7+
var ua = navigator.userAgent || '';
8+
var s = (platform + ' ' + ua).toLowerCase();
9+
10+
if (/mac|iphone|ipad|ipod|darwin/.test(s)) return 'macos';
11+
if (/win/.test(s)) return 'windows';
12+
if (/linux|x11|android|cros/.test(s)) return 'linux'; // Chromebooks + Android land on Linux/AppImage
13+
return null;
14+
}
15+
16+
function apply() {
17+
var os = detectOS();
18+
if (!os) return;
19+
var card = document.querySelector('.dl-card[data-os="' + os + '"]');
20+
if (!card) return;
21+
card.classList.add('is-recommended');
22+
var badge = card.querySelector('.dl-reco');
23+
if (badge) badge.hidden = false;
24+
}
25+
26+
if (document.readyState === 'loading') {
27+
document.addEventListener('DOMContentLoaded', apply);
28+
} else {
29+
apply();
30+
}
31+
})();

‎index.html‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,23 +291,26 @@ <h2>Native builds, released together</h2>
291291
</div>
292292

293293
<div class="dl-grid">
294-
<div class="dl-card">
294+
<div class="dl-card" data-os="linux">
295+
<span class="dl-reco" hidden>Your platform</span>
295296
<div class="os"><svg viewBox="0 0 24 24"><path d="M12 2C9.5 2 8.7 4 8.7 6.2c0 1 .2 1.6.2 2.4-.5.6-2.4 2.9-2.4 6.1 0 2 .6 3.4 1.4 4.4.4.5.2 1.3-.4 1.6-.7.4-1.2 1-1.2 1.6 0 .8.9 1.2 2.2 1.2h6.6c1.3 0 2.2-.4 2.2-1.2 0-.6-.5-1.2-1.2-1.6-.6-.3-.8-1.1-.4-1.6.8-1 1.4-2.4 1.4-4.4 0-3.2-1.9-5.5-2.4-6.1 0-.8.2-1.4.2-2.4C15.3 4 14.5 2 12 2Z"/></svg> Linux</div>
296297
<div class="variants">
297298
<a href="https://github.com/aethersdr/AetherSDR/releases/latest">AppImage <span class="arch">x86_64</span></a>
298299
<a href="https://github.com/aethersdr/AetherSDR/releases/latest">AppImage <span class="arch">aarch64 · Pi</span></a>
299300
</div>
300301
</div>
301302

302-
<div class="dl-card">
303+
<div class="dl-card" data-os="macos">
304+
<span class="dl-reco" hidden>Your platform</span>
303305
<div class="os"><svg viewBox="0 0 24 24"><path d="M16.4 2c.1 1.2-.3 2.3-1 3.2-.8.9-2 1.6-3.1 1.5-.1-1.1.4-2.3 1.1-3.1.8-.9 2-1.5 3-1.6ZM19 17.3c-.5 1.2-.8 1.8-1.5 2.8-1 1.5-2.5 3.3-4.3 3.3-1.6 0-2-.9-4.1-.9-2.1 0-2.6.9-4.1.9-1.8 0-3.2-1.7-4.2-3.1C-1 16-1.4 9.8 1.4 6.9 2.7 5.4 4.5 4.5 6.3 4.5c1.8 0 3 1 4.1 1 1 0 2.4-1 4.3-1 1.4 0 3.4.6 4.7 2.4-4.1 2.3-3.5 8.2.6 10.4Z"/></svg> macOS</div>
304306
<div class="variants">
305307
<a href="https://github.com/aethersdr/AetherSDR/releases/latest">DMG <span class="arch">Apple Silicon</span></a>
306308
<a href="https://github.com/aethersdr/AetherSDR/releases/latest">DMG <span class="arch">Intel · Rosetta</span></a>
307309
</div>
308310
</div>
309311

310-
<div class="dl-card">
312+
<div class="dl-card" data-os="windows">
313+
<span class="dl-reco" hidden>Your platform</span>
311314
<div class="os"><svg viewBox="0 0 24 24"><path d="M3 5.5 10.5 4.4v7.1H3V5.5ZM11.6 4.2 21 3v8.5h-9.4V4.2ZM3 12.5h7.5v7.1L3 18.5v-6ZM11.6 12.5H21V21l-9.4-1.3v-7.2Z"/></svg> Windows</div>
312315
<div class="variants">
313316
<a class="primary-dl" href="https://apps.microsoft.com/detail/9nc6bmwfn811" target="_blank" rel="noopener">Microsoft Store <span class="arch">recommended</span></a>
@@ -486,5 +489,6 @@ <h4>Resources</h4>
486489
</div>
487490
</footer>
488491

492+
<script src="assets/js/os-detect.js?v=1" defer></script>
489493
</body>
490494
</html>

‎scripts/build.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ def main():
3333
f"<style>\n{css}\n</style>",
3434
)
3535

36+
# Inline JS as a real <script> before the asset pass — data-URI-ing a
37+
# script src would break execution in the single-file bundle.
38+
with open(os.path.join(ROOT, "assets/js/os-detect.js"), encoding="utf-8") as f:
39+
js = f.read()
40+
html = re.sub(
41+
r'<script src="assets/js/os-detect\.js[^"]*"[^>]*></script>',
42+
f"<script>\n{js}\n</script>",
43+
html,
44+
)
45+
3646
# Embed every referenced asset (src="assets/..." and content="assets/...").
3747
def repl(match):
3848
attr, path = match.group(1), match.group(2)

‎styles.css‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,18 @@ section.block { padding: 84px 0; }
345345
transition: border-color .2s ease, transform .2s ease;
346346
}
347347
.dl-card:hover { border-color: var(--line-hi); transform: translateY(-3px); }
348+
.dl-card.is-recommended {
349+
border-color: var(--cyan);
350+
box-shadow: 0 0 0 1px var(--cyan), 0 26px 56px -26px rgba(50, 160, 220, 0.6);
351+
background: linear-gradient(180deg, rgba(93,227,255,0.06), rgba(93,227,255,0.01)), var(--bg-1);
352+
}
353+
.dl-reco {
354+
align-self: flex-start;
355+
font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
356+
color: #041019;
357+
background: var(--grad);
358+
border-radius: 100px; padding: 4px 11px;
359+
}
348360
.dl-card .os { display: flex; align-items: center; gap: 11px; font-weight: 680; font-size: 18px; }
349361
.dl-card .os svg { width: 24px; height: 24px; fill: var(--cyan); }
350362
.dl-card .variants { display: grid; gap: 8px; margin-top: 2px; }

0 commit comments

Comments
 (0)