#How to make external scripts work with ViewTransitions

16 messages · Page 1 of 1 (latest)

silver igloo
#

For my own scripts, adding the astro:after-swap event listener works. But what do i do to re-run scripts sourced externally from a CDN?

For example, I have this MathJax script import within my base layout:

<script
  id="MathJax-script"
  async
  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
  is:inline
  data-astro-rerun
></script>

The script doesn't run when i load the pages containing math expressions. I have to do a manual refresh and then the math expressions are rendered

bold tusk
#

Hi @silver igloo 👋, as you did, adding data-astro-rerun will re-execute the script on navigation. So I would assume that the script runs but doesn't have the desired effect if not executed during a full page load. Let me take a deeper look at the script. 👀

silver igloo
#

This is my BaseLayout.astro:

---
import "../styles/global.css";
import Header from "./Header.astro";
import Footer from "./Footer.astro";
import { ViewTransitions } from "astro:transitions";

interface Props { tabTitle: string; }
const { tabTitle } = Astro.props;
const siteDescription = "A site to organize and showcase my coding notes";
const baseUrl = import.meta.env.BASE_URL;
---

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="description" content="Code Journal" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="generator" content={Astro.generator} />
    <link rel="icon" type="image/svg+xml" href=`${baseUrl}/icons/code.svg` />
    <title>{tabTitle}</title>
    <meta name="description" content={siteDescription} />

    <script src="../utils/theme-script.ts"></script>
    <script src="../utils/mermaid-script.ts"></script>
    <script
      id="MathJax-script"
      async
      src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
      is:inline
      data-astro-rerun></script>

    <ViewTransitions fallback="swap" />
  </head>

  <body class="markdown-body">
    <Header />
    <main>
      <slot>This page is empty</slot>
    </main>
    <Footer />

    <script is:inline>
      // Reinitialize MathJax after page navigation
      document.addEventListener(
        "astro:after-swap",
        async () => await MathJax.typesetPromise()
      );

      // Init MathJax on page load
      document.addEventListener(
        "astro:page-load",
        async () => await MathJax.typesetPromise()
      );
    </script>
  </body>
</html>

I've tried adding the doing the MathJax.typeset() as well as await MathJax.typesetPromise() but the math expressions are either not formatted or only some terms get rendered.

silver igloo
bold tusk
#

Yes, we should shoot for MathJax.typeset()

#

Thanks for the repo!

bold tusk
#

The following seems to work for me. Want to give it a try?

<!-- MathJax for Math expressions -->
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" is:inline>
</script>

<script>
  // Reinitialize MathJax after page navigation
  // @ts-expect-error
  document.addEventListener("astro:after-swap", () => MathJax.typeset());
</script>
#

Basically, all of this was already in your repo 👍

#

(do not use astro-data-rerun in your case, the script is prepared for being re-executed via MathJax.typeset() and it should only be loaded once)

silver igloo
#

I made your changes and tried again but still similar behavior. Either no math expressions or only some are rendered on first load.

Makes me wonder if there's something wrong with my browser

#

Probably some MathJax behavior or config details i need to search

bold tusk
#

I only checked dev server with chrome. What do you use?

silver igloo
#

I'm also on the dev server. My system has:
Fedora 40 (workstation)
Chrome Version 129.0.6668.100 (Official Build) (64-bit)

silver igloo
#

Would it be easier to use some remark/rehype plugin? How do you make them work after you've added them into astro.config.mjs

silver igloo
#

Welp, converted the external script to an internal one and used the astro:after-swap there. Here's mathjax-script.ts:

const initializeMathJax = () => {
  // MathJax config
  // @ts-ignore
  window.MathJax = {
    loader: { load: ["[tex]/boldsymbol"] },
    tex: {
      inlineMath: [
        ["$", "$"],
        ["\\(", "\\)"],
      ],
      packages: { "[+]": ["boldsymbol"] },
    },
    svg: {
      fontCache: "global",
    },
  };

  // Create and append MathJax script dynamically
  const script = document.createElement("script");
  script.src = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js";
  script.async = true;
  document.head.appendChild(script);

  // Re-typeset MathJax when the page is ready
  script.onload = async () => {
    // @ts-ignore
    await MathJax.typesetPromise();
  };
};

// Init MathJax on page load
document.addEventListener("astro:page-load", initializeMathJax);

// Reapply MathJax after Astro swaps the page
document.addEventListener("astro:after-swap", initializeMathJax);
strong glenBOT