mdbook-repl 0.2.0

A rust based mdbook preprocessor plugin that allows you to live code in your markdown book.
<!-- Custom REPL Script -->
<script>
  document.querySelectorAll(".repl").forEach((replElement) => {
    const iframeElement = replElement.querySelector("iframe");

    const id = replElement.getAttribute("data-id");
    const lang = replElement.getAttribute("data-lang");
    const code = replElement.nextElementSibling.innerText.trim();
    const readonly = replElement.getAttribute("data-readonly") === "true";
    let theme = mapTheme(localStorage.getItem("mdbook-theme"));

    const postmessage = (msg) => iframeElement.contentWindow.postMessage({ repl: msg }, "*");

    function mapTheme(bookTheme) {
      if (bookTheme === "coal" || bookTheme === "navy" || bookTheme === "ayu") return "dark";
      else return "light";
    }

    window.addEventListener("message", (event) => {
      if (event.source === window || !event.data.repl) return;

      const repl = event.data.repl;
      // if id is empty means iframe is first loaded, so we send configurations to it
      if (repl.id === "") postmessage({ id, editor: { theme, lang, code, defaultCode: code, readonly } });
      // if id is not empty and it's the same as the current repl, we can receive the data
      else if (repl.id === id) {
        if (repl.editor.theme !== theme) postmessage({ editor: { theme } });
        else if (repl.editor.lang !== lang) postmessage({ editor: { lang } });
        else if (repl.editor.readonly !== readonly) postmessage({ editor: { readonly } });
        else if (repl.editor.defaultCode !== code) postmessage({ editor: { defaultCode: code } });
        else {
          // update the iframe height
          replElement.style.height = repl.dimensions.height + "px";
          // show the iframe and hide the pre element
          iframeElement.classList.remove("hide");
          replElement.nextElementSibling.style.display = "none";
        }
      }
    });

    // listen to theme change
    document.querySelectorAll("button[role='menuitem'].theme").forEach((btn) => {
      btn.addEventListener("click", (event) => {
        theme = mapTheme(event.target.id);
        postmessage({ editor: { theme } });
      });
    });
  });
</script>