/** * reinit-handlers.js — registers the standard set of HTMX swap re-initialisers. * * Loaded AFTER htmx-reinit.js and after the underlying libraries (hljs, * cytoscape) so the handler bodies can call them directly. Each handler * scopes its DOM queries to the swap target — passing an Element to * querySelectorAll only searches that subtree, so handlers are O(swap) * rather than O(document) on every swap. */ (function () { 'use strict'; if (!window.RusteloReinit) { console.error('[reinit-handlers] htmx-reinit.js must load before this script'); return; } // --- highlight.js ------------------------------------------------------- // Highlight every
 in the swapped region that isn't already
  // decorated. hljs marks processed blocks by adding the .hljs class, which
  // makes the selector self-cleaning on re-runs.
  window.RusteloReinit.register('highlight', function (scope) {
    if (typeof window.hljs === 'undefined' || !window.hljs.highlightElement) {
      return;
    }
    scope.querySelectorAll('pre code:not(.hljs)').forEach(function (block) {
      window.hljs.highlightElement(block);
    });
  });

  // --- theme-init ---------------------------------------------------------
  // Re-apply the dark/light class on  from the theme cookie. Cheap
  // and idempotent: setting an already-set class is a no-op.
  window.RusteloReinit.register('theme', function (_scope) {
    const matches = document.cookie.match(/theme=([^;]+)/);
    const theme = matches ? matches[1] : 'dark';
    const html = document.documentElement;
    const wantDark = theme === 'dark' ||
      (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
    if (wantDark) {
      html.classList.add('dark');
      html.classList.remove('light');
    } else {
      html.classList.add('light');
      html.classList.remove('dark');
    }
  });

  // --- tag-filters --------------------------------------------------------
  // Re-arm the filter pill click handlers in the swapped region. The
  // legacy script set window.tagFiltersInitialized = true and bailed on
  // subsequent runs; bypass that flag by re-binding only pills that don't
  // yet carry our data-reinit attribute.
  window.RusteloReinit.register('tag-filters', function (scope) {
    if (typeof window.filterPostsByTag !== 'function') {
      return;
    }
    scope.querySelectorAll('[data-tag-pill]:not([data-tag-reinit])').forEach(function (pill) {
      pill.setAttribute('data-tag-reinit', '1');
      pill.addEventListener('click', function (ev) {
        ev.preventDefault();
        const tag = pill.getAttribute('data-tag');
        if (tag) {
          window.filterPostsByTag(tag);
        }
      });
    });
  });

  // --- scroll-to-top -------------------------------------------------------
  // Wires the footer "Scroll to top" button emitted by UnifiedFooter (SSR).
  // The Leptos on:click handler is WASM-only and compiles to nothing in SSR;
  // this provides the equivalent for the HTMX profile via event delegation.
  // Runs once: the button lives in the footer which is never swapped.
  (function () {
    if (window.__rusteloScrollToTopWired) {
      return;
    }
    window.__rusteloScrollToTopWired = true;
    document.addEventListener('click', function (ev) {
      var btn = ev.target && ev.target.closest('button[aria-label="Scroll to top"]');
      if (btn) {
        ev.preventDefault();
        window.scrollTo({ top: 0, behavior: 'smooth' });
      }
    });
  })();

  // --- content-graph ------------------------------------------------------
  // ContentGraph.render is idempotent against the same container id (it
  // tears down the previous instance internally). Only fire when the
  // swap actually contains a graph container.
  window.RusteloReinit.register('content-graph', function (scope) {
    if (!window.ContentGraph || typeof window.ContentGraph.render !== 'function') {
      return;
    }
    scope.querySelectorAll('[data-content-graph]').forEach(function (el) {
      const containerId = el.getAttribute('id');
      const focusId = el.getAttribute('data-focus-id') || null;
      const theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
      if (containerId) {
        try {
          window.ContentGraph.render(containerId, focusId, theme);
        } catch (err) {
          console.error('[reinit:content-graph] render failed', err);
        }
      }
    });
  });
})();