devela 0.27.0

A development layer of coherence.
Documentation
<!-- devela::src::_doc::header.html -->
<script>
  document.addEventListener("DOMContentLoaded", async function() {
    // Ensure this script runs only once per page load
    if (window.scriptLoaderInitialized) return;
    window.scriptLoaderInitialized = true;

    // console.log("Loaded: src/_doc/header.html:"); // DEBUG

    /* settings */

    const crateConfigs = {
      "devela": {
        katex: ["/zall", "/zall_", "/media/visual/color", "/num", "/phys"],
        katexChem: ["/zall/","/zall_", "/phys/"]
      },
    };

    // Find which crate this page belongs to
    let currentCrate = null;
    let relativePath = null;
    for (const crateName of Object.keys(crateConfigs)) {
      // Find the LAST occurrence of the crate name in the path
      const lastCrateIndex = window.location.pathname.lastIndexOf(`/${crateName}/`);
      if (lastCrateIndex !== -1) {
        currentCrate = crateName;
        // Extract everything after the last occurence of the crate name
        relativePath = window.location.pathname.slice(lastCrateIndex + crateName.length + 1);
        break;
      }
    }
    if (!currentCrate) return; // Not a known crate
    const config = crateConfigs[currentCrate];

    /* load resources */

    try {
      if (config.katex && config.katex.some(prefix => relativePath.startsWith(prefix))) {
        await loadKatex().catch(handleMathError);
      // } else {
      //   console.log("Not loading KaTeX for:", relativePath); // DEBUG
      }
      if (config.katexChem && config.katexChem.some(prefix => relativePath.startsWith(prefix))) {
        await loadKatexChem().catch(handleMathError);
      }
    } catch (error) {
      handleMathError(error);
    }

    /* resource loading functions */

    // INFO: https://katex.org/docs/browser.html#starter-template
    // INFO: https://github.com/KaTeX/KaTeX/tree/main/contrib/copy-tex
    async function loadKatex() {
      console.log("Loading KaTeX for:", relativePath);

      // Load CSS, and scripts sequentially
      const katexCSS = document.createElement("link");
      katexCSS.rel = "stylesheet";
      katexCSS.href = "https://cdn.jsdelivr.net/npm/katex@0.16.45/dist/katex.min.css"; // ↓ !=
      katexCSS.integrity = "sha384-UA8juhPf75SzzAMA/4fo3yOU7sBJ0om7SCD2GHq0fZqZco6tr1UCV7nUbk9J90JM";
      katexCSS.crossOrigin = "anonymous";
      document.head.appendChild(katexCSS);

      await loadScript({
        src: "https://cdn.jsdelivr.net/npm/katex@0.16.45/dist/katex.min.js",
        integrity: "sha384-Tt7wBxLKwSzFVRET4O4U9H6v8MNaQ/CjN2FMP4xFm0ErrFu6aNqoonRVW5W40iGI" // !=
      });
      await loadScript({
        src: "https://cdn.jsdelivr.net/npm/katex@0.16.45/dist/contrib/auto-render.min.js",
        integrity: "sha384-bjyGPfbij8/NDKJhSGZNP/khQVgtHUE5exjm4Ydllo42FwIgYsdLO2lXGmRBf5Mz" // ==
      });
      await loadScript({
        src: "https://cdn.jsdelivr.net/npm/katex@0.16.45/dist/contrib/copy-tex.min.js",
        integrity: "sha384-Pe2JWbaShhSRT0SESJ9XLPeAsi4yrNi7r/CiH0Coq7giBjK5a6Ae7XcybE8rNlQP" // ==
      });

      // Initialize KaTeX
      renderMathInElement(document.body, {
        delimiters: [
          {left: "$$", right: "$$", display: true},
          {left: "$", right: "$", display: false},
          {left: "\\(", right: "\\)", display: false},
          {left: "\\[", right: "\\]", display: true}
        ],
        trust: (context) => context.command === "\\href"
      });
      // Add custom styles: https://katex.org/docs/issues.html#css-customization
      const katexStyle = document.createElement("style");
      katexStyle.textContent = `
        .katex-display { overflow: hidden; }
        .docblock p { overflow-y: hidden; }
      `;
      document.head.appendChild(katexStyle);
    }

    // INFO: https://github.com/KaTeX/KaTeX/blob/main/contrib/mhchem/README.md
    async function loadKatexChem() {
      console.log("Loading KaTeX MhChem plugin for:", relativePath);
      await loadScript({
        src: "https://cdn.jsdelivr.net/npm/katex@0.16.45/dist/contrib/mhchem.min.js",
        integrity: "sha384-fB8BH//9nBzROkMUsu/Dr35jWHIbnKesUo9rW0hfEgw8mZGnkAyBAjKX9F98OVuo" // ==
      });
    }

    /* helper functions */

    function loadScript(config) {
      return new Promise((resolve, reject) => {
        const script = document.createElement("script");
        script.src = config.src;
        if (config.integrity) {
          script.integrity = config.integrity;
          script.crossOrigin = "anonymous";
        }
        script.onload = resolve;
        script.onerror = () => reject(new Error(`Failed to load script: ${config.src}`));
        document.head.appendChild(script);
      });
    }
    function handleMathError(error) {
      console.error("Math rendering error:", error);
    }
  });
</script>