您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
owowify website evewywhewe! >w<
// ==UserScript== // @name owowify website // @description owowify website evewywhewe! >w< // @author owowed // @version 0.0.3 // @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== /** * wincesed undew GNYU! GPL vewsion 3.0 -w- */ const blocklistTags = "style, script, svg, noscript, iframe, object, code, pre, input"; !function () { const updateSubtreeOwowification = () => { setTimeout(() => owowifySubtree(document.body), 700); }; const windowHrefCheck = stateCheck( () => window.location.href, () => updateSubtreeOwowification() ); const documentTitleCheck = stateCheck( () => owowify(document.title) ); const observer = new MutationObserver((records) => { if (windowHrefCheck()) return; documentTitleCheck(); for (const record of records) { for (const newNode of record.addedNodes) { owowifySubtree(newNode); } } }); observer.observe(document.body, { childList: true, subtree: true, /* don't use characterData, it'll kill your page */ }); owowifySubtree(document.body); document.title = owowify(document.title); function stateCheck(newValueGetter, callback) { let value = newValueGetter; return () => { const newValue = newValueGetter(); if (value != newValue) { value = newValue; callback?.(); return true; } }; } }(); /** @param {Element} element */ function owowifySubtree(element) { if (element.nodeType != Node.ELEMENT_NODE) return; const currentElementValid = isElementValidOwowify(element) && isElementValidOwowify(element.parentElement); if (!currentElementValid) { element.noOwowify = true; } if (element instanceof HTMLInputElement) { if (element.readOnly && !["password", "url", "hidden"].includes(element.type)) { element.value = owowify(element.value); element.placeholder = owowify(element.placeholder); } } if (element.hasAttribute("title")) { element.setAttribute("title", owowify(element.getAttribute("title"))); } for (const node of element.childNodes) { if (node.nodeType == Node.ELEMENT_NODE) { owowifySubtree(node); } if (node.nodeType == Node.TEXT_NODE && currentElementValid) { owowifyTextNode(node); } } } /** @param {Node} node */ function owowifyTextNode(node) { if (node.nodeType == Node.TEXT_NODE) { node.nodeValue = owowify(node.nodeValue); } } /** @param {Element} element */ function isElementValidOwowify(element) { if (element == null) return null; if (element.noOwowify || element.classList?.contains?.("-owo-no-owowify")) return false; if (element instanceof HTMLInputElement) { return !element.textContent.includes(element.href); } return !(element.matches(blocklistTags) || element.isContentEditable); } /** * @param {String} inputText * @returns {String} */ function owowify(inputText) { 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]"; const result = inputText // OwO emote .replace(reg`/(i(?:'|)m(?:\s+|\s+so+\s+)bored)${endSentencePattern}/gi`, subOwoEmote("-w-")) .replace(reg`/(love\s+(?:you|him|her|them))${endSentencePattern}/gi`, subOwoEmote("uwu")) .replace(reg`/(i\s+don(?:'|)t\s+care|i\s*d\s*c)${endSentencePattern}/gi`, subOwoEmote("0w0")) // world substitution .replace(reg`/l${vowel}ve?/gi`, $0 => subSameCase($0, "luv")) // OwO translation /* replace all "r" to "w", no exception! */ .replace(/r/gi, $0 => subSameCase($0, "w")) /* lame -> wame, goal -> goaw, gallery -> gallewy, lol -> lol, null -> null */ .replace(reg`/(?<!([wl]${vowel}+)|l)l(?!(${vowel}?l+)|.${vowel})/gi`, $0 => subSameCase($0, "w")) /* na -> nya, nu -> nyu, no -> nyo, ne -> nye */ .replace(reg`/n(${vowelNoE}+)/gi`, ($0, $vowel) => subSameCase($0 + $vowel, `ny${$vowel}`)) /* ma -> mya, mu -> myu, mo -> myo */ .replace(reg`/m(${vowelNoIE}+)(?!w*${zackqyWord})/gi`, ($0, $vowel) => subSameCase($0 + $vowel, `my${$vowel}`)) /* pa -> pwa, pu -> pwu, po -> pwo */ .replace(reg`/p(${vowelNoIE}+)(?!w*${zackqyWord})/gi`, ($0, $vowel) => subSameCase($0 + $vowel, `pw${$vowel}`)); return result; } function subOwoEmote(emote) { const matchEndSpace = /^\s+$/g; return ($0, $setenceBeforeEnd, $endSentence) => { if ($endSentence == undefined || matchEndSpace.test($endSentence)) { return `${$setenceBeforeEnd} ${emote}`; } else return $0; } } /** * @param {string} inputText * @param {string} replaceText */ function subSameCase(inputText, replaceText) { let result = ""; for (let i = 0; i < replaceText.length; i++) { if (inputText[i] != undefined && replaceText[i] != undefined) { if (inputText[i].toUpperCase() == inputText[i]) { result += replaceText[i].toUpperCase(); } else if (inputText[i].toLowerCase() == inputText[i]) { result += replaceText[i].toLowerCase(); } else { result += replaceText[i]; } } else { result += replaceText[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 }