NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==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(); }