Replacer

replace words

目前為 2024-12-13 提交的版本,檢視 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Replacer
// @namespace    http://tampermonkey.net/
// @version      1.0
// @license MIT
// @description  replace words
// @author       Shuraken007
// @include https://*/*
// @include http://*/*
// @grant        GM.getValue
// @grant        GM.setValue
// ==/UserScript==
load_config("https://api.npoint.io/ecef5ef17a23b6bd2222")
addEventListener("load", main)

var replacements = null
var config_data = null
const observer = new MutationObserver(run_mutations);

async function main() {
   'use strict';

   var counter = 0;
   while (!replacements) {
      await new Promise(r => setTimeout(r, 500));
      counter++;
      if (counter > 10) {
         throw new Error("config with replacements not loaded");
      }
   }
   console.log("config loaded!");
   if (replacements.length == 0) {
      console.log("no replacements for this site!");
      return
   }

   observer.observe(document.body, { childList: true, subtree: true });
   replaceText(document.body);

   GM.setValue("replacement_json_config", JSON.stringify(config_data))
};

async function load_config(link) {
   var restored_config = await GM.getValue("replacement_json_config", null)
   if (restored_config) {
      var data = JSON.parse(restored_config);
      build_suited_config(data)
      return
   }
   fetch(link)
      .then(response => response.json())
      .then(json => build_suited_config(json))
      .catch(err => console.log(err));
}

function build_suited_config(data) {
   var cur_url = window.location.href;
   replacements = [];
   for (const [k, v] of Object.entries(data)) {
      url_token = tokenToRegex(k, true)
      url_token = new RegExp(url_token)
      if (!url_token.test(cur_url)) {
         continue
      }

      for (let i = 0; i < v.length; i += 2) {
         regex = tokenToRegex(v[i])
         replacement = tokenToRegex(v[i + 1])

         replacements.push(regex)
         replacements.push(replacement)
      }
   }
   config_data = data
   // console.log(replacements)
}

function run_mutations(mutations) {
   mutations.forEach(mutation => {
      if (mutation.type === "childList") {
         mutation.addedNodes.forEach(node => {
            replaceText(node);
         });
      }
   });
}

function replaceText(node) {
   switch (node.nodeType) {
      case Node.ELEMENT_NODE:
         node.childNodes.forEach(replaceText);
         break;
      case Node.TEXT_NODE: {
         let text = node.textContent;
         if (!text) { break; }
         // console.log(node.nodeType, node.nodeValue)
         new_text = make_replacements(text);
         if (text != new_text) { node.textContent = new_text }
         break;
      }
      case Node.DOCUMENT_NODE:
         node.childNodes.forEach(replaceText);
   }
}

function make_replacements(text) {
   for (let i = 0; i < replacements.length; i += 2) {
      regex = replacements[i]
      replacement = replacements[i + 1]
      text = text.replaceAll(regex, replacement);
   }
   return text
}

// prepareRegex by JoeSimmons
// used to take a string and ready it for use in new RegExp()
function prepareRegex(string) {
   // escape: []^&$.()?/\+{}|
   string = string.replace(/([\[\]\^\&\$\.\(\)\?\/\\\+\{\}\|])/g, '\\$1');
   // '*' -> '[^ ]*', but '\*' -> '*'
   string = string.replace(/\\?\*/g, function (fullMatch) {
      return fullMatch === '\\*' ? '*' : '[^ ]*';
   })
   return string
}

function getRegFromString(string) {
   var a = string.split("/");
   modifiers = a.pop();
   a.shift();
   pattern = a.join("/");
   if (!modifiers.includes('g')) {
      modifiers += 'g'
   }
   // console.log(`pattern: ${pattern}, modifiers: ${modifiers}`)
   return new RegExp(pattern, modifiers);
}

var rIsRegexp = /^\/(.+)\/([gim]+)?$/;
function tokenToRegex(string, is_prepared = false) {
   if (string.match(rIsRegexp)) {
      // console.log(`user_regexp: ${string}`)
      return getRegFromString(string)
   }
   if (is_prepared) {
      string = prepareRegex(string);
      return new RegExp(string);
   }
   return string
}