daemon-sec-lotl

DÆMONBins: GTFOBins × LOLBAS × WADComs × LOOBins in one filterable catalog
git clone https://git.daemon-sec.xyz/daemon-sec-lotl.git
Log | Files | Refs | Submodules | README | LICENSE

init.ts (1790B)


      1 /**
      2  * Wires the shared daemon-sec effects into this site: the dot field
      3  * behind the top of each page and the cursor with its action pill.
      4  *
      5  * Astro's ClientRouter swaps the body on navigation, which removes the
      6  * cursor element and the canvas, so both are re-bound on every
      7  * `astro:page-load` and torn down on `astro:before-swap`.
      8  */
      9 import { mountParticleField } from './particle-field';
     10 import { mountCursor } from './cursor';
     11 
     12 const DECKS = 'gtfobins|lolbas|wadcoms|loobins|daemon';
     13 const TOOL = new RegExp(`^/(?:${DECKS})/[^/?#]+`);
     14 const DECK = new RegExp(`^/(?:${DECKS}|catalog)/?(?:[?#].*)?$`);
     15 
     16 let destroyCursor: (() => void) | null = null;
     17 const fields = new Set<() => void>();
     18 
     19 function bindFields(): void {
     20   document.querySelectorAll<HTMLCanvasElement>('canvas[data-dots]:not([data-bound])').forEach((cv) => {
     21     cv.dataset.bound = '';
     22     const destroy = mountParticleField(cv, {
     23       /* This site's mode-flipping tokens; a canvas inside a .plate band
     24          reads that band's values. */
     25       vars: { ink: '--text', base: '--base', iris: '--iris', love: '--love' },
     26       onFail: () => cv.closest<HTMLElement>('.dmn-page-field')?.remove(),
     27     });
     28     fields.add(destroy);
     29   });
     30 }
     31 
     32 function bindCursor(): void {
     33   if (document.querySelector('.dmn-cursor')) return;
     34   destroyCursor?.();
     35   destroyCursor = mountCursor({
     36     linkLabel: (href) => (TOOL.test(href) ? 'Read' : DECK.test(href) ? 'Browse' : null),
     37     /* Dark bands are `.plate`; `.plate-dawn` panels inside them are light. */
     38     isDark: (t) => t.closest('.plate, .plate-dawn')?.classList.contains('plate') ?? false,
     39   });
     40 }
     41 
     42 export function initDmn(): void {
     43   bindFields();
     44   bindCursor();
     45 }
     46 
     47 document.addEventListener('astro:before-swap', () => {
     48   fields.forEach((d) => d());
     49   fields.clear();
     50 });