Word & Text Replace

replaces text with other text.

目前为 2019-09-26 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Word & Text Replace
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.3.1
  5. // @description replaces text with other text.
  6. // @author listfilterErick
  7. // @grant none
  8.  
  9. // @match *://*/*
  10.  
  11. // @require http://code.jquery.com/jquery-1.12.4.min.js
  12. // @require https://greasyfork.org/scripts/5392-waitforkeyelements/code/WaitForKeyElements.js?version=115012
  13.  
  14. // @licence CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/
  15. // @licence GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
  16. // ==/UserScript==
  17. /*jshint esversion: 6*/
  18.  
  19. /*
  20. Update Log 1.3.1
  21. - new options:
  22. -- logMatches, logChangedText
  23. -- dontMarkDivs, checkHyperlinkElements
  24. - cleanup: changed variable names, cleaned up function code.
  25.  
  26. * Text nodes are trimmed before checking but changed text is not trimmed unless specified in the regex.
  27. */
  28.  
  29. (function () {
  30.  
  31. let replaceRules = [];
  32. /*
  33. regex reference
  34. \b: word boundry
  35. \W: any non-alpha character
  36. */
  37. if (1) {
  38. replaceRules.push(
  39. // basic examples:
  40. //[/(.\W?)*/i, 'words'], //replace all text instances with "words".
  41. //[/\w/gi, 'a'], //replace all characters with an "a" character.
  42. //[/match/gi, 'a'], //matches "match" in "ABmarchCD" and "red match".
  43. //[/\bmatch\b/gi, 'a'], //does not match "ABmatchesCD" but does match "this match is red".
  44. //[/scripts/gi, 'dictionaries'],
  45. //[/script/gi, 'dictionary'],
  46. //[/(web)?site/gi, 'webzone'],
  47. );
  48. // separated just for an example of an option of grouping/sorting.
  49. replaceRules.push(
  50. //[/user/gi, 'individual'],
  51. //[/\buse\b/gi, 'utilize'],
  52. );
  53. }
  54. /*
  55. #### note on moving rules to a seperate userscript ####
  56. https://wiki.greasespot.net/UnsafeWindow
  57. unsafeWindow.replaceRules = replaceRules; //set rules(page scope) to rules(script scope)
  58. replaceRules = unsafeWindow.replaceRules; //set rules(script scope) to rules(page scope)
  59. */
  60.  
  61. const showReplaceButton = 0; // set to 1 to show a button to manually run this script.
  62. const buttonTransparency = .2; // set to a value between 0 and 1, 1 is no transparency, .5 is 50% transparency.
  63. const dynamicChecking = 1; // set to 1 to run the script automatically when new image elements are detected.
  64.  
  65. const showLogMessages = 0; // set to 1 to log script messages, overrides the following log options.
  66. const logMatches = 1; // set to 1 to log matches to the console.
  67. const logChangedText = 0; // set to 1 to log changed text to the console.
  68. const logRuntimes = 1; // set to 1 to log function runtimes to the console.
  69.  
  70. const dontMarkDivs = 1; // set to 1 to not mark divs as checked, solves some site issues.
  71. // setting to 1 would make dynamic checks recheck checked divs.
  72.  
  73. function consolelog(text, showOption) {
  74. if (showLogMessages && showOption) {
  75. console.log(text);
  76. }
  77. }
  78.  
  79. let titleChecked = 0;
  80. let nodeCounter = 1;
  81. let aCounter = 1;
  82.  
  83. // ==== replaceText() =========================================================================|
  84. function replaceText() {
  85.  
  86. if (logRuntimes) {
  87. var startTime = performance.now();
  88. }
  89.  
  90. let numTerms = replaceRules.length;
  91. let ruleMatched = 0;
  92.  
  93. // ==== title element =====================================================================|
  94. let titleText = jQuery("title").text();
  95. if (titleText && !titleChecked) {
  96. for (let index = 0; index < numTerms; index++) {
  97. if (replaceRules[index][0].test(titleText)) {
  98. consolelog("(title match): "+ titleText +" | "+ replaceRules[index][0], logMatches);
  99. titleText = titleText.replace(replaceRules[index][0], replaceRules[index][1]);
  100. jQuery("title").text(titleText);
  101. }
  102. }
  103. titleChecked = 1;
  104. }
  105.  
  106. // ==== text elements =====================================================================|
  107. let textWalker = document.createTreeWalker(
  108. document.body,
  109. NodeFilter.SHOW_TEXT,
  110. {
  111. acceptNode: function (node) {
  112. if (node.nodeValue.trim() &&
  113. !/CODE|SCRIPT|STYLE/.test(node.parentNode.nodeName) && // exclude scripts and style elements
  114. !/wr-checked/.test(node.parentNode.classList)) { // exclude checked elements
  115. return NodeFilter.FILTER_ACCEPT;
  116. }
  117. return NodeFilter.FILTER_SKIP;
  118. }
  119. },
  120. false
  121. );
  122. let textNode = textWalker.nextNode();
  123. while (textNode) {
  124. let currentText = textNode.nodeValue;
  125. let parentNode = textNode.parentNode;
  126. if (!dontMarkDivs || parentNode.nodeName != "DIV") { //supposedly adding a class to a div broke a site somehow.
  127. parentNode.classList.add("wr-checked");
  128. }
  129. for (let index = 0; index < numTerms; index++) {
  130. if (replaceRules[index][0].test(currentText.trim())) {// ## checks the trimmed text.
  131. ruleMatched = 1;
  132. consolelog(nodeCounter +" (text match): "+ currentText +" | "+ replaceRules[index][0], logMatches);
  133. currentText = currentText.replace(replaceRules[index][0], replaceRules[index][1]);
  134. }
  135. }
  136. if (ruleMatched) {
  137. ruleMatched = 0;
  138. textNode.nodeValue = currentText;
  139. consolelog(nodeCounter +" (text): "+ currentText.trim(), logChangedText);
  140. nodeCounter++;
  141. }
  142. textNode = textWalker.nextNode();
  143. }
  144.  
  145. if (logRuntimes) {
  146. const endTime = performance.now();
  147. const runTime = ((endTime - startTime) / 1000).toFixed(2);
  148. if (runTime > 1) {
  149. consolelog('(WR) finished after ' + runTime + ' seconds.', 1);
  150. }else {
  151. consolelog('(WR) finished in less than 1 second.', 1);
  152. }
  153. }
  154.  
  155. } //end function replaceText()
  156.  
  157. replaceText();
  158. if (dynamicChecking) {
  159. jQuery(document).ready(waitForKeyElements("img", replaceText));
  160. //jQuery(window).on("load", function() { //after all initial images are loaded.
  161. //waitForKeyElements("img", replaceText);
  162. //});
  163. }
  164.  
  165. if (showReplaceButton) {
  166. if (!jQuery("#wt-buttons").length) {
  167. consolelog("(WR) created #wt-buttons.");
  168. jQuery("body").prepend("<div id='wt-buttons'><div id='wr-reset'>WR</div><div id='wt-close'>&times;</div></div>");
  169. jQuery("#wt-close").click(function () { jQuery("#wt-buttons").remove(); });
  170.  
  171. const webToolsCss =
  172. `<style type="text/css">
  173. #wt-buttons {
  174. width: 50px;
  175. display: block;
  176. opacity: `+ buttonTransparency + `;
  177. position: fixed;
  178. top: 0px;
  179. right: 0px;
  180. z-index: 999;
  181. }
  182. #wt-buttons:hover {
  183. opacity: 1;
  184. }
  185. #wt-buttons div {
  186. display: block !important;
  187. padding: 5px;
  188. border-radius: 5px;
  189. margin-top: 2px;
  190. font-size: initial !important;
  191. font-weight: bold;
  192. color: white;
  193. cursor: pointer;
  194. }
  195. #wt-close {
  196. background: #777777;
  197. text-align: center;
  198. }
  199. </style>`;
  200.  
  201. jQuery(document.body).append(webToolsCss);
  202. } else {
  203. jQuery("#wt-buttons").prepend("<div id='wr-reset'>WR</div>");
  204. }
  205. jQuery("#wr-reset").click(replaceText);
  206.  
  207. const wordReplaceCss =
  208. `<style type="text/css">
  209. #wr-reset {
  210. background: #ffb51b;
  211. }
  212. </style>`;
  213.  
  214. jQuery(document.body).append(wordReplaceCss);
  215. } // end if (showReplaceButton)
  216. })();