Skip to content

Commit 2b5cc1c

Browse files
Inject nav-state script centrally
Inject a centralized nav-state script into generated site HTML during Build-Site so first-level menu defaults and persisted fold state are applied for all repositories using Process-PSModule. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 6f6c4f4 commit 2b5cc1c

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

.github/workflows/Build-Site.yml

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,103 @@ jobs:
179179
if (-not (Test-Path -Path '../../_site')) {
180180
throw "Expected Zensical output at ../../_site but it was not created."
181181
}
182+
183+
$navStateScript = @'
184+
(() => {
185+
const storageKey = "zensical-nav-state-v1";
186+
let lastSignature = "";
187+
188+
const getToggles = () =>
189+
Array.from(document.querySelectorAll("input.md-nav__toggle.md-toggle[id]"));
190+
191+
const getPrimaryList = () =>
192+
document.querySelector("nav.md-nav--primary > ul.md-nav__list");
193+
194+
const applyDefaultTopLevelState = (toggles) => {
195+
const primaryList = getPrimaryList();
196+
if (!primaryList) {
197+
return;
198+
}
199+
200+
const topLevelToggles = Array.from(
201+
primaryList.querySelectorAll(
202+
":scope > li > input.md-nav__toggle.md-toggle[id]"
203+
)
204+
);
205+
const topLevelIds = new Set(topLevelToggles.map((toggle) => toggle.id));
206+
207+
for (const toggle of toggles) {
208+
toggle.checked = topLevelIds.has(toggle.id);
209+
}
210+
};
211+
212+
const restoreState = (toggles) => {
213+
const raw = localStorage.getItem(storageKey);
214+
if (!raw) {
215+
applyDefaultTopLevelState(toggles);
216+
return;
217+
}
218+
219+
try {
220+
const state = JSON.parse(raw);
221+
for (const toggle of toggles) {
222+
if (Object.prototype.hasOwnProperty.call(state, toggle.id)) {
223+
toggle.checked = !!state[toggle.id];
224+
}
225+
}
226+
} catch {
227+
applyDefaultTopLevelState(toggles);
228+
}
229+
};
230+
231+
const persistState = (toggles) => {
232+
const state = {};
233+
for (const toggle of toggles) {
234+
state[toggle.id] = !!toggle.checked;
235+
}
236+
localStorage.setItem(storageKey, JSON.stringify(state));
237+
};
238+
239+
const initialize = () => {
240+
const toggles = getToggles();
241+
if (toggles.length === 0) {
242+
return;
243+
}
244+
245+
const signature = toggles.map((toggle) => toggle.id).join("|");
246+
if (signature === lastSignature) {
247+
return;
248+
}
249+
250+
lastSignature = signature;
251+
restoreState(toggles);
252+
for (const toggle of toggles) {
253+
if (toggle.dataset.navStateBound === "true") {
254+
continue;
255+
}
256+
257+
toggle.dataset.navStateBound = "true";
258+
toggle.addEventListener("change", () => persistState(getToggles()));
259+
}
260+
};
261+
262+
if (document.readyState === "loading") {
263+
document.addEventListener("DOMContentLoaded", initialize, { once: true });
264+
} else {
265+
initialize();
266+
}
267+
268+
setInterval(initialize, 500);
269+
})();
270+
'@
271+
272+
Get-ChildItem -Path '../../_site' -Filter '*.html' -Recurse | ForEach-Object {
273+
$html = Get-Content -Path $_.FullName -Raw
274+
if ($html -notmatch 'zensical-nav-state-v1') {
275+
$html = $html -replace '</body>', "<script>$navStateScript</script>`n</body>"
276+
Set-Content -Path $_.FullName -Value $html -NoNewline
277+
}
278+
}
182279
}
183280

184281
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0

0 commit comments

Comments
 (0)