daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

Base.astro (8366B)


      1 ---
      2 import { ClientRouter } from 'astro:transitions';
      3 import Header from '../components/Header.astro';
      4 import Footer from '../components/Footer.astro';
      5 import Icon from '../components/Icon.astro';
      6 import SearchModal from '../components/SearchModal.astro';
      7 import { url } from '../lib/url';
      8 import '../styles/app.css';
      9 // Preload the two faces that paint above the fold — the wordmark in the
     10 // masthead and the DM Mono the masthead/labels use — so the header does not flash
     11 // its fallback on first paint. The rest load on demand via @font-face.
     12 import notoWordmark from '../fonts/noto-sans-display-var-latin.woff2';
     13 import dmMono from '../fonts/dm-mono-400.woff2';
     14 
     15 interface Props {
     16   title?: string;
     17   description?: string;
     18   railless?: boolean;
     19 }
     20 const {
     21   title = 'DÆMON//SEC — Cyber & IT Cheatsheet Vault',
     22   description = 'A curated, glassy vault of the best IT and cybersecurity cheatsheets — Active Directory, enumeration, exploitation, priv-esc, and more.',
     23 } = Astro.props;
     24 const canonical = new URL(Astro.url.pathname, Astro.site).href;
     25 ---
     26 <!doctype html>
     27 <html lang="en" data-theme="light">
     28   <head>
     29     <meta charset="utf-8" />
     30     <meta name="viewport" content="width=device-width, initial-scale=1" />
     31     <title>{title}</title>
     32     <meta name="description" content={description} />
     33     <link rel="canonical" href={canonical} />
     34     <link rel="icon" href={url('favicon.svg')} type="image/svg+xml" />
     35     <link rel="preload" href={notoWordmark} as="font" type="font/woff2" crossorigin />
     36     <link rel="preload" href={dmMono} as="font" type="font/woff2" crossorigin />
     37     <meta name="theme-color" content="#191724" media="(prefers-color-scheme: dark)" />
     38     <meta name="theme-color" content="#faf4ed" media="(prefers-color-scheme: light)" />
     39     <meta property="og:type" content="website" />
     40     <meta property="og:title" content={title} />
     41     <meta property="og:description" content={description} />
     42     <meta property="og:image" content={url('og.svg')} />
     43     <meta name="twitter:card" content="summary_large_image" />
     44     <!-- Set theme before first paint to avoid FOUC -->
     45     <script is:inline>
     46       (function () {
     47         function apply() {
     48           try {
     49             var t = localStorage.getItem('theme');
     50             // Dawn (cream) is the default, matching the main DÆMON site.
     51             if (t !== 'light' && t !== 'dark') t = 'light';
     52             document.documentElement.setAttribute('data-theme', t);
     53             document.documentElement.style.colorScheme = t;
     54           } catch (e) {
     55             document.documentElement.setAttribute('data-theme', 'light');
     56           }
     57         }
     58 
     59         apply();
     60 
     61         /* Every page ships `<html data-theme="light">` in its static markup,
     62            because that is the default and the build has no way to know what
     63            any given reader chose. On a view-transition navigation Astro
     64            swaps in the new document — attributes on <html> included — so
     65            that baked-in "light" overwrites the live attribute and the page
     66            reverts to dawn mid-session.
     67 
     68            This listener re-applies the stored choice on every swap. It runs
     69            in `astro:after-swap`, which fires after the new document is in
     70            place but before it is painted, so the correction never flashes.
     71 
     72            The listener is registered once, from an inline head script that
     73            executes on the first full load only — which is exactly why it
     74            has to be `is:inline` and live here rather than in app.ts: a
     75            bundled module re-imported per page would re-register it, and a
     76            deferred one would run too late to beat the paint. */
     77         document.addEventListener('astro:after-swap', apply);
     78       })();
     79     </script>
     80     <!-- Page iris. Every internal navigation opens the next page as a
     81          circle from the link that was pressed: the theme wipe's gesture,
     82          at page pace. The CSS is beside the theme wipe in global.css;
     83          this only supplies the origin and the end radius. -->
     84     <script is:inline>
     85       (function () {
     86         function centre(el) {
     87           var r = el.getBoundingClientRect();
     88           return { x: r.left + r.width / 2, y: r.top + r.height / 2 };
     89         }
     90 
     91         /* Where the last click landed. Capture phase, so it is recorded
     92            before the ClientRouter's own listener takes the click. A click
     93            with detail 0 came from the keyboard and has no pointer
     94            position, so it opens from the middle of the control. */
     95         var press = null;
     96         document.addEventListener('click', function (e) {
     97           var at = e.detail === 0 && e.target instanceof Element
     98             ? centre(e.target)
     99             : { x: e.clientX, y: e.clientY };
    100           at.t = Date.now();
    101           press = at;
    102         }, true);
    103 
    104         var origin = null;
    105         function paint() {
    106           if (!origin) return;
    107           var s = document.documentElement.style;
    108           s.setProperty('--vt-x', origin.x + 'px');
    109           s.setProperty('--vt-y', origin.y + 'px');
    110           s.setProperty('--vt-r', origin.r + 'px');
    111         }
    112 
    113         /* A press older than a second did not cause this navigation (back,
    114            forward, a scripted one), so it falls back to the link Astro
    115            reports, then to the middle of the screen. The radius reaches
    116            the farthest corner exactly, so the circle finishes as it
    117            covers the page rather than part-way through an overshoot. */
    118         document.addEventListener('astro:before-preparation', function (e) {
    119           var at = press && Date.now() - press.t < 1000 ? press
    120             : e.sourceElement instanceof Element ? centre(e.sourceElement)
    121             : { x: innerWidth / 2, y: innerHeight / 2 };
    122           origin = {
    123             x: at.x,
    124             y: at.y,
    125             r: Math.hypot(Math.max(at.x, innerWidth - at.x), Math.max(at.y, innerHeight - at.y)),
    126           };
    127           paint();
    128         });
    129 
    130         /* The swap replaces <html>'s attributes with the new page's, and
    131            the inline style carrying these three goes with them, so they
    132            are put back before the new page is painted, for the same
    133            reason as the theme note above. */
    134         document.addEventListener('astro:after-swap', paint);
    135       })();
    136     </script>
    137     <ClientRouter />
    138   </head>
    139   <body>
    140     <a class="skip-link" href="#main">Skip to content</a>
    141     <!-- Shared arrowhead for every inline-SVG flowchart (src/styles/flow.css).
    142          Defined once here so a diagram only has to reference `url(#flow-arrow)`.
    143          `context-stroke` makes the head take each edge's own stroke colour, so
    144          one marker serves foam forward edges and love back-edges alike. -->
    145     <svg width="0" height="0" aria-hidden="true" style="position:absolute" focusable="false">
    146       <defs>
    147         <marker id="flow-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7"
    148                 markerHeight="7" orient="auto-start-reverse" markerUnits="userSpaceOnUse">
    149           <path class="flow-arrow" d="M0,0 L10,5 L0,10 z" fill="context-stroke" />
    150         </marker>
    151       </defs>
    152     </svg>
    153     <!-- The film over the whole page. It is what keeps a flat colour
    154          reading as stock rather than as a swatch, and it stands in for the
    155          texture the old glass build got from blur. -->
    156     <span class="grain" aria-hidden="true"></span>
    157     <Header />
    158     <main id="main" tabindex="-1">
    159       <slot />
    160     </main>
    161     <Footer />
    162     <!-- Sheets run to a couple of thousand lines; without this the only way
    163          back to the header is a long scroll. Hidden until app.ts marks it
    164          visible, so it never shows on a page short enough not to need it. -->
    165     <button id="to-top" class="to-top" type="button" hidden aria-label="Back to top">
    166       <Icon name="chevron" />
    167     </button>
    168     <SearchModal />
    169     <script>
    170       import '../scripts/app.ts';
    171     </script>
    172     <script>
    173       // The effects shared with daemon-sec.xyz (src/scripts/dmn): the cursor
    174       // pill and the sheet image viewer. Re-bound after each navigation.
    175       import { initDmn } from '../scripts/dmn/init';
    176       document.addEventListener('astro:page-load', initDmn);
    177       if (document.readyState !== 'loading') initDmn();
    178       else document.addEventListener('DOMContentLoaded', initDmn, { once: true });
    179     </script>
    180   </body>
    181 </html>