owowify website evewywhewe! >w<
当前为
// ==UserScript==
// @name owowify website
// @description owowify website evewywhewe! >w<
// @author owowed
// @version 0.0.2
// @namespace fun.owowed.moe
// @license GPL-3.0-or-later
// @match *://*/*
// @grant none
// @run-at document-end
// @copyright All rights reserved. Licensed under GPL-3.0-or-later. View license at https://spdx.org/licenses/GPL-3.0-or-later.html
// ==/UserScript==
/**
* [author note]
*
* honestly, i dont know what the fuck is going on here
*
* this is one of my old personal userscript collection
*
* i made this back when i began learning javascript and
* userscript stuff, and also when i dont know any better
* and start writing random stuff, like this
*
* so yeah, expect some really bad poopy programmer code here
*
* anyway, this userscript uses subtree mutation observer,
* sooo that may degrade your browsing performance, beware
*
* also, good luck when you want to fork it lol
*
* ps: maybe sooner or later, ill clean this stuff up,
* and rework some of the bits and stuff later
*
* ~~ owowed
*/
/**
* wincesed undew GNYU! GPL, vewsion 3.0 -w-
*/
const textNodeParentElementBlacklistSelector = "style, script, svg, noscript, iframe, object, code, pre, input";
let lastWindowHref = window.location.href;
let idleTimeout = 0;
{
initObserver(document.body, {childList: true, subtree: true});
owowifyElement(document.body);
setInterval(() => {
if (idleTimeout > 15) {
if (lastWindowHref != window.location.href) {
idleTimeout = 0;
lastWindowHref = window.location.href;
}
else {
return;
}
}
owowifyElement(document.body);
idleTimeout++;
}, 1000);
document.title = owowify(document.title);
}
function initObserver(node, options = {}) {
const observer = new MutationObserver(records => {
for (const mut of records) {
if (mut.addedNodes.length > 0) {
for (const nd of mut.addedNodes) {
owowifyElement(nd);
idleTimeout = 12;
}
}
}
});
observer.observe(node, {...options});
}
/** @param {Element} element */
function owowifyElement(element) {
if (element.nodeType != Node.ELEMENT_NODE) return;
const currentElementValid =
(isElementValid(element) && isElementValid(element.parentElement))
|| (element instanceof HTMLAnchorElement && !element.textContent.includes(element.href));
if (!currentElementValid) {
element.noOwowify = true;
}
if (element.hasAttribute("title")) {
element.setAttribute("title", owowify(element.getAttribute("title")));
}
for (const nd of element.childNodes) {
if (nd.nodeType == Node.ELEMENT_NODE) {
owowifyElement(nd);
}
if (nd.nodeType == Node.TEXT_NODE && currentElementValid) {
owowifyNode(nd);
}
}
if (element instanceof HTMLInputElement) {
if (element.readOnly && !["password", "url", "hidden"].includes(element.type)) {
element.value = owowify(element.value);
element.placeholder = owowify(element.placeholder);
}
}
}
/** @param {Node} node */
function owowifyNode(node) {
if (node.nodeType == Node.TEXT_NODE) {
node.nodeValue = owowify(node.nodeValue);
}
}
function isElementValid(element) {
if (element == null) return null;
return !(element.matches(textNodeParentElementBlacklistSelector)
|| element.noOwowify
|| element.classList?.contains?.("-owo-no-owowify")
|| element.isContentEditable);
}
/**
*
* @param {String} textstr
* @param {OwowifyOptions} options
* @returns {String}
*/
function owowify(textstr, options) {
const endSentencePattern = String.raw`([\w ,.!?]+)?`; // endSentencePattern
const endSentencePattern1 = String.raw`([\w ,.?]+)?`; // endSentencePattern without "!" sign
const endSentencePattern2 = String.raw`([\w ,.]+)?`; // endSentencePattern without "!" and "?" sign
const vowel = "[aiueo]";
const vowelNoE = "[aiuo]"; // vowel without e
const vowelNoIE = "[auo]"; // vowel without i and e
const zackqyWord = "[jzckq]";
let result = Array.isArray(textstr) ? textstr.join(" ") : textstr;
// OWO EMOTE
// result = subOwoEmote(result, reg`/(stop\!+)${endSentencePattern1}/gi`, " -M-");
result = subOwoEmote(result, reg`/(i(?:'|)m(?:\s+|\s+so+\s+)bored)${endSentencePattern}/gi`, " -w-")
result = subOwoEmote(result, reg`/(love\s+(?:you|him|her|them))${endSentencePattern}/gi`, " uwu");
result = subOwoEmote(result, reg`/(i\s+don(?:'|)t\s+care|i\s*d\s*c)${endSentencePattern}/gi`, " 0w0");
// result = subOwoEmote(result, reg`/(i(?:'|)m\s+scared)${endSentencePattern}/gi`, " ;w;");
// WORD REPLACEMENT
result = result.replace(reg`/l${vowel}ve?/gi`, g0 => subSameCase(g0, "luv"));
// MAIN TRANSLATION
result = result.replace(/r/gi, g0 => subSameCase(g0, "w"));
// result = result.replace(reg`/(?<=(?<!w)(?<!${vowel}+)${vowel}+)l(?!l+\s+|l+$)|l(?=${vowel}+(?!${vowel}+)(?!w))/gi`, g0 => subSameCase(g0, "w")); // nope
result = result.replace(reg`/(?<=(?<!w${vowel}+)${vowel}+)l(?!l+)/gi`, g0 => subSameCase(g0, "w"));
result = result.replace(reg`/n(${vowelNoE}+)/gi`, (g0, g1) => subSameCase(g0 + g1, `ny${g1}`));
result = result.replace(reg`/m(${vowelNoIE}+)(?!w*${zackqyWord})/gi`, (g0, g1) => subSameCase(g0 + g1, `my${g1}`));
result = result.replace(reg`/p(${vowelNoIE}+)(?!w*${zackqyWord})/gi`, (g0, g1) => subSameCase(g0 + g1, `pw${g1}`));
return result;
}
/**
* @param {string} all
* @param {RegExp} pattern
* @param {string} emote
*/
function subOwoEmote(all, pattern, emote) {
const matchEndSpace = /^\s+$/g;
return all.replace(pattern, (gp0, gp1, gp2) => {
return gp2 == undefined || matchEndSpace.test(gp2)
? gp1 + emote
: gp0;
});
}
/**
* @param {string} strA
* @param {string} strB
*/
function subSameCase(strA, strB) {
let result = "";
for (let i = 0; i < strB.length; i++) {
if (strA[i] != undefined && strB[i] != undefined) {
if (strA[i].toUpperCase() == strA[i]) {
result += strB[i].toUpperCase();
}
else if (strA[i].toLowerCase() == strA[i]) {
result += strB[i].toLowerCase();
}
else {
result += strB[i];
}
}
else {
result += strB[i];
}
}
return result;
}
/** @param {[string[], ...any[]]} templateArgs */
function reg(...templateArgs) {
const rawString = String.raw(...templateArgs);
const pattern = rawString.substring(1, rawString.lastIndexOf("/"));
const flags = rawString.substring(rawString.lastIndexOf("/")+1, rawString.length);
return new RegExp(pattern, flags);
}
// mdn docs
/** @param {string} str */
function regexEscape(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}