// ==UserScript==
// @name how long ago
// @version 1
// @description replaces all dates with the time from that date
// @run-at document-start
// @author You
// @license GPLv3
// @exclude /livereload.net\/files\/ffopen\/index.html$/
// @match *://*/*
// @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=
// @grant none
// @namespace https://greasyfork.org/users/1184528
// ==/UserScript==
const a = loadlib("allfuncs")
const newelem = loadlib("newelem")
a(function (elem) {
if (elem.title && !elem.title.includes("\u202e\u202d")) {
let x = elem.title && getdate(elem.title)
if (x) elem.title = elem.title.replace(x.string, getstr(x))
}
if (elem.tagName.toLowerCase() == "relative-time") {
if (!elem.shadowRoot || elem.shadowRoot.innerHTML.includes("\u202e\u202d"))
return
elem = elem.shadowRoot
let x = getdate(elem.innerHTML)
if (!x) return
replaceall(
new RegExp(regescape(x.string)),
(e) =>
newelem("timediff", {
innerHTML: getstr(x),
}),
elem,
["script", "style", "timediff", "input", "textarea"]
)
return
}
if (!elem.innerHTML.includes("\u202e\u202d")) {
let x = getdate(elem.innerHTML)
if (!x) return
replaceall(
new RegExp(regescape(x.string)),
(e) =>
newelem("timediff", {
innerHTML: getstr(x),
}),
elem,
["script", "style", "timediff", "input", "textarea"]
)
}
function getstr(x) {
return `[${howlongago(
x.ms,
-3
)} ${howlongago(x.ms, -3) == "today" ? "" : x.isago ? "ago" : "until"} ${x.string}\u202e\u202d]`
}
}).runonallelems()
function regescape(reg) {
return reg.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&")
}
function replaceall(regex, getelem, node = document.body, ignores = []) {
var search, newelement, splitnode, splittext, i, childnode
if (node.nodeType == 3) {
search = node.data.search(regex)
if (search >= 0) {
splitnode = node.splitText(search)
splittext = splitnode.splitText(RegExp.lastMatch.length)
newelement = getelem(splitnode.data)
if (!ignores.includes(newelement.tagName.toLowerCase()))
ignores.push(newelement.tagName.toLowerCase())
splitnode.innerHTML = splitnode.textContent = ""
newelement.appendChild(splitnode)
splittext.parentNode.insertBefore(newelement, splittext)
}
} else if (
node.nodeType == 11 ||
(node.tagName && !ignores.includes(node.tagName.toLowerCase()))
)
for (i = 0; (childnode = node.childNodes[i]); ++i)
replaceall(regex, getelem, childnode, ignores)
}
function howlongago(ms, remove = 0) {
remove--
var time = ["year", "day", "hour", "minute", "second", "milisecond"]
var x = Object.values(a(ms).fromms().val)
x = x.slice(0, remove)
if (x.find((e) => e !== 0)) {
time.splice(0, x.indexOf(x.find((e) => e !== 0)))
x.splice(0, x.indexOf(x.find((e) => e !== 0)))
return x.map((e, i) => `${e} ${time[i]}${e == 1 ? "" : "s"}`).join(" ")
}
window.x = [...x]
return (
//`0 ${time[x.length - 1]}s` ||
"today"
)
}
function getdate(date) {
const tonum = {
january: 1,
february: 2,
march: 3,
april: 4,
may: 5,
june: 6,
july: 7,
august: 8,
september: 9,
october: 10,
november: 11,
december: 12,
jan: 1,
feb: 2,
mar: 3,
apr: 4,
jun: 6,
jul: 7,
aug: 8,
sep: 9,
oct: 10,
nov: 11,
dec: 12,
}
function f(reg) {
reg = String(reg).replaceAll(/^\/|\/[gimsueyx]*$/g, "")
;[
["d2", "\\d{2}(?:rd|th|nd|st)?"],
["d4", "\\d{4}(?:rd|th|nd|st)?"],
["d12", "\\d{1,2}(?:rd|th|nd|st)?"],
[
"monthname",
"(?:jan(?:uary)?|feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|may|june?|july?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)",
],
["space", "[^a-z0-9.]"],
["start", "(?<![\\d\\w/])"],
["end", "(?![\\d\\w])"],
].forEach(([a, s]) => {
reg = reg.replaceAll(a, s)
})
return new RegExp(reg, "i")
}
function d({ day, month, year, string }) {
day = Number(day.match(/\d+/)[0])
month = tonum[month?.toLowerCase?.()] || Number(month)
if (!month) return
if (day > 31) return
year = Number(
year.length == 2
? String(new Date().getFullYear()).substring(0, 2) + year
: year
)
var today = new Date()
today.setHours(0, 0, 0, 0)
var ms = today - new Date(year, month - 1, day)
return {
day,
month,
year,
string,
ms: Math.abs(ms),
isago: ms > 0,
}
}
var temp
if ((temp = date.match(f(/start(d12)([\/\-])(d12)\2(d4|d2)end/))))
return d({
day: temp[3],
month: temp[1],
year: temp[4],
string: temp[0],
})
if ((temp = date.match(f(/start(d4)([\/\-])(d12)\2(d12)end/))))
return d({
day: temp[4],
month: temp[3],
year: temp[1],
string: temp[0],
})
if ((temp = date.match(f(/start(monthname)space*(d12)space+(d4)end/))))
return d({
day: temp[2],
month: temp[1],
year: temp[3],
string: temp[0],
})
if ((temp = date.match(f(/start(monthname)(d12)(d4)end/))))
return d({
day: temp[2],
month: temp[1],
year: temp[3],
string: temp[0],
})
if ((temp = date.match(f(/start(d12)(monthname)(d4)end/))))
return d({
day: temp[1],
month: temp[2],
year: temp[3],
string: temp[0],
})
if ((temp = date.match(f(/start(d4)(monthname)(d12)end/))))
return d({
day: temp[3],
month: temp[2],
year: temp[1],
string: temp[0],
})
if ((temp = date.match(f(/start(d12)space*(monthname)space*(d4)end/))))
return d({
day: temp[1],
month: temp[2],
year: temp[3],
string: temp[0],
})
if ((temp = date.match(f(/start(d4)space*(monthname)space*(d12)end/))))
return d({
day: temp[3],
month: temp[2],
year: temp[1],
string: temp[0],
})
if ((temp = date.match(f(/start(monthname)space*(d12)end/))))
return d({
day: temp[2],
month: temp[1],
year: new Date().getFullYear(),
string: temp[0],
})
}