Word Switcher for AO3 (site-wide; user-settable)

Switches the a select word with a preferred word site-wide, across all AO3 works. User-settable.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Word Switcher for AO3 (site-wide; user-settable)
// @namespace    github.com/forceofcalm
// @version      0.1
// @description  Switches the a select word with a preferred word site-wide, across all AO3 works. User-settable.
// @author       calm
// @match        https://archiveofourown.org/works/*
// @icon         [later]
// @grant        none
// @license      MIT
// ==/UserScript==

// ADD YOUR WORD PREFERENCES HERE
// format: ['word to be replaced', 'preferred word'],
// the quotes and comma are important!
// also these are examples, you can replace them with whatever you want
const words = [
  ['oi', 'hey'],
  ['gray', 'grey'],
  ['roommates', 'flatmates'],
  ['one', 'two'],
];

(() => {
  const workText = document.querySelector('#workskin');

  words.forEach(([oldWord, newWord]) => {
      const regex = new RegExp(String.raw`\b${oldWord}\b`, 'gu');
      const regexCapitalized = new RegExp(String.raw`\b${oldWord[0].toUpperCase() + oldWord.toLowerCase().slice(1)}\b`, 'gu');
      const regexLower = new RegExp(String.raw`\b${oldWord}\b`, 'gu');
      const regexUpper = new RegExp(String.raw`\b${oldWord}\b`, 'gu');
      const regexIgnoreCase = new RegExp(String.raw`\b${oldWord}\b`, 'gui');

      const oldWordTest = regexIgnoreCase.test(workText.textContent);
      const newWordTest = regexIgnoreCase.test(workText.textContent);

      const hasBothWords = oldWordTest && newWordTest;

      // check that work only has one of the words
      if (hasBothWords) {
        alert(`Word Switcher: Work contains both ${oldWord} and ${newWord}. Please edit the work manually.`);
        return;
      }

      // work is already in preferred word
      if (newWordTest) {
        return;
      }

      function replaceWord(node, oldWord, newWord) {
        if (node.nodeType === Node.TEXT_NODE) {
            node.textContent = node.textContent.replace(oldWord, newWord);
        } else if (node.hasChildNodes()) {
            node.childNodes.forEach(childNode => {
              replaceWord(childNode, oldWord, newWord);
            });
        }
      }

      // normally cased word
      replaceWord(workText, regex, newWord);
      // capitalized word
      replaceWord(workText, regexCapitalized, newWord[0].toUpperCase() + newWord.slice(1).toLowerCase());
      // lowercased word
      replaceWord(workText, regexLower, newWord.toLowerCase());
      // uppercased word
      replaceWord(workText, regexUpper, newWord.toUpperCase());
    });
})();