Work Text:
What this is
This is a script that you, as a reader, can use in your browser to replace names (or any other words) in the stories you read. It's main use would be to put your desired name into Y/N self-insert stories, but there are other usages as well: Maybe an author makes a brutal misspelling, maybe you don't like the way your favourite character's name is translated in English, maybe you're simply a bit curious about a "what if" situation... I don't judge! It's your browser, you can do whatever you want - and I'll help you do so :3
How to install this
You will need to install a "userscript manager". This is a browser extension that will allow you to run your own code on any website (and only inside your browser, so nobody except you sees what you do).
You can search the web for "[your browser] userscripts". Or you could simply go with TamperMonkey, an extension that has been around for a long while. There should nowadays even be apps for smartphones!
Then, you will need to add the script itself. This depends on your chosen extension or app, but most should allow you to copypaste code. Or you could try clicking this link and see if it triggers an install prompt!
Now, after you reload the page, you should see two more buttons in the top menu of each work. These two buttons will allow you to add new search&replace entries, and delete all saved entries. It's very basic, but it does work automatically and remembers your choices! Keep in mind that you need to enter the exact spelling, and it searches for full words only - so if you're replacing "bark" with "woof", it's going to leave alone the word "barkeeper" (and not making him a "woofeeper").
The Code
This is the code if you need to copypaste it or just want to have a look. It's not beautiful, but it's functional.
// ==UserScript==
// @name AO3 Search and Replace
// @namespace https://feind.xyz
// @version 2024-04-07
// @description allows you to search & replace text in AO3 works
// @author feind
// @match https://archiveofourown.org/works/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=archiveofourown.org
// @grant none
// ==/UserScript==
(function() {
const findAndReplaceText = (element, searchTerm, replacementText) => {
const escapedSearchTerm = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
const searchRegex = new RegExp(`\\b${escapedSearchTerm}\\b`, 'gi')
function processNode(node) {
if (node.nodeType === Node.TEXT_NODE) {
const matches = node.nodeValue.match(searchRegex)
if (matches) {
const newContent = node.nodeValue.replace(searchRegex, replacementText)
node.nodeValue = newContent
}
} else if (node.nodeType === Node.ELEMENT_NODE) {
node.childNodes.forEach(processNode)
}
}
processNode(element)
}
const workskinElement = document.getElementById('workskin')
let replacements = localStorage.getItem('replacements') ? JSON.parse(localStorage.getItem('replacements')) : []
replacements.forEach((replacement) => {
findAndReplaceText(workskinElement, replacement.s, replacement.r)
})
const topMenu = document.querySelector('.work.navigation.actions')
const addEntryButton = document.createElement('li')
addEntryButton.innerHTML = '<a href="#">Add Search & Replace Entry</a>'
topMenu.appendChild(addEntryButton)
const clearEntriesButton = document.createElement('li')
clearEntriesButton.innerHTML = `<a href="#">Clear Search & Replace Entries (${replacements.length})</a>`
topMenu.appendChild(clearEntriesButton)
addEntryButton.addEventListener('click', (event) => {
event.preventDefault()
event.stopPropagation()
const searchTerm = prompt('Search term:')
const replacementText = prompt('Replacement text:')
replacements.push({ s: searchTerm, r: replacementText })
localStorage.setItem('replacements', JSON.stringify(replacements))
findAndReplaceText(workskinElement, searchTerm, replacementText)
clearEntriesButton.innerHTML = `<a href="#">Clear Search & Replace Entries (${replacements.length})</a>`
alert('Replacement added!')
})
clearEntriesButton.addEventListener('click', (event) => {
event.preventDefault()
event.stopPropagation()
localStorage.removeItem('replacements')
replacements = []
clearEntriesButton.innerHTML = `<a href="#">Clear Search & Replace Entries (${replacements.length})</a>`
alert('Replacements cleared! Please reload the page.')
})
})()
