lib:textjack

[1 day ago 3/5/2025‮‭], 7:16:43 PM

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

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