how long ago

replaces all dates with the time from that date

当前为 2024-04-06 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name how long ago
  3. // @version 0.3
  4. // @description replaces all dates with the time from that date
  5. // @run-at document-start
  6. // @author You
  7. // @license GPLv3
  8. // @match *://*/*
  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. // @grant none
  11. // @namespace https://greasyfork.org/users/1184528
  12. // ==/UserScript==
  13. const a = loadlib("allfuncs")
  14. const newelem = loadlib("newelem")
  15. a(function (elem) {
  16. if (elem.title && !elem.title.includes("\u202e\u202d")) {
  17. let x = elem.title && getdate(elem.title)
  18. if (x) elem.title = elem.title.replace(x.string, getstr(x))
  19. }
  20. if (elem.tagName.toLowerCase() == "relative-time") {
  21. if (!elem.shadowRoot || elem.shadowRoot.innerHTML.includes("\u202e\u202d"))
  22. return
  23. elem = elem.shadowRoot
  24. let x = getdate(elem.innerHTML)
  25. if (!x) return
  26. replaceall(
  27. new RegExp(regescape(x.string)),
  28. (e) =>
  29. newelem("timediff", {
  30. innerHTML: getstr(x),
  31. }),
  32. elem,
  33. ["script", "style", "timediff", "input", "textarea"]
  34. )
  35. return
  36. }
  37.  
  38. if (!elem.innerHTML.includes("\u202e\u202d")) {
  39. let x = getdate(elem.innerHTML)
  40. if (!x) return
  41. replaceall(
  42. new RegExp(regescape(x.string)),
  43. (e) =>
  44. newelem("timediff", {
  45. innerHTML: getstr(x),
  46. }),
  47. elem,
  48. ["script", "style", "timediff", "input", "textarea"]
  49. )
  50. }
  51. function getstr(x) {
  52. return `[${howlongago(
  53. x.ms,
  54. -3
  55. )} ${howlongago(x.ms, -3) == "today" ? "" : x.isago ? "ago" : "until"} ${x.string}\u202e\u202d]`
  56. }
  57. }).runonallelems()
  58. function regescape(reg) {
  59. return reg.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&")
  60. }
  61. function replaceall(regex, getelem, node = document.body, ignores = []) {
  62. var search, newelement, splitnode, splittext, i, childnode
  63. if (node.nodeType == 3) {
  64. search = node.data.search(regex)
  65. if (search >= 0) {
  66. splitnode = node.splitText(search)
  67. splittext = splitnode.splitText(RegExp.lastMatch.length)
  68. newelement = getelem(splitnode.data)
  69. if (!ignores.includes(newelement.tagName.toLowerCase()))
  70. ignores.push(newelement.tagName.toLowerCase())
  71. splitnode.innerHTML = splitnode.textContent = ""
  72. newelement.appendChild(splitnode)
  73. splittext.parentNode.insertBefore(newelement, splittext)
  74. }
  75. } else if (
  76. node.nodeType == 11 ||
  77. (node.tagName && !ignores.includes(node.tagName.toLowerCase()))
  78. )
  79. for (i = 0; (childnode = node.childNodes[i]); ++i)
  80. replaceall(regex, getelem, childnode, ignores)
  81. }
  82.  
  83. function howlongago(ms, remove = 0) {
  84. remove--
  85. var time = ["year", "day", "hour", "minute", "second", "milisecond"]
  86. var x = Object.values(a(ms).fromms().val)
  87. x = x.slice(0, remove)
  88. if (x.find((e) => e !== 0)) {
  89. time.splice(0, x.indexOf(x.find((e) => e !== 0)))
  90. x.splice(0, x.indexOf(x.find((e) => e !== 0)))
  91. return x.map((e, i) => `${e} ${time[i]}${e == 1 ? "" : "s"}`).join(" ")
  92. }
  93. window.x = [...x]
  94. return (
  95. //`0 ${time[x.length - 1]}s` ||
  96. "today"
  97. )
  98. }
  99. function getdate(date) {
  100. const tonum = {
  101. january: 1,
  102. february: 2,
  103. march: 3,
  104. april: 4,
  105. may: 5,
  106. june: 6,
  107. july: 7,
  108. august: 8,
  109. september: 9,
  110. october: 10,
  111. november: 11,
  112. december: 12,
  113. jan: 1,
  114. feb: 2,
  115. mar: 3,
  116. apr: 4,
  117. jun: 6,
  118. jul: 7,
  119. aug: 8,
  120. sep: 9,
  121. oct: 10,
  122. nov: 11,
  123. dec: 12,
  124. }
  125.  
  126. function f(reg) {
  127. reg = String(reg).replaceAll(/^\/|\/[gimsueyx]*$/g, "")
  128. ;[
  129. ["d2", "\\d{2}(?:rd|th|nd|st)?"],
  130. ["d4", "\\d{4}(?:rd|th|nd|st)?"],
  131. ["d12", "\\d{1,2}(?:rd|th|nd|st)?"],
  132. [
  133. "monthname",
  134. "(?:jan(?:uary)?|feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|may|june?|july?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)",
  135. ],
  136. ["space", "[^a-z0-9.]"],
  137. ["start", "(?<![\\d\\w/])"],
  138. ["end", "(?![\\d\\w])"],
  139. ].forEach(([a, s]) => {
  140. reg = reg.replaceAll(a, s)
  141. })
  142. return new RegExp(reg, "i")
  143. }
  144.  
  145. function d({ day, month, year, string }) {
  146. day = Number(day.match(/\d+/)[0])
  147. month = tonum[month?.toLowerCase?.()] || Number(month)
  148. if (!month) return
  149. if (day > 31) return
  150. year = Number(
  151. year.length == 2
  152. ? String(new Date().getFullYear()).substring(0, 2) + year
  153. : year
  154. )
  155. var today = new Date()
  156. today.setHours(0, 0, 0, 0)
  157. var ms = today - new Date(year, month - 1, day)
  158. return {
  159. day,
  160. month,
  161. year,
  162. string,
  163. ms: Math.abs(ms),
  164. isago: ms > 0,
  165. }
  166. }
  167. var temp
  168. if ((temp = date.match(f(/start(d12)([\/\-])(d12)\2(d4|d2)end/))))
  169. return d({
  170. day: temp[3],
  171. month: temp[1],
  172. year: temp[4],
  173. string: temp[0],
  174. })
  175.  
  176. if ((temp = date.match(f(/start(d4)([\/\-])(d12)\2(d12)end/))))
  177. return d({
  178. day: temp[4],
  179. month: temp[3],
  180. year: temp[1],
  181. string: temp[0],
  182. })
  183.  
  184. if ((temp = date.match(f(/start(monthname)space*(d12)space+(d4)end/))))
  185. return d({
  186. day: temp[2],
  187. month: temp[1],
  188. year: temp[3],
  189. string: temp[0],
  190. })
  191.  
  192. if ((temp = date.match(f(/start(monthname)(d12)(d4)end/))))
  193. return d({
  194. day: temp[2],
  195. month: temp[1],
  196. year: temp[3],
  197. string: temp[0],
  198. })
  199.  
  200. if ((temp = date.match(f(/start(d12)(monthname)(d4)end/))))
  201. return d({
  202. day: temp[1],
  203. month: temp[2],
  204. year: temp[3],
  205. string: temp[0],
  206. })
  207.  
  208. if ((temp = date.match(f(/start(d4)(monthname)(d12)end/))))
  209. return d({
  210. day: temp[3],
  211. month: temp[2],
  212. year: temp[1],
  213. string: temp[0],
  214. })
  215.  
  216. if ((temp = date.match(f(/start(d12)space*(monthname)space*(d4)end/))))
  217. return d({
  218. day: temp[1],
  219. month: temp[2],
  220. year: temp[3],
  221. string: temp[0],
  222. })
  223. if ((temp = date.match(f(/start(d4)space*(monthname)space*(d12)end/))))
  224. return d({
  225. day: temp[3],
  226. month: temp[2],
  227. year: temp[1],
  228. string: temp[0],
  229. })
  230. if ((temp = date.match(f(/start(monthname)space*(d12)end/))))
  231. return d({
  232. day: temp[2],
  233. month: temp[1],
  234. year: new Date().getFullYear(),
  235. string: temp[0],
  236. })
  237. }