您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
replaces Y/N and other placeholders in x Reader fic with the name of your choice
当前为
// ==UserScript== // @name AO3: Replace Y/N in works with your name // @description replaces Y/N and other placeholders in x Reader fic with the name of your choice // @author escctrl // @namespace https://greasyfork.org/en/users/906106-escctrl // @version 0.2 // @match https://archiveofourown.org/works/* // @license MIT // @require https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js // @require https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js // @grant none // ==/UserScript== var given_name = "", family_name = ""; // the function to deal with all the configuration - using jQueryUI for dialogs (function($) { 'use strict'; // retrieve localStorage on page load if (!localStorage) { console.log("The userscript \"AO3: Replace Y/N in works with your name\" terminated early because local storage cannot be accessed"); return false; } else loadconfig(); // if no other script has created it yet, write out a "Userscripts" option to the main navigation if ($('#scriptconfig').length == 0) { $('#header ul.primary.navigation li.dropdown').last() .after(`<li class="dropdown" id="scriptconfig"> <a class="dropdown-toggle" href="/" data-toggle="dropdown" data-target="#">Userscripts</a> <ul class="menu dropdown-menu"></ul> </li>`); } // then add this script's config option to navigation dropdown $('#scriptconfig .dropdown-menu').append(`<li><a href="javascript:void(0);" id="opencfg_replaceYN">Replace Y/N</a></li>`); // if the background is dark, use the dark UI theme to match let dialogtheme = lightOrDark($('body').css('background-color')) == "dark" ? "ui-darkness" : "base"; // adding the jQuery stylesheet to style the dialog, and fixing the interference of AO3's styling $("head").append(`<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/${dialogtheme}/jquery-ui.css">`) .append(`<style tyle="text/css"> #cfgdialog_replaceYN legend {font-size: inherit; height: auto; width: auto; opacity: inherit;} #cfgdialog_replaceYN form {box-shadow: revert; cursor:auto;} #cfgdialog_replaceYN fieldset {background: revert; box-shadow: revert;} #cfgdialog_replaceYN input[type='text'] { position: relative; top: 1px; padding: .4em; width: 95%; } #cfgdialog_replaceYN fieldset p { padding-top: 0; padding-left: 0; padding-right: 0; } </style>`); // the config dialog container let cfg = document.createElement('div'); cfg.id = 'cfgdialog_replaceYN'; $(cfg).html(`<form> <fieldset><legend>Given Name</legend> <p>replaces Y/N and G/N in the work text</p> <input type="text" name="given" id="given" value="${given_name}" placeholder="your given name"> </fieldset> <fieldset><legend>Family Name</legend> <p>replaces F/N, L/N and Y/L/N in the work text</p> <input type="text" name="family" id="family" value="${family_name}" placeholder="your family name"> </fieldset> <p>Any changes to this configuration will only take effect after reloading the page!</p> <!-- Allow form submission with keyboard without duplicating the dialog button --> <input type="submit" tabindex="-1" style="display: none;"> </form>`); // attach it to the DOM so that selections work $("body").append(cfg); let dialogwidth = parseInt($("body").css("width")); // parseInt ignores letters (px) dialogwidth = dialogwidth > 400 ? 400 : dialogwidth * 0.9; // initialize the dialog (but don't open it) $( "#cfgdialog_replaceYN" ).dialog({ appendTo: "#main", modal: true, title: 'Replace Y/N Configuration', draggable: true, resizable: false, autoOpen: false, width: dialogwidth, position: {my:"center", at: "center top"}, buttons: { Reset: deleteconfig, Save: setconfig, Cancel: closedialog } }); function closedialog() { $( "#cfgdialog_replaceYN" ).dialog( "close" ); } // on click of the menu, open the configuration dialog $("#opencfg_replaceYN").on("click", function(e) { $( "#cfgdialog_replaceYN" ).dialog('open'); }); // event triggers if form is submitted with the <enter> key $( "#cfgdialog_replaceYN form" ).on("submit", (e)=>{ e.preventDefault(); setconfig(); }); // functions to deal with the localStorage function loadconfig() { given_name = localStorage.getItem('script-replaceYN-given') || ""; family_name = localStorage.getItem('script-replaceYN-family') || ""; } function setconfig() { // grab form fields for easier selection later let new_given = $(`#cfgdialog_replaceYN form [name="given"]`).val(); let new_family = $(`#cfgdialog_replaceYN form [name="family"]`).val(); localStorage.setItem('script-replaceYN-given', new_given); localStorage.setItem('script-replaceYN-family', new_family); closedialog(); } function deleteconfig() { // empties all fields in the form $('#cfgdialog_replaceYN form [name]').val(""); // delete the localStorage localStorage.removeItem('script-replaceYN-given'); localStorage.removeItem('script-replaceYN-family'); closedialog(); } })(jQuery); // function to run the text replacement on Y/N and [Y/]L/N etc // sadly this can run only on initial page load - after that the work text has been changed and we wouldn't find the placeholders to replace function replaceYN() { // don't run a replace if no name has been configured if (given_name != "" || family_name != "") { document.querySelectorAll('#main #chapters .userstuff > *').forEach((p) => { p.innerHTML = p.innerHTML .replace(/\(Y\/N\)|Y\/N/ig, given_name).replace(/\(G\/N\)|G\/N/ig, given_name) .replace(/\((Y\/)?L\/N\)|(Y\/)?L\/N/ig, family_name).replace(/\(F\/N\)|F\/N/ig, family_name); }); } } // replace text only when page finished loading if (document.readyState === 'complete') replaceYN(); else window.addEventListener('load', () => replaceYN()); // helper function to determine whether a color (the background in use) is light or dark // https://awik.io/determine-color-bright-dark-using-javascript/ function lightOrDark(color) { // Variables for red, green, blue values var r, g, b, hsp; // Check the format of the color, HEX or RGB? if (color.match(/^rgb/)) { // If RGB --> store the red, green, blue values in separate variables color = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/); r = color[1]; g = color[2]; b = color[3]; } else { // If hex --> Convert it to RGB: http://gist.github.com/983661 color = +("0x" + color.slice(1).replace(color.length < 5 && /./g, '$&$&')); r = color >> 16; g = color >> 8 & 255; b = color & 255; } // HSP (Highly Sensitive Poo) equation from http://alienryderflex.com/hsp.html hsp = Math.sqrt( 0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b) ); // Using the HSP value, determine whether the color is light or dark if (hsp>127.5) { return 'light'; } else { return 'dark'; } }