WaniKani Community Details Keep Open State

Keep [details] or <details> tags as open or close, and not changing with edits

// ==UserScript==
// @name         WaniKani Community Details Keep Open State
// @namespace    https://github.com/patarapolw/wanikani-userscript
// @version      0.1.0
// @description  Keep [details] or <details> tags as open or close, and not changing with edits
// @author       polv
// @license      MIT
// @match        https://community.wanikani.com/*
// @icon         https://www.google.com/s2/favicons?domain=wanikani.com
// @grant        none
// ==/UserScript==

(() => {
  // src/shared/discourse.ts
  function getWindow() {
    return typeof unsafeWindow === "undefined" ? window : unsafeWindow;
  }

  // src/forum-details-open.ts
  var elPreview = null;
  var openKeys = /* @__PURE__ */ new Map();
  var EDITOR_PREVIEW_CLASS = "d-editor-preview";
  var obs = new MutationObserver((muts) => {
    muts.forEach((m) => {
      for (const n of m.addedNodes) {
        if (n instanceof HTMLElement && n.classList.contains(EDITOR_PREVIEW_CLASS)) {
          elPreview = n;
          openKeys.clear();
        }
      }
      for (const n of m.removedNodes) {
        if (n instanceof HTMLElement && n.classList.contains(EDITOR_PREVIEW_CLASS)) {
          elPreview = null;
        }
      }
    });
  });
  obs.observe(document.body, { childList: true, subtree: true });
  function getDetailsKey(d) {
    var _a;
    return ((_a = d.querySelector("summary")) == null ? void 0 : _a.innerHTML) || "";
  }
  var markdownIt = getWindow().require("pretty-text/engines/discourse-markdown-it");
  var oldCook = markdownIt.cook;
  markdownIt.cook = function(raw, opts) {
    let html = oldCook.bind(this)(raw, opts);
    if (elPreview) {
      const keys = /* @__PURE__ */ new Map();
      const makeKey = (key) => {
        const k0 = key;
        let i = keys.get(k0) || 0;
        if (!i) {
          key = JSON.stringify([key, ++i]);
        } else {
          key = JSON.stringify(key);
        }
        keys.set(k0, i);
        return key;
      };
      elPreview.querySelectorAll("details").forEach((details) => {
        let key = getDetailsKey(details);
        if (key) {
          openKeys.set(makeKey(key), details.open);
        }
      });
      keys.clear();
      const div = document.createElement("div");
      div.innerHTML = html;
      div.querySelectorAll("details").forEach((details) => {
        let key = getDetailsKey(details);
        if (key) {
          key = makeKey(key);
          if (details.hasAttribute("open"))
            return;
          const state = openKeys.get(key);
          if (typeof state === "boolean") {
            details.open = state;
          }
        }
      });
      html = div.innerHTML;
    }
    return html;
  };
})();