lib:textjack

3/5/2025, 7:16:43 PM

当前为 2025-03-07 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name lib:textjack
  3. // @version 3
  4. // @match *://*/*
  5. // @run-at document-start
  6. // @author rssaromeo
  7. // @license GPLv3
  8. // @include *
  9. // @grant none
  10. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAHJQTFRFAAAAEIijAo2yAI60BYyuF4WaFIifAY6zBI2wB4usGIaZEYigIoiZCIyrE4igG4iYD4mjEomhFoedCoqpDIqnDomlBYyvE4efEYmiDYqlA42xBoytD4mkCYqqGYSUFYidC4qoC4upAo6yCoupDYqmCYur4zowOQAAACZ0Uk5TAO////9vr////1+/D/+/L+/Pf/////+f3///////H4////////+5G91rAAACgUlEQVR4nM2Y22KjIBCGidg1264liZqDadK03X3/V2wNKHMC7MpF/xthHD5mgERAqZhWhfYqH6K+Qf2qNNf625hCoFj9/gblMUi5q5jLkXLCKudgyiRm0FMK82cWJp1fLbV5VmvJbCIc0GCYaFqqlDJgADdBjncqAXYobm1xh72aFMflbysteFfdy2Yi1XGOm5HGBzQ1dq7TzEoxjeNTjQZb7VA3e1c7+ImgasAgQ9+xusNVNZIo5xmOMgihIS2PbCQIiHEUdTvhxCcS/kPomfFI2zHy2PkWmA6aNatIJpKFJyekyy02xh5Y3DI9T4aOT6VhIUrsNTFp1pf79Z4SIIVDegl6IJO6cHiL/GimIZDhgTu/BlYWCQzHMl0zBWT/T3KAhtxOuUB9FtBrpsz0RV4xsjHmW+UCaffcSy/5viMGer0/6HdFNMZBq/vjJL38H9Dqx4Fuy0Em12DbZy+9pGtiDijbglwAehyj11n0tRD3WUBm+lwulE/8h4BuA+iWAQQnteg2Xm63WQLTpnMnpjdge0Mgu/GRPsV4xdjQ94Lfi624fabhDkfUqIKNrM64Q837v8yL0prasepCgrtvw1sJpoqanGEX7b5mQboNW8eawXaWXTMfMGxub472hzWzHSn6Sg2G9+6TAyRruE71s+zAzjWaknoyJCQzwxrghH2k5FDT4eqWunuNxyN9QCGcxVod5oADbYnIUkDTGZEf1xDJnSFteQ3KdsT8zYDMQXcHxsevcLH1TrsABzkNPyA/L7b0jg704viMMlpQI96WsHknCt/3YH0kOEo9zcGkwrFK39ck72rmoehmKqo2RKlilzSy/nJKEV45CT38myJp456fezktHjN5aeMAAAAASUVORK5CYII=
  11. // @description 3/5/2025, 7:16:43 PM
  12. // @namespace https://greasyfork.org/users/1184528
  13. // ==/UserScript==
  14.  
  15. let obslist = []
  16. var textJackList = []
  17. Object.assign(window, console)
  18. const a = loadlib("newallfuncs")
  19.  
  20. function replaceText(text) {
  21. var oldtext = text
  22. for (var cb of textJackList) {
  23. text = cb(text)
  24. if (text !== oldtext) {
  25. return (text = replaceText(text))
  26. }
  27. }
  28. return text
  29. }
  30. // Function to handle text changes
  31. function handleTextChange(mutations) {
  32. disableObservers()
  33. mutations.forEach((mutation) => {
  34. if (mutation.type === "childList") {
  35. mutation.addedNodes.forEach((node) => {
  36. if (node.nodeType === Node.TEXT_NODE) {
  37. // Filter text for text nodes
  38. node.textContent = replaceText(node.textContent)
  39. } else if (node.nodeType === Node.ELEMENT_NODE) {
  40. // If it's an element, check its text content
  41. node.childNodes.forEach((child) => {
  42. if (child.nodeType === Node.TEXT_NODE) {
  43. child.textContent = replaceText(child.textContent)
  44. }
  45. })
  46. // Observe any shadow roots
  47. if (node.shadowRoot) {
  48. createObserver(node.shadowRoot)
  49. }
  50. }
  51. })
  52. } else if (mutation.type === "characterData") {
  53. // Filter text for character data changes
  54. mutation.target.textContent = replaceText(
  55. mutation.target.textContent
  56. )
  57. }
  58. })
  59. enableObservers()
  60. }
  61.  
  62. // Create a MutationObserver for the main document
  63. function createObserver(elem) {
  64. var obs = new MutationObserver((mutations) => {
  65. handleTextChange(mutations)
  66. mutations.forEach((mutation) => {
  67. mutation.addedNodes.forEach((node) => {
  68. // If the added node is a shadow host, observe its shadow root
  69. if (node.nodeType === Node.ELEMENT_NODE && node.shadowRoot) {
  70. createObserver(node.shadowRoot)
  71. }
  72. })
  73. })
  74. })
  75.  
  76. // Start observing the document body
  77. obslist.push([
  78. obs,
  79. elem,
  80. {
  81. childList: true,
  82. subtree: true,
  83. characterData: true,
  84. },
  85. ])
  86. }
  87. // Function to enable all observers
  88. function enableObservers() {
  89. try {
  90. disableObservers()
  91. } catch (e) {}
  92. // warn(obslist, 1)
  93. obslist.forEach(([observer, target, opts]) =>
  94. observer.observe(target, opts)
  95. )
  96. }
  97.  
  98. // Function to disable all observers
  99. function disableObservers() {
  100. // warn(obslist, 0)
  101. obslist.forEach(([observer]) => observer.disconnect())
  102. }
  103.  
  104. // Optionally, filter existing text content on page load
  105. function filterExistingText(node) {
  106. disableObservers()
  107. if (node.nodeType === Node.TEXT_NODE) {
  108. node.textContent = replaceText(node.textContent)
  109. } else if (node.nodeType === Node.ELEMENT_NODE) {
  110. node.childNodes.forEach(filterExistingText)
  111. // If the element has a shadow root, filter its content
  112. if (node.shadowRoot) {
  113. filterExistingText(node.shadowRoot)
  114. }
  115. }
  116. enableObservers()
  117. }
  118.  
  119. // Filter existing text in the document
  120. var waitingForBody = false
  121. if (document.body) {
  122. setup()
  123. } else {
  124. waitingForBody = true
  125. }
  126.  
  127. loadlib("libloader").savelib("textjack", function newTextJack(cb) {
  128. textJackList.push(cb)
  129. if (document.body) {
  130. setup()
  131. } else {
  132. waitingForBody = true
  133. }
  134. })
  135. a.bodyload().then(() => {
  136. if (waitingForBody) {
  137. setup()
  138. }
  139. })
  140.  
  141. function setup() {
  142. filterExistingText(document.body)
  143. createObserver(document.body)
  144. enableObservers()
  145. }