Dedonych / ShikiPrettier

// ==UserScript==
// @name         ShikiPrettier 
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Prettier for shikimori style editor
// @author       Dedonych
// @match        https://shikimori.one/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=shikimori.one
// @require      https://unpkg.com/prettier@3.3.3/standalone.js
// @require      https://unpkg.com/prettier@3.3.3/plugins/postcss.js
// @grant        none
// @updateURL    https://openuserjs.org/meta/Dedonych/ShikiPrettier.meta.js
// @downloadURL  https://openuserjs.org/install/Dedonych/ShikiPrettier.user.js
// @license      MIT
// ==/UserScript==
{
  const setup = () => {
    if (document.getElementById("prettier-btn")) return;
    //check for current page as edit/styles
    if (
      !location.pathname.includes("/edit/styles") ||
      !document.querySelector(".CodeMirror")
    )
      return setTimeout(() => setup(), 1000);
    //create button "Prettier"
    const btn = Object.assign(document.createElement("input"), {
      type: "submit",
      onclick: async function (e) {
        e.preventDefault();
        this.disabled = true;
        this.value = "loading...";
        const cm = document.querySelector(".CodeMirror").CodeMirror;
        const code = cm.getValue();
        try {
          const formatted = await prettier.format(code, {
            parser: "css",
            plugins: prettierPlugins,
          });
          cm.setValue(formatted);
        } catch (err) {
          const {
            cause: { reason, line, column },
            codeFrame,
          } = err;
          createErrorPrettier(reason, line, column, codeFrame);
        } finally {
          this.disabled = false;
          this.value = "Prettier";
        }
      },
      value: "Prettier",
      id: "prettier-btn",
      style: "margin-right:16px;background:#49749e",
    });

    document
      .querySelectorAll(".p-profiles-edit .editor-container .buttons").forEach(e=>e.prepend(btn.cloneNode()));
  };
// On error
  function createErrorPrettier(error, line, column, frame) {
    if (document.querySelector(".shiki-prettier_error")) {
      document.querySelector(".shiki-prettier_error").remove();
    }
    const errorElementDiv = Object.assign(document.createElement("div"), {
      className:
        "toastify on error toastify-right toastify-top shiki-prettier_error",
      innerHTML: `
          <b>ShikiPrettier Error:</b>
          <p>${error}</p>
          <p>line: ${line}; column:${column}</p>
          <pre>${frame}</pre>
          `,
      style: "transform: translate(0px, 0px); top: 15px;",
    });
    const btnClose = Object.assign(document.createElement("button"), {
      className: "toast-close",
      onclick: () => {
        errorElementDiv.classList.remove("on");
        setTimeout(() => errorElementDiv.remove(), 400);
      },
    });
    errorElementDiv.append(btnClose);
    setTimeout(() => errorElementDiv.remove(), 10000);
    document.body.prepend(errorElementDiv);
  }
  addEventListener("turbolinks:load", setup);
  addEventListener("DOMContentLoaded", setup);
  setup();
}