Make sidebar sections open when clicked

This commit is contained in:
2026-07-22 16:51:11 -05:00
parent 1237b330aa
commit 4f42fdeda9
3 changed files with 217 additions and 31 deletions
+16 -16
View File
@@ -53,6 +53,22 @@ aliases:
imageClass="hx:top-[40%] hx:left-[24px] hx:w-[180%] hx:sm:w-[110%] hx:dark:opacity-80"
link="wiki"
>}}
{{< hextra/feature-card
title="Privacy Tools"
subtitle="The essential tools you need to safeguard your digital privacy, chosen by community consensus."
class="hx:aspect-auto hx:md:aspect-[1.1/1] hx:max-md:min-h-[340px] pg:colored-card"
image="pg-home-privacy-tools.png"
imageClass="hx:top-[40%] hx:left-[24px] hx:w-[180%] hx:sm:w-[110%] hx:dark:opacity-80"
link="tools"
>}}
{{< hextra/feature-card
title="News Briefs"
subtitle="Stay updated with the latest news and developments in the world of cybersecurity, privacy, and digital rights."
class="hx:aspect-auto hx:md:aspect-[1.1/1] hx:max-md:min-h-[340px] pg:colored-card"
image="pg-home-privacy-news.png"
imageClass="hx:top-[40%] hx:left-[24px] hx:w-[180%] hx:sm:w-[110%] hx:dark:opacity-80"
link="https://www.privacyguides.org/news/"
>}}
{{< hextra/feature-card
title="Educational Videos"
subtitle="Watch our educational videos to learn more about digital privacy and how to protect yourself online."
@@ -69,14 +85,6 @@ aliases:
imageClass="hx:top-[40%] hx:left-[24px] hx:w-[180%] hx:sm:w-[110%] hx:dark:opacity-80"
link="activism"
>}}
{{< hextra/feature-card
title="Privacy Tools"
subtitle="The essential tools you need to safeguard your digital privacy, chosen by community consensus."
class="hx:aspect-auto hx:md:aspect-[1.1/1] hx:max-md:min-h-[340px] pg:colored-card"
image="pg-home-privacy-tools.png"
imageClass="hx:top-[40%] hx:left-[24px] hx:w-[180%] hx:sm:w-[110%] hx:dark:opacity-80"
link="tools"
>}}
{{< hextra/feature-card
title="Community Forum"
subtitle="Join the conversation, get answers, and connect with others who share your commitment to digital privacy."
@@ -85,14 +93,6 @@ aliases:
imageClass="hx:top-[40%] hx:left-[24px] hx:w-[180%] hx:sm:w-[110%] hx:dark:opacity-80"
link="https://discuss.privacyguides.net"
>}}
{{< hextra/feature-card
title="News Briefs"
subtitle="Stay updated with the latest news and developments in the world of cybersecurity, privacy, and digital rights."
class="hx:aspect-auto hx:md:aspect-[1.1/1] hx:max-md:min-h-[340px] pg:colored-card"
image="pg-home-privacy-news.png"
imageClass="hx:top-[40%] hx:left-[24px] hx:w-[180%] hx:sm:w-[110%] hx:dark:opacity-80"
link="https://www.privacyguides.org/news/"
>}}
{{< /hextra/feature-grid >}}
<div class="hx:mt-12"></div>
+2 -15
View File
@@ -1,6 +1,7 @@
# Hugo configuration file
title: Privacy Guides
relativeURLs: true
baseURL: https://wiki.privacyguides.org
locale: en-US
# temporarily ignore blog content
ignoreFiles:
@@ -101,17 +102,3 @@ outputs:
home: [HTML, RSS, llms]
page: [HTML, markdown, RSS]
section: [HTML, RSS]
defaultContentLanguage: en
defaultContentLanguageInSubdir: false
languages:
en:
languageName: English
weight: 1
# baseURL: https://en.privacyguides.org
contentDir: 'content'
# fr:
# languageName: Français
# weight: 2
# baseURL: https://fr.privacyguides.org
# contentDir: 'translations/fr'
+199
View File
@@ -0,0 +1,199 @@
<script>
(() => {
const redirectCache = new Map();
const forceNavigatePaths = new Set([]);
function normalizePathname(pathname) {
const normalized = pathname.replace(/\/+$/, '');
return normalized || '/';
}
function urlsReferToSamePage(firstUrl, secondUrl) {
const first = new URL(firstUrl, location.href);
const second = new URL(secondUrl, location.href);
return (
first.origin === second.origin &&
normalizePathname(first.pathname) ===
normalizePathname(second.pathname) &&
first.search === second.search
);
}
function getMetaRefreshDestination(documentCopy, sourceUrl) {
const refresh = documentCopy.querySelector(
'meta[http-equiv="refresh" i]'
);
if (!refresh) return null;
const content = refresh.getAttribute('content') || '';
const match = content.match(
/^\s*\d+(?:\.\d+)?\s*;\s*url\s*=\s*(.+?)\s*$/i
);
if (!match) return null;
const destination = match[1]
.trim()
.replace(/^(['"])(.*)\1$/, '$2');
try {
return new URL(destination, sourceUrl).href;
} catch {
return null;
}
}
async function redirectsToAnotherPage(href) {
const requestedUrl = new URL(href, location.href);
const cacheKey = requestedUrl.href;
if (redirectCache.has(cacheKey)) {
return redirectCache.get(cacheKey);
}
const checkPromise = (async () => {
try {
const response = await fetch(requestedUrl.href, {
method: 'GET',
redirect: 'follow',
credentials: 'same-origin',
cache: 'force-cache'
});
/*
* Detect ordinary HTTP redirects while ignoring redirects that
* only add or remove a trailing slash.
*/
if (
response.redirected &&
!urlsReferToSamePage(requestedUrl.href, response.url)
) {
return true;
}
/*
* Some static-site generators implement redirects using an HTML
* meta-refresh page rather than an HTTP redirect.
*/
const contentType =
response.headers.get('content-type') || '';
if (!contentType.includes('text/html')) {
return false;
}
const html = await response.text();
const documentCopy = new DOMParser().parseFromString(
html,
'text/html'
);
const destination = getMetaRefreshDestination(
documentCopy,
requestedUrl.href
);
return (
destination !== null &&
!urlsReferToSamePage(requestedUrl.href, destination)
);
} catch (error) {
console.warn(
`Could not check whether ${requestedUrl.href} redirects:`,
error
);
/*
* Preserve normal navigation when detection fails.
*/
return false;
}
})();
redirectCache.set(cacheKey, checkPromise);
return checkPromise;
}
document.addEventListener(
'click',
async (event) => {
if (!(event.target instanceof Element)) return;
/*
* Preserve middle-clicks and modifier-clicks so users can still
* open links in new tabs or windows.
*/
if (
event.button !== 0 ||
event.ctrlKey ||
event.metaKey ||
event.shiftKey ||
event.altKey
) {
return;
}
const link = event.target.closest(
'.hextra-sidebar-container a[href]'
);
if (!link) return;
const linkUrl = new URL(link.href, location.href);
/*
* Do not alter external links.
*/
if (linkUrl.origin !== location.origin) return;
const row = link.parentElement;
const toggleButton = row?.querySelector(
'.hextra-sidebar-collapsible-button'
);
/*
* Links without a collapsible arrow are ordinary page links.
*/
if (!toggleButton) return;
/*
* Explicitly allow known section pages to navigate normally.
*/
if (
forceNavigatePaths.has(
normalizePathname(linkUrl.pathname)
)
) {
return;
}
/*
* Temporarily prevent navigation while checking whether this is a
* redirect-only section link or a real page.
*/
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
const isRedirect = await redirectsToAnotherPage(linkUrl.href);
if (isRedirect) {
/*
* Reuse Hextra's existing collapsible-sidebar behavior.
*/
toggleButton.click();
} else {
/*
* This section has its own page, so navigate to it normally.
*/
location.assign(linkUrl.href);
}
},
true
);
})();
</script>