コードを自動的に保存して予期せぬ喪失から守ります
// ==UserScript== // @name AtCoder Save Buffer // @namespace http://atcoder.jp/ // @version 0.1 // @description コードを自動的に保存して予期せぬ喪失から守ります // @author magurofly // @match https://atcoder.jp/contests/*/tasks/* // @grant none // ==/UserScript== // getSourceCode() // $ (async function() { 'use strict'; const QUEUE_MAX = 12; const STORAGE = sessionStorage; function setSourceCode(code) { if ($(".btn-toggle-editor").hasClass("active")) { $(".plain-textarea").val(code); } else { $(".editor").data("editor").doc.setValue(code); } } if (!("atcoder_save_buffer_queue" in STORAGE)) { STORAGE.atcoder_save_buffer_queue = "[]"; } const digest = [...new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(location.pathname)))].map(byte => byte.toString(16).padStart(2, "0")).join(""); const id = "atcoder_save_buffer_" + digest; addEventListener("beforeunload", () => { const queue = JSON.parse(localStorage.atcoder_save_buffer_queue); const i = queue.indexOf(id); if (i != -1) queue.splice(i, 1); if (queue.length >= QUEUE_MAX) { const prev = queue.shift(); delete STORAGE[prev]; } queue.push(id); STORAGE[id] = getSourceCode(); STORAGE.atcoder_save_buffer_queue = JSON.stringify(queue); }); $(() => { if (id in localStorage) { setSourceCode(localStorage[id]); console.info("restored saved buffer"); } }); })();