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.1
// @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);
// 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,
minWidth: 400,
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/ig, given_name).replace(/G\/N/ig, given_name)
.replace(/(Y\/)?L\/N/ig, family_name).replace(/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'; }
}