Skip to content

Commit b6c4152

Browse files
authored
adding backup fonts for docs (#90)
Signed-off-by: Daniel Guns <danbguns@gmail.com>
1 parent 39a3f05 commit b6c4152

10 files changed

Lines changed: 216 additions & 25 deletions

File tree

docs/assets/scss/_styles_project.scss

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,3 +791,71 @@ code:not(pre code) {
791791
* {
792792
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
793793
}
794+
795+
// Font Awesome fallbacks - ensure icons degrade gracefully when fonts are blocked
796+
// Add fallback font stack to prevent invisible icons
797+
.fab, .fas, .far {
798+
// Ensure icons have minimum width to prevent layout shift
799+
min-width: 1em;
800+
display: inline-block;
801+
text-align: center;
802+
position: relative;
803+
}
804+
805+
// Text fallbacks for icons - shown when fonts fail to load (via JavaScript detection)
806+
.icon-fallback-text {
807+
display: none;
808+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
809+
font-size: 0.9em;
810+
margin-left: 0.25em;
811+
812+
// Show fallback text when fonts fail
813+
.fonts-failed & {
814+
display: inline;
815+
}
816+
817+
// Hide icon when showing fallback text
818+
.fonts-failed + & {
819+
display: inline;
820+
}
821+
}
822+
823+
// When fonts fail, hide icon and show text
824+
.fonts-failed {
825+
.fab, .fas, .far {
826+
// Make icon invisible but keep space
827+
visibility: hidden;
828+
width: 0;
829+
min-width: 0;
830+
margin: 0;
831+
}
832+
833+
.icon-fallback-text {
834+
display: inline;
835+
}
836+
}
837+
838+
// Specific icon text fallbacks
839+
.fa-github + .icon-fallback-text::before {
840+
content: '[GitHub]';
841+
}
842+
843+
.fa-arrow-alt-circle-right + .icon-fallback-text::before {
844+
content: '';
845+
}
846+
847+
.fa-box + .icon-fallback-text::before {
848+
content: '[Box]';
849+
}
850+
851+
.fa-beer + .icon-fallback-text::before {
852+
content: '[Beer]';
853+
}
854+
855+
.fa-moon + .icon-fallback-text::before {
856+
content: '🌙';
857+
}
858+
859+
.fa-sun + .icon-fallback-text::before {
860+
content: '☀️';
861+
}

docs/assets/scss/_variables_project.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,7 @@ $link-hover-color: $purple-600;
4141
$border-radius: 0.5rem;
4242
$border-radius-sm: 0.25rem;
4343
$border-radius-lg: 0.75rem;
44+
45+
// Font Awesome font path - ensure it points to the correct location
46+
// This should match where Hugo mounts the webfonts (static/webfonts)
47+
$fa-font-path: "../webfonts" !default;

docs/content/_index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ notoc: true
2525
<!-- Action Buttons -->
2626
<div class="d-flex flex-wrap justify-content-center gap-3 mb-5">
2727
<a class="btn btn-lg btn-primary" href="{{< relref \"getting-started/\" >}}">
28-
Get Started <i class="fas fa-arrow-alt-circle-right ms-2"></i>
28+
Get Started <i class="fas fa-arrow-alt-circle-right ms-2" aria-label="Arrow"></i><span class="icon-fallback-text">→</span>
2929
</a>
3030
<a class="btn btn-lg btn-outline-primary" href="https://github.com/dgunzy/flux9s">
31-
<i class="fab fa-github me-2"></i>View on GitHub
31+
<i class="fab fa-github me-2" aria-label="GitHub"></i><span class="icon-fallback-text">[GitHub]</span><span>View on GitHub</span>
3232
</a>
3333
</div>
3434

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{{ if .Site.Params.links.user }}
2+
{{ partial "footer/links.html" .Site.Params.links.user }}
3+
{{ end }}
4+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<ul class="td-footer__links-list">
2+
{{ range . }}
3+
<li class="td-footer__links-item" data-bs-toggle="tooltip" title="{{ .name }}" aria-label="{{ .name }}">
4+
<a target="_blank" rel="noopener" href="{{ .url }}" aria-label="{{ .name }}">
5+
<i class="{{ .icon }}"></i>
6+
{{/* Add fallback text for icons */}}
7+
{{ if eq .icon "fab fa-github" }}
8+
<span class="icon-fallback-text">[GitHub]</span>
9+
{{ else if eq .icon "fas fa-box" }}
10+
<span class="icon-fallback-text">[Box]</span>
11+
{{ else if eq .icon "fas fa-beer" }}
12+
<span class="icon-fallback-text">[Beer]</span>
13+
{{ end }}
14+
</a>
15+
</li>
16+
{{ end }}
17+
</ul>
18+
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
11
{{- /* Custom head includes for flux9s docs */ -}}
2-
<script src="{{ "js/metadata.js" | relURL }}"></script>
3-
<script src="{{ "js/dark-mode.js" | relURL }}"></script>

docs/layouts/partials/navbar.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
<div class="d-flex align-items-center ms-3">
2626
{{/* Dark mode toggle */}}
2727
<button class="theme-toggle btn btn-link text-decoration-none" id="theme-toggle" aria-label="Toggle dark mode" title="Toggle dark mode">
28-
<i class="fas fa-moon" id="theme-icon"></i>
28+
<i class="fas fa-moon" id="theme-icon" aria-hidden="true"></i>
29+
<span class="sr-only">Toggle dark mode</span>
2930
</button>
3031
</div>
3132
</div>

docs/layouts/partials/scripts.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{{/* Custom scripts for flux9s docs - loaded at end of body */}}
2+
<script src="{{ "js/font-fallback.js" | relURL }}"></script>
23
<script src="{{ "js/metadata.js" | relURL }}"></script>
34
<script src="{{ "js/dark-mode.js" | relURL }}"></script>

docs/static/js/font-fallback.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Font loading detection and fallback handling
2+
// Detects if Font Awesome fonts loaded successfully, shows text fallbacks if not
3+
4+
(function() {
5+
'use strict';
6+
7+
// Check if Font Awesome fonts are available
8+
function checkFontLoaded(fontFamily) {
9+
if (!document.fonts || !document.fonts.check) {
10+
// Fallback for browsers without Font Loading API
11+
return false;
12+
}
13+
14+
// Check if the font is loaded
15+
// Font Awesome 6 Free (solid) uses weight 900
16+
// Font Awesome 6 Brands uses weight 400
17+
if (fontFamily.includes('Free')) {
18+
return document.fonts.check('900 1em "' + fontFamily + '"');
19+
} else if (fontFamily.includes('Brands')) {
20+
return document.fonts.check('400 1em "' + fontFamily + '"');
21+
}
22+
return false;
23+
}
24+
25+
// Wait for fonts to load, then check
26+
function detectFontLoading() {
27+
if (!document.fonts) {
28+
// No Font Loading API - assume fonts might not load, show fallbacks
29+
setTimeout(function() {
30+
document.documentElement.classList.add('fonts-failed');
31+
}, 2000);
32+
return;
33+
}
34+
35+
// Wait for fonts to be ready
36+
document.fonts.ready.then(function() {
37+
// Check both Font Awesome font families
38+
const freeLoaded = checkFontLoaded('Font Awesome 6 Free');
39+
const brandsLoaded = checkFontLoaded('Font Awesome 6 Brands');
40+
41+
// If either font failed to load, show fallbacks
42+
if (!freeLoaded || !brandsLoaded) {
43+
document.documentElement.classList.add('fonts-failed');
44+
console.warn('Font Awesome fonts failed to load, showing text fallbacks');
45+
}
46+
}).catch(function() {
47+
// If font loading fails, show fallbacks
48+
document.documentElement.classList.add('fonts-failed');
49+
});
50+
51+
// Also set a timeout - if fonts don't load within 3 seconds, show fallbacks
52+
setTimeout(function() {
53+
const freeLoaded = checkFontLoaded('Font Awesome 6 Free');
54+
const brandsLoaded = checkFontLoaded('Font Awesome 6 Brands');
55+
56+
if (!freeLoaded || !brandsLoaded) {
57+
document.documentElement.classList.add('fonts-failed');
58+
}
59+
}, 3000);
60+
}
61+
62+
// Run detection when DOM is ready
63+
if (document.readyState === 'loading') {
64+
document.addEventListener('DOMContentLoaded', detectFontLoading);
65+
} else {
66+
detectFontLoading();
67+
}
68+
})();
69+

docs/static/js/metadata.js

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,74 @@
11
// Fetch and display project metadata
22
(async function () {
3+
// Helper to safely get element and set text
4+
function safeSetText(elementId, text) {
5+
try {
6+
const el = document.getElementById(elementId);
7+
if (el) {
8+
el.textContent = text;
9+
}
10+
} catch (e) {
11+
console.warn("Failed to update element:", elementId, e);
12+
}
13+
}
14+
15+
// Helper to set default values
16+
function setDefaults() {
17+
safeSetText("crates-downloads", "-");
18+
safeSetText("github-stars", "-");
19+
safeSetText("github-downloads", "-");
20+
safeSetText("github-releases", "-");
21+
}
22+
323
try {
424
// Fetch metadata from our API endpoint (generated during build)
525
const basePath =
626
window.location.pathname.split("/").slice(0, -1).join("/") || "";
7-
const response = await fetch(`${basePath}/metadata.json`);
27+
const metadataUrl = `${basePath}/metadata.json`;
28+
29+
// Use fetch with timeout
30+
const controller = new AbortController();
31+
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout
32+
33+
const response = await fetch(metadataUrl, {
34+
signal: controller.signal,
35+
cache: 'no-cache'
36+
});
37+
38+
clearTimeout(timeoutId);
39+
840
if (!response.ok) {
9-
throw new Error("Failed to fetch metadata");
41+
throw new Error(`Failed to fetch metadata: ${response.status} ${response.statusText}`);
1042
}
1143

1244
const metadata = await response.json();
1345

1446
// Update crates.io downloads
15-
const cratesEl = document.getElementById("crates-downloads");
16-
if (cratesEl && metadata.crates_downloads) {
17-
cratesEl.textContent = formatNumber(metadata.crates_downloads);
47+
if (metadata.crates_downloads !== undefined) {
48+
safeSetText("crates-downloads", formatNumber(metadata.crates_downloads));
1849
}
1950

2051
// Update GitHub stars
21-
const starsEl = document.getElementById("github-stars");
22-
if (starsEl && metadata.github_stars) {
23-
starsEl.textContent = formatNumber(metadata.github_stars);
52+
if (metadata.github_stars !== undefined) {
53+
safeSetText("github-stars", formatNumber(metadata.github_stars));
2454
}
2555

2656
// Update GitHub binary downloads
27-
const downloadsEl = document.getElementById("github-downloads");
28-
if (downloadsEl && metadata.github_binary_downloads) {
29-
downloadsEl.textContent = formatNumber(metadata.github_binary_downloads);
57+
if (metadata.github_binary_downloads !== undefined) {
58+
safeSetText("github-downloads", formatNumber(metadata.github_binary_downloads));
3059
}
3160

3261
// Update GitHub releases
33-
const releasesEl = document.getElementById("github-releases");
34-
if (releasesEl && metadata.github_releases) {
35-
releasesEl.textContent = formatNumber(metadata.github_releases);
62+
if (metadata.github_releases !== undefined) {
63+
safeSetText("github-releases", formatNumber(metadata.github_releases));
3664
}
3765
} catch (error) {
38-
console.error("Error loading metadata:", error);
39-
// Set default values on error
40-
document.getElementById("crates-downloads").textContent = "-";
41-
document.getElementById("github-stars").textContent = "-";
42-
document.getElementById("github-downloads").textContent = "-";
43-
document.getElementById("github-releases").textContent = "-";
66+
// Log error but don't break the page
67+
if (error.name !== 'AbortError') {
68+
console.warn("Error loading metadata (this is non-critical):", error.message);
69+
}
70+
// Set default values on error - these are already "-" by default in HTML
71+
setDefaults();
4472
}
4573
})();
4674

0 commit comments

Comments
 (0)