source: Klonkt/src/assets/js/mod/chrome.js@ 1e172f3

main
Last change on this file since 1e172f3 was 1e172f3, checked in by roboburr <roboburr@…>, 5 weeks ago

Modules laden vanuit de shell in plaats van inline script (shaer-bqr, stap 1)

Het mechanisme uit optie C, met de bottom-tab als eerste geval zodat het ook
te bewijzen is.

WAAROM. De CSP-nonce rouleert per verzoek (shaer-0i6). Een script dat via htmx
binnenkomt draagt dus een nonce die het document niet kent en wordt geweigerd.
De chrome komt bij ELKE navigatie out-of-band opnieuw binnen, dus daar valt de
JS bij de eerste klik binnen de site al weg.

HOE. Een bootstrap in shell.ejs -- die komt alleen bij een volledige laadbeurt
binnen en heeft dus wel de goede nonce. Hij leest body[data-js], een lijst
modulenamen, en importeert ze uit /assets/js/mod/. Een dynamische import vanuit
een vertrouwd script is precies waar strict-dynamic voor bedoeld is, dus de
module zelf heeft geen nonce nodig.

Bij een htmx-navigatie zet de pcmsNav-trigger data-js opnieuw en haalt de
bootstrap op wat er nieuw bij staat. 'chrome' staat er altijd bij.

De naam wordt een PAD, dus hij moet door /[a-z0-9-]+$/ -- geen punt, geen
schuine streep.

EERSTE GEVAL: de zoekknop van de bottom-tab. Geen servergegevens erin, al
gedelegeerd, al voorzien van een slot -- dus de verhuizing verandert niets aan de
logica en het mechanisme is er echt mee te toetsen.

WAT DIT BLOOTLEGT VOOR DE VOLGENDE STAP: het topnav-script interpoleert
vertalingen (<%= t('search.section_posts') %>) en kan dus niet zomaar een
statisch bestand worden. Servergegevens horen via een data-attribuut naar een
module, niet via interpolatie in de code. Dat is een eigen stap en staat als
zodanig in mod/chrome.js opgeschreven.

Templates compileren, suite 551/551. Het echte bewijs is een klik BINNEN de site:
na een herlading werkt alles toch al.

  • Property mode set to 100644
File size: 1.9 KB
Line 
1// De chrome: alles wat om elke pagina heen staat (shaer-bqr).
2//
3// Dit stond als inline <script> in de partials. Dat kan niet blijven: de
4// CSP-nonce rouleert per verzoek, en de chrome wordt bij ELKE htmx-navigatie
5// out-of-band opnieuw ingevoegd. Zo'n script draagt dan een nonce die het
6// document niet kent en wordt geweigerd -- dus viel de chrome-JS bij de eerste
7// klik binnen de site al weg (shaer-0i6).
8//
9// Nu een module, geladen door de bootstrap in shell.ejs. Die zit in het
10// document zelf, heeft dus wel de goede nonce, en een dynamische import vanuit
11// een vertrouwd script is precies waar 'strict-dynamic' voor is.
12//
13// TWEE REGELS voor alles wat hier bij komt:
14//
15// GEDELEGEERD luister op document, nooit op een element dat er nu staat. De
16// chrome wordt vervangen, dus een vastgehouden verwijzing is na
17// een navigatie een verwijzing naar iets dat weg is.
18// IDEMPOTENT de module kan een tweede keer geladen worden. Een slot op
19// window voorkomt dat er een tweede stel luisteraars bij komt --
20// dat is hoe de themaknop ooit twee keer vuurde en dus niets deed.
21//
22// En: GEEN servergegevens in deze code. Interpolatie hoort niet in een statisch
23// bestand; wat de server wil meegeven komt via een data-attribuut op een element.
24
25(function () {
26 'use strict';
27 if (window.__chromeMod) return;
28 window.__chromeMod = true;
29
30 // De zoekknop in de bottom-tab opent de overlay. De overlay zelf wordt bij een
31 // htmx-navigatie vervangen, dus hem hier vasthouden zou na een klik binnen de
32 // site niets meer opleveren: elke keer opnieuw opzoeken.
33 document.addEventListener('click', function (e) {
34 if (!e.target.closest || !e.target.closest('#bottom-tab-search-toggle')) return;
35 var o = document.getElementById('search-overlay');
36 if (o) {
37 o.hidden = false;
38 var i = o.querySelector('input');
39 if (i) i.focus();
40 }
41 });
42})();
Note: See TracBrowser for help on using the repository browser.