GitHub Relative Time Format

replacing GitHub relative timestamps(<relative-time>) with customizable date and time formats

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name              GitHub Relative Time Format
// @name:zh-CN        GitHub 时间格式化
// @namespace         https://greasyfork.org/zh-CN/scripts/480032-github-relative-time-format
// @version           0.7.1
// @description       replacing GitHub relative timestamps(<relative-time>) with customizable date and time formats
// @description:zh-CN 用自定义的日期时间格式替换 GitHub 时间显示(<relative-time>)
// @author            MuXiu1997 (https://github.com/MuXiu1997)
// @license           MIT
// @homepageURL       https://github.com/MuXiu1997/github-relative-time-format
// @supportURL        https://github.com/MuXiu1997/github-relative-time-format
// @match             https://github.com/**
// @icon              https://www.google.com/s2/favicons?sz=64&domain=github.com
// @grant             GM_getValue
// @grant             GM_setValue
// @grant             GM_registerMenuCommand
// @grant             GM_unregisterMenuCommand
// @require           https://cdn.jsdelivr.net/npm/[email protected]/dayjs.min.js
// @require           https://cdn.jsdelivr.net/npm/[email protected]/dist/src/index.umd.js
// ==/UserScript==
(function(ts_debounce, dayjs) {

//#region rolldown:runtime
	var __create = Object.create;
	var __defProp = Object.defineProperty;
	var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
	var __getOwnPropNames = Object.getOwnPropertyNames;
	var __getProtoOf = Object.getPrototypeOf;
	var __hasOwnProp = Object.prototype.hasOwnProperty;
	var __copyProps = (to, from, except, desc) => {
		if (from && typeof from === "object" || typeof from === "function") {
			for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
				key = keys[i];
				if (!__hasOwnProp.call(to, key) && key !== except) {
					__defProp(to, key, {
						get: ((k) => from[k]).bind(null, key),
						enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
					});
				}
			}
		}
		return to;
	};
	var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
		value: mod,
		enumerable: true
	}) : target, mod));

//#endregion
dayjs = __toESM(dayjs);

//#region node_modules/.pnpm/[email protected]/node_modules/alien-signals/esm/system.mjs
	function createReactiveSystem({ update, notify, unwatched }) {
		return {
			link: link$1,
			unlink: unlink$1,
			propagate: propagate$1,
			checkDirty: checkDirty$1,
			shallowPropagate: shallowPropagate$1
		};
		function link$1(dep, sub, version$1) {
			const prevDep = sub.depsTail;
			if (prevDep !== void 0 && prevDep.dep === dep) return;
			const nextDep = prevDep !== void 0 ? prevDep.nextDep : sub.deps;
			if (nextDep !== void 0 && nextDep.dep === dep) {
				nextDep.version = version$1;
				sub.depsTail = nextDep;
				return;
			}
			const prevSub = dep.subsTail;
			if (prevSub !== void 0 && prevSub.version === version$1 && prevSub.sub === sub) return;
			const newLink = sub.depsTail = dep.subsTail = {
				version: version$1,
				dep,
				sub,
				prevDep,
				nextDep,
				prevSub,
				nextSub: void 0
			};
			if (nextDep !== void 0) nextDep.prevDep = newLink;
			if (prevDep !== void 0) prevDep.nextDep = newLink;
			else sub.deps = newLink;
			if (prevSub !== void 0) prevSub.nextSub = newLink;
			else dep.subs = newLink;
		}
		function unlink$1(link$2, sub = link$2.sub) {
			const dep = link$2.dep;
			const prevDep = link$2.prevDep;
			const nextDep = link$2.nextDep;
			const nextSub = link$2.nextSub;
			const prevSub = link$2.prevSub;
			if (nextDep !== void 0) nextDep.prevDep = prevDep;
			else sub.depsTail = prevDep;
			if (prevDep !== void 0) prevDep.nextDep = nextDep;
			else sub.deps = nextDep;
			if (nextSub !== void 0) nextSub.prevSub = prevSub;
			else dep.subsTail = prevSub;
			if (prevSub !== void 0) prevSub.nextSub = nextSub;
			else if ((dep.subs = nextSub) === void 0) unwatched(dep);
			return nextDep;
		}
		function propagate$1(link$2) {
			let next = link$2.nextSub;
			let stack;
			top: do {
				const sub = link$2.sub;
				let flags = sub.flags;
				if (!(flags & 60)) sub.flags = flags | 32;
				else if (!(flags & 12)) flags = 0;
				else if (!(flags & 4)) sub.flags = flags & -9 | 32;
				else if (!(flags & 48) && isValidLink(link$2, sub)) {
					sub.flags = flags | 40;
					flags &= 1;
				} else flags = 0;
				if (flags & 2) notify(sub);
				if (flags & 1) {
					const subSubs = sub.subs;
					if (subSubs !== void 0) {
						const nextSub = (link$2 = subSubs).nextSub;
						if (nextSub !== void 0) {
							stack = {
								value: next,
								prev: stack
							};
							next = nextSub;
						}
						continue;
					}
				}
				if ((link$2 = next) !== void 0) {
					next = link$2.nextSub;
					continue;
				}
				while (stack !== void 0) {
					link$2 = stack.value;
					stack = stack.prev;
					if (link$2 !== void 0) {
						next = link$2.nextSub;
						continue top;
					}
				}
				break;
			} while (true);
		}
		function checkDirty$1(link$2, sub) {
			let stack;
			let checkDepth = 0;
			let dirty = false;
			top: do {
				const dep = link$2.dep;
				const flags = dep.flags;
				if (sub.flags & 16) dirty = true;
				else if ((flags & 17) === 17) {
					if (update(dep)) {
						const subs = dep.subs;
						if (subs.nextSub !== void 0) shallowPropagate$1(subs);
						dirty = true;
					}
				} else if ((flags & 33) === 33) {
					if (link$2.nextSub !== void 0 || link$2.prevSub !== void 0) stack = {
						value: link$2,
						prev: stack
					};
					link$2 = dep.deps;
					sub = dep;
					++checkDepth;
					continue;
				}
				if (!dirty) {
					const nextDep = link$2.nextDep;
					if (nextDep !== void 0) {
						link$2 = nextDep;
						continue;
					}
				}
				while (checkDepth--) {
					const firstSub = sub.subs;
					const hasMultipleSubs = firstSub.nextSub !== void 0;
					if (hasMultipleSubs) {
						link$2 = stack.value;
						stack = stack.prev;
					} else link$2 = firstSub;
					if (dirty) {
						if (update(sub)) {
							if (hasMultipleSubs) shallowPropagate$1(firstSub);
							sub = link$2.sub;
							continue;
						}
						dirty = false;
					} else sub.flags &= -33;
					sub = link$2.sub;
					const nextDep = link$2.nextDep;
					if (nextDep !== void 0) {
						link$2 = nextDep;
						continue top;
					}
				}
				return dirty;
			} while (true);
		}
		function shallowPropagate$1(link$2) {
			do {
				const sub = link$2.sub;
				const flags = sub.flags;
				if ((flags & 48) === 32) {
					sub.flags = flags | 16;
					if ((flags & 6) === 2) notify(sub);
				}
			} while ((link$2 = link$2.nextSub) !== void 0);
		}
		function isValidLink(checkLink, sub) {
			let link$2 = sub.depsTail;
			while (link$2 !== void 0) {
				if (link$2 === checkLink) return true;
				link$2 = link$2.prevDep;
			}
			return false;
		}
	}

//#endregion
//#region node_modules/.pnpm/[email protected]/node_modules/alien-signals/esm/index.mjs
	let cycle = 0;
	let batchDepth = 0;
	let notifyIndex = 0;
	let queuedLength = 0;
	let activeSub;
	const queued = [];
	const { link, unlink, propagate, checkDirty, shallowPropagate } = createReactiveSystem({
		update(node) {
			if (node.depsTail !== void 0) return updateComputed(node);
			else return updateSignal(node);
		},
		notify(effect$1) {
			let insertIndex = queuedLength;
			let firstInsertedIndex = insertIndex;
			do {
				var _effect$subs;
				effect$1.flags &= -3;
				queued[insertIndex++] = effect$1;
				effect$1 = (_effect$subs = effect$1.subs) === null || _effect$subs === void 0 ? void 0 : _effect$subs.sub;
				if (effect$1 === void 0 || !(effect$1.flags & 2)) break;
			} while (true);
			queuedLength = insertIndex;
			while (firstInsertedIndex < --insertIndex) {
				const left = queued[firstInsertedIndex];
				queued[firstInsertedIndex++] = queued[insertIndex];
				queued[insertIndex] = left;
			}
		},
		unwatched(node) {
			if (!(node.flags & 1)) effectScopeOper.call(node);
			else if (node.depsTail !== void 0) {
				node.depsTail = void 0;
				node.flags = 17;
				purgeDeps(node);
			}
		}
	});
	function setActiveSub(sub) {
		const prevSub = activeSub;
		activeSub = sub;
		return prevSub;
	}
	function signal(initialValue) {
		return signalOper.bind({
			currentValue: initialValue,
			pendingValue: initialValue,
			subs: void 0,
			subsTail: void 0,
			flags: 1
		});
	}
	function computed(getter) {
		return computedOper.bind({
			value: void 0,
			subs: void 0,
			subsTail: void 0,
			deps: void 0,
			depsTail: void 0,
			flags: 0,
			getter
		});
	}
	function effect(fn) {
		const e = {
			fn,
			subs: void 0,
			subsTail: void 0,
			deps: void 0,
			depsTail: void 0,
			flags: 6
		};
		const prevSub = setActiveSub(e);
		if (prevSub !== void 0) link(e, prevSub, 0);
		try {
			e.fn();
		} finally {
			activeSub = prevSub;
			e.flags &= -5;
		}
		return effectOper.bind(e);
	}
	function updateComputed(c) {
		++cycle;
		c.depsTail = void 0;
		c.flags = 5;
		const prevSub = setActiveSub(c);
		try {
			const oldValue = c.value;
			return oldValue !== (c.value = c.getter(oldValue));
		} finally {
			activeSub = prevSub;
			c.flags &= -5;
			purgeDeps(c);
		}
	}
	function updateSignal(s) {
		s.flags = 1;
		return s.currentValue !== (s.currentValue = s.pendingValue);
	}
	function run(e) {
		const flags = e.flags;
		if (flags & 16 || flags & 32 && checkDirty(e.deps, e)) {
			++cycle;
			e.depsTail = void 0;
			e.flags = 6;
			const prevSub = setActiveSub(e);
			try {
				e.fn();
			} finally {
				activeSub = prevSub;
				e.flags &= -5;
				purgeDeps(e);
			}
		} else e.flags = 2;
	}
	function flush() {
		while (notifyIndex < queuedLength) {
			const effect$1 = queued[notifyIndex];
			queued[notifyIndex++] = void 0;
			run(effect$1);
		}
		notifyIndex = 0;
		queuedLength = 0;
	}
	function computedOper() {
		const flags = this.flags;
		if (flags & 16 || flags & 32 && (checkDirty(this.deps, this) || (this.flags = flags & -33, false))) {
			if (updateComputed(this)) {
				const subs = this.subs;
				if (subs !== void 0) shallowPropagate(subs);
			}
		} else if (!flags) {
			this.flags = 5;
			const prevSub = setActiveSub(this);
			try {
				this.value = this.getter();
			} finally {
				activeSub = prevSub;
				this.flags &= -5;
			}
		}
		const sub = activeSub;
		if (sub !== void 0) link(this, sub, cycle);
		return this.value;
	}
	function signalOper(...value) {
		if (value.length) {
			if (this.pendingValue !== (this.pendingValue = value[0])) {
				this.flags = 17;
				const subs = this.subs;
				if (subs !== void 0) {
					propagate(subs);
					if (!batchDepth) flush();
				}
			}
		} else {
			if (this.flags & 16) {
				if (updateSignal(this)) {
					const subs = this.subs;
					if (subs !== void 0) shallowPropagate(subs);
				}
			}
			let sub = activeSub;
			while (sub !== void 0) {
				var _sub$subs;
				if (sub.flags & 3) {
					link(this, sub, cycle);
					break;
				}
				sub = (_sub$subs = sub.subs) === null || _sub$subs === void 0 ? void 0 : _sub$subs.sub;
			}
			return this.currentValue;
		}
	}
	function effectOper() {
		effectScopeOper.call(this);
	}
	function effectScopeOper() {
		this.depsTail = void 0;
		this.flags = 0;
		purgeDeps(this);
		const sub = this.subs;
		if (sub !== void 0) unlink(sub);
	}
	function purgeDeps(sub) {
		const depsTail = sub.depsTail;
		let dep = depsTail !== void 0 ? depsTail.nextDep : sub.deps;
		while (dep !== void 0) dep = unlink(dep, sub);
	}

//#endregion
//#region \0@[email protected]/helpers/typeof.js
	function _typeof(o) {
		"@babel/helpers - typeof";
		return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
			return typeof o$1;
		} : function(o$1) {
			return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
		}, _typeof(o);
	}

//#endregion
//#region \0@[email protected]/helpers/toPrimitive.js
	function toPrimitive(t, r) {
		if ("object" != _typeof(t) || !t) return t;
		var e = t[Symbol.toPrimitive];
		if (void 0 !== e) {
			var i = e.call(t, r || "default");
			if ("object" != _typeof(i)) return i;
			throw new TypeError("@@toPrimitive must return a primitive value.");
		}
		return ("string" === r ? String : Number)(t);
	}

//#endregion
//#region \0@[email protected]/helpers/toPropertyKey.js
	function toPropertyKey(t) {
		var i = toPrimitive(t, "string");
		return "symbol" == _typeof(i) ? i : i + "";
	}

//#endregion
//#region \0@[email protected]/helpers/defineProperty.js
	function _defineProperty(e, r, t) {
		return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
			value: t,
			enumerable: !0,
			configurable: !0,
			writable: !0
		}) : e[r] = t, e;
	}

//#endregion
//#region \0@[email protected]/helpers/objectSpread2.js
	function ownKeys(e, r) {
		var t = Object.keys(e);
		if (Object.getOwnPropertySymbols) {
			var o = Object.getOwnPropertySymbols(e);
			r && (o = o.filter(function(r$1) {
				return Object.getOwnPropertyDescriptor(e, r$1).enumerable;
			})), t.push.apply(t, o);
		}
		return t;
	}
	function _objectSpread2(e) {
		for (var r = 1; r < arguments.length; r++) {
			var t = null != arguments[r] ? arguments[r] : {};
			r % 2 ? ownKeys(Object(t), !0).forEach(function(r$1) {
				_defineProperty(e, r$1, t[r$1]);
			}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r$1) {
				Object.defineProperty(e, r$1, Object.getOwnPropertyDescriptor(t, r$1));
			});
		}
		return e;
	}

//#endregion
//#region node_modules/.pnpm/[email protected]/node_modules/consola/dist/core.mjs
	const LogLevels = {
		silent: Number.NEGATIVE_INFINITY,
		fatal: 0,
		error: 0,
		warn: 1,
		log: 2,
		info: 3,
		success: 3,
		fail: 3,
		ready: 3,
		start: 3,
		box: 3,
		debug: 4,
		trace: 5,
		verbose: Number.POSITIVE_INFINITY
	};
	const LogTypes = {
		silent: { level: -1 },
		fatal: { level: LogLevels.fatal },
		error: { level: LogLevels.error },
		warn: { level: LogLevels.warn },
		log: { level: LogLevels.log },
		info: { level: LogLevels.info },
		success: { level: LogLevels.success },
		fail: { level: LogLevels.fail },
		ready: { level: LogLevels.info },
		start: { level: LogLevels.info },
		box: { level: LogLevels.info },
		debug: { level: LogLevels.debug },
		trace: { level: LogLevels.trace },
		verbose: { level: LogLevels.verbose }
	};
	function isPlainObject$1(value) {
		if (value === null || typeof value !== "object") return false;
		const prototype = Object.getPrototypeOf(value);
		if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) return false;
		if (Symbol.iterator in value) return false;
		if (Symbol.toStringTag in value) return Object.prototype.toString.call(value) === "[object Module]";
		return true;
	}
	function _defu(baseObject, defaults, namespace = ".", merger) {
		if (!isPlainObject$1(defaults)) return _defu(baseObject, {}, namespace, merger);
		const object = Object.assign({}, defaults);
		for (const key in baseObject) {
			if (key === "__proto__" || key === "constructor") continue;
			const value = baseObject[key];
			if (value === null || value === void 0) continue;
			if (merger && merger(object, key, value, namespace)) continue;
			if (Array.isArray(value) && Array.isArray(object[key])) object[key] = [...value, ...object[key]];
			else if (isPlainObject$1(value) && isPlainObject$1(object[key])) object[key] = _defu(value, object[key], (namespace ? `${namespace}.` : "") + key.toString(), merger);
			else object[key] = value;
		}
		return object;
	}
	function createDefu(merger) {
		return (...arguments_) => arguments_.reduce((p, c) => _defu(p, c, "", merger), {});
	}
	const defu = createDefu();
	function isPlainObject(obj) {
		return Object.prototype.toString.call(obj) === "[object Object]";
	}
	function isLogObj(arg) {
		if (!isPlainObject(arg)) return false;
		if (!arg.message && !arg.args) return false;
		if (arg.stack) return false;
		return true;
	}
	let paused = false;
	const queue = [];
	var Consola = class Consola {
		/**
		* Creates an instance of Consola with specified options or defaults.
		*
		* @param {Partial<ConsolaOptions>} [options={}] - Configuration options for the Consola instance.
		*/
		constructor(options = {}) {
			const types = options.types || LogTypes;
			this.options = defu(_objectSpread2(_objectSpread2({}, options), {}, {
				defaults: _objectSpread2({}, options.defaults),
				level: _normalizeLogLevel(options.level, types),
				reporters: [...options.reporters || []]
			}), {
				types: LogTypes,
				throttle: 1e3,
				throttleMin: 5,
				formatOptions: {
					date: true,
					colors: false,
					compact: true
				}
			});
			for (const type in types) {
				const defaults = _objectSpread2(_objectSpread2({ type }, this.options.defaults), types[type]);
				this[type] = this._wrapLogFn(defaults);
				this[type].raw = this._wrapLogFn(defaults, true);
			}
			if (this.options.mockFn) this.mockTypes();
			this._lastLog = {};
		}
		/**
		* Gets the current log level of the Consola instance.
		*
		* @returns {number} The current log level.
		*/
		get level() {
			return this.options.level;
		}
		/**
		* Sets the minimum log level that will be output by the instance.
		*
		* @param {number} level - The new log level to set.
		*/
		set level(level) {
			this.options.level = _normalizeLogLevel(level, this.options.types, this.options.level);
		}
		/**
		* Displays a prompt to the user and returns the response.
		* Throw an error if `prompt` is not supported by the current configuration.
		*
		* @template T
		* @param {string} message - The message to display in the prompt.
		* @param {T} [opts] - Optional options for the prompt. See {@link PromptOptions}.
		* @returns {promise<T>} A promise that infer with the prompt options. See {@link PromptOptions}.
		*/
		prompt(message, opts) {
			if (!this.options.prompt) throw new Error("prompt is not supported!");
			return this.options.prompt(message, opts);
		}
		/**
		* Creates a new instance of Consola, inheriting options from the current instance, with possible overrides.
		*
		* @param {Partial<ConsolaOptions>} options - Optional overrides for the new instance. See {@link ConsolaOptions}.
		* @returns {ConsolaInstance} A new Consola instance. See {@link ConsolaInstance}.
		*/
		create(options) {
			const instance = new Consola(_objectSpread2(_objectSpread2({}, this.options), options));
			if (this._mockFn) instance.mockTypes(this._mockFn);
			return instance;
		}
		/**
		* Creates a new Consola instance with the specified default log object properties.
		*
		* @param {InputLogObject} defaults - Default properties to include in any log from the new instance. See {@link InputLogObject}.
		* @returns {ConsolaInstance} A new Consola instance. See {@link ConsolaInstance}.
		*/
		withDefaults(defaults) {
			return this.create(_objectSpread2(_objectSpread2({}, this.options), {}, { defaults: _objectSpread2(_objectSpread2({}, this.options.defaults), defaults) }));
		}
		/**
		* Creates a new Consola instance with a specified tag, which will be included in every log.
		*
		* @param {string} tag - The tag to include in each log of the new instance.
		* @returns {ConsolaInstance} A new Consola instance. See {@link ConsolaInstance}.
		*/
		withTag(tag) {
			return this.withDefaults({ tag: this.options.defaults.tag ? this.options.defaults.tag + ":" + tag : tag });
		}
		/**
		* Adds a custom reporter to the Consola instance.
		* Reporters will be called for each log message, depending on their implementation and log level.
		*
		* @param {ConsolaReporter} reporter - The reporter to add. See {@link ConsolaReporter}.
		* @returns {Consola} The current Consola instance.
		*/
		addReporter(reporter) {
			this.options.reporters.push(reporter);
			return this;
		}
		/**
		* Removes a custom reporter from the Consola instance.
		* If no reporter is specified, all reporters will be removed.
		*
		* @param {ConsolaReporter} reporter - The reporter to remove. See {@link ConsolaReporter}.
		* @returns {Consola} The current Consola instance.
		*/
		removeReporter(reporter) {
			if (reporter) {
				const i = this.options.reporters.indexOf(reporter);
				if (i !== -1) return this.options.reporters.splice(i, 1);
			} else this.options.reporters.splice(0);
			return this;
		}
		/**
		* Replaces all reporters of the Consola instance with the specified array of reporters.
		*
		* @param {ConsolaReporter[]} reporters - The new reporters to set. See {@link ConsolaReporter}.
		* @returns {Consola} The current Consola instance.
		*/
		setReporters(reporters) {
			this.options.reporters = Array.isArray(reporters) ? reporters : [reporters];
			return this;
		}
		wrapAll() {
			this.wrapConsole();
			this.wrapStd();
		}
		restoreAll() {
			this.restoreConsole();
			this.restoreStd();
		}
		/**
		* Overrides console methods with Consola logging methods for consistent logging.
		*/
		wrapConsole() {
			for (const type in this.options.types) {
				if (!console["__" + type]) console["__" + type] = console[type];
				console[type] = this[type].raw;
			}
		}
		/**
		* Restores the original console methods, removing Consola overrides.
		*/
		restoreConsole() {
			for (const type in this.options.types) if (console["__" + type]) {
				console[type] = console["__" + type];
				delete console["__" + type];
			}
		}
		/**
		* Overrides standard output and error streams to redirect them through Consola.
		*/
		wrapStd() {
			this._wrapStream(this.options.stdout, "log");
			this._wrapStream(this.options.stderr, "log");
		}
		_wrapStream(stream, type) {
			if (!stream) return;
			if (!stream.__write) stream.__write = stream.write;
			stream.write = (data) => {
				this[type].raw(String(data).trim());
			};
		}
		/**
		* Restores the original standard output and error streams, removing the Consola redirection.
		*/
		restoreStd() {
			this._restoreStream(this.options.stdout);
			this._restoreStream(this.options.stderr);
		}
		_restoreStream(stream) {
			if (!stream) return;
			if (stream.__write) {
				stream.write = stream.__write;
				delete stream.__write;
			}
		}
		/**
		* Pauses logging, queues incoming logs until resumed.
		*/
		pauseLogs() {
			paused = true;
		}
		/**
		* Resumes logging, processing any queued logs.
		*/
		resumeLogs() {
			paused = false;
			const _queue = queue.splice(0);
			for (const item of _queue) item[0]._logFn(item[1], item[2]);
		}
		/**
		* Replaces logging methods with mocks if a mock function is provided.
		*
		* @param {ConsolaOptions["mockFn"]} mockFn - The function to use for mocking logging methods. See {@link ConsolaOptions["mockFn"]}.
		*/
		mockTypes(mockFn) {
			const _mockFn = mockFn || this.options.mockFn;
			this._mockFn = _mockFn;
			if (typeof _mockFn !== "function") return;
			for (const type in this.options.types) {
				this[type] = _mockFn(type, this.options.types[type]) || this[type];
				this[type].raw = this[type];
			}
		}
		_wrapLogFn(defaults, isRaw) {
			return (...args) => {
				if (paused) {
					queue.push([
						this,
						defaults,
						args,
						isRaw
					]);
					return;
				}
				return this._logFn(defaults, args, isRaw);
			};
		}
		_logFn(defaults, args, isRaw) {
			if ((defaults.level || 0) > this.level) return false;
			const logObj = _objectSpread2(_objectSpread2({
				date: /* @__PURE__ */ new Date(),
				args: []
			}, defaults), {}, { level: _normalizeLogLevel(defaults.level, this.options.types) });
			if (!isRaw && args.length === 1 && isLogObj(args[0])) Object.assign(logObj, args[0]);
			else logObj.args = [...args];
			if (logObj.message) {
				logObj.args.unshift(logObj.message);
				delete logObj.message;
			}
			if (logObj.additional) {
				if (!Array.isArray(logObj.additional)) logObj.additional = logObj.additional.split("\n");
				logObj.args.push("\n" + logObj.additional.join("\n"));
				delete logObj.additional;
			}
			logObj.type = typeof logObj.type === "string" ? logObj.type.toLowerCase() : "log";
			logObj.tag = typeof logObj.tag === "string" ? logObj.tag : "";
			const resolveLog = (newLog = false) => {
				const repeated = (this._lastLog.count || 0) - this.options.throttleMin;
				if (this._lastLog.object && repeated > 0) {
					const args2 = [...this._lastLog.object.args];
					if (repeated > 1) args2.push(`(repeated ${repeated} times)`);
					this._log(_objectSpread2(_objectSpread2({}, this._lastLog.object), {}, { args: args2 }));
					this._lastLog.count = 1;
				}
				if (newLog) {
					this._lastLog.object = logObj;
					this._log(logObj);
				}
			};
			clearTimeout(this._lastLog.timeout);
			const diffTime = this._lastLog.time && logObj.date ? logObj.date.getTime() - this._lastLog.time.getTime() : 0;
			this._lastLog.time = logObj.date;
			if (diffTime < this.options.throttle) try {
				const serializedLog = JSON.stringify([
					logObj.type,
					logObj.tag,
					logObj.args
				]);
				const isSameLog = this._lastLog.serialized === serializedLog;
				this._lastLog.serialized = serializedLog;
				if (isSameLog) {
					this._lastLog.count = (this._lastLog.count || 0) + 1;
					if (this._lastLog.count > this.options.throttleMin) {
						this._lastLog.timeout = setTimeout(resolveLog, this.options.throttle);
						return;
					}
				}
			} catch (_unused) {}
			resolveLog(true);
		}
		_log(logObj) {
			for (const reporter of this.options.reporters) reporter.log(logObj, { options: this.options });
		}
	};
	function _normalizeLogLevel(input, types = {}, defaultLevel = 3) {
		if (input === void 0) return defaultLevel;
		if (typeof input === "number") return input;
		if (types[input] && types[input].level !== void 0) return types[input].level;
		return defaultLevel;
	}
	Consola.prototype.add = Consola.prototype.addReporter;
	Consola.prototype.remove = Consola.prototype.removeReporter;
	Consola.prototype.clear = Consola.prototype.removeReporter;
	Consola.prototype.withScope = Consola.prototype.withTag;
	Consola.prototype.mock = Consola.prototype.mockTypes;
	Consola.prototype.pause = Consola.prototype.pauseLogs;
	Consola.prototype.resume = Consola.prototype.resumeLogs;
	function createConsola(options = {}) {
		return new Consola(options);
	}

//#endregion
//#region node_modules/.pnpm/[email protected]/node_modules/consola/dist/browser.mjs
	var BrowserReporter = class {
		constructor(options) {
			this.options = _objectSpread2({}, options);
			this.defaultColor = "#7f8c8d";
			this.levelColorMap = {
				0: "#c0392b",
				1: "#f39c12",
				3: "#00BCD4"
			};
			this.typeColorMap = { success: "#2ecc71" };
		}
		_getLogFn(level) {
			if (level < 1) return console.__error || console.error;
			if (level === 1) return console.__warn || console.warn;
			return console.__log || console.log;
		}
		log(logObj) {
			const consoleLogFn = this._getLogFn(logObj.level);
			const type = logObj.type === "log" ? "" : logObj.type;
			const tag = logObj.tag || "";
			const style = `
      background: ${this.typeColorMap[logObj.type] || this.levelColorMap[logObj.level] || this.defaultColor};
      border-radius: 0.5em;
      color: white;
      font-weight: bold;
      padding: 2px 0.5em;
    `;
			const badge = `%c${[tag, type].filter(Boolean).join(":")}`;
			if (typeof logObj.args[0] === "string") consoleLogFn(`${badge}%c ${logObj.args[0]}`, style, "", ...logObj.args.slice(1));
			else consoleLogFn(badge, style, ...logObj.args);
		}
	};
	function createConsola$1(options = {}) {
		return createConsola(_objectSpread2({
			reporters: options.reporters || [new BrowserReporter({})],
			prompt(message, options2 = {}) {
				if (options2.type === "confirm") return Promise.resolve(confirm(message));
				return Promise.resolve(prompt(message));
			}
		}, options));
	}
	const consola = createConsola$1();

//#endregion
//#region package.json
	var version = "0.7.1";

//#endregion
//#region src/core.ts
	const logger = consola.withDefaults({ tag: "GRTF" });
	/** Check if the element is a valid relative-time custom element */
	function isRelativeTimeElement(element) {
		return element instanceof HTMLElement && element.tagName === "RELATIVE-TIME";
	}
	/**
	* Check if the node is a <relative-time> element or sits inside one (including Shadow DOM).
	* This is efficient for attribute or characterData mutations.
	*/
	function isInsideRelativeTime(node) {
		if (!node) return false;
		const element = node instanceof Element ? node : node.parentElement;
		if (element === null || element === void 0 ? void 0 : element.closest("relative-time")) return true;
		const root = node.getRootNode();
		return root instanceof ShadowRoot && isRelativeTimeElement(root.host);
	}
	/**
	* Check if the element contains any <relative-time> descendants.
	* This is useful for childList mutations where a container might be added.
	*/
	function isContainingRelativeTime(node) {
		return node instanceof Element && node.getElementsByTagName("relative-time").length > 0;
	}
	/** Determine if the element should preserve its native format based on attributes */
	function shouldPreserveNativeFormat(element) {
		const format = element.getAttribute("format");
		return format === "duration" || format === "elapsed";
	}
	/** Apply custom format to a single relative-time element */
	function applyCustomFormat(element, displayFormat, tooltipFormat) {
		const startTime = performance.now();
		const datetime = element.getAttribute("datetime");
		if (!datetime) return;
		const date = (0, dayjs.default)(datetime);
		if (!date.isValid()) return;
		element.title = date.format(tooltipFormat);
		try {
			var _element$disconnected;
			(_element$disconnected = element.disconnectedCallback) === null || _element$disconnected === void 0 || _element$disconnected.call(element);
			let updated = false;
			if (element.shadowRoot) {
				const newContent = date.format(displayFormat);
				if (element.shadowRoot.innerHTML !== newContent) {
					element.shadowRoot.innerHTML = newContent;
					updated = true;
				}
			} else {
				const newContent = date.format(displayFormat);
				if (element.textContent !== newContent) {
					element.textContent = newContent;
					updated = true;
				}
			}
			if (updated) {
				const duration = performance.now() - startTime;
				logger.debug(`Updated element:`, element, `in ${duration.toFixed(3)}ms`);
			}
		} catch (error) {
			logger.warn("Error updating element", element, error);
		}
	}
	/** Restore the native behavior of the relative-time element */
	function restoreNativeFormat(element) {
		try {
			var _element$connectedCal;
			(_element$connectedCal = element.connectedCallback) === null || _element$connectedCal === void 0 || _element$connectedCal.call(element);
		} catch (error) {
			logger.warn("Error restoring element", element, error);
		}
	}
	/** Iterate and update all relative-time elements in the DOM */
	function updateAllElements(displayFormat, tooltipFormat) {
		const startTime = performance.now();
		const elements = document.querySelectorAll(`relative-time`);
		if (elements.length === 0) return;
		let updateCount = 0;
		for (const element of elements) if (shouldPreserveNativeFormat(element)) restoreNativeFormat(element);
		else {
			applyCustomFormat(element, displayFormat, tooltipFormat);
			updateCount++;
		}
		const duration = performance.now() - startTime;
		if (updateCount > 0) logger.debug({
			type: "success",
			message: `Total updated: ${updateCount} elements in ${duration.toFixed(3)}ms`
		});
	}

//#endregion
//#region \0@[email protected]/helpers/asyncToGenerator.js
	function asyncGeneratorStep(n, t, e, r, o, a, c) {
		try {
			var i = n[a](c), u = i.value;
		} catch (n$1) {
			e(n$1);
			return;
		}
		i.done ? t(u) : Promise.resolve(u).then(r, o);
	}
	function _asyncToGenerator(n) {
		return function() {
			var t = this, e = arguments;
			return new Promise(function(r, o) {
				var a = n.apply(t, e);
				function _next(n$1) {
					asyncGeneratorStep(a, r, o, _next, _throw, "next", n$1);
				}
				function _throw(n$1) {
					asyncGeneratorStep(a, r, o, _next, _throw, "throw", n$1);
				}
				_next(void 0);
			});
		};
	}

//#endregion
//#region src/ui.ts
	let activeResolve = null;
	/**
	* Show a GitHub-style modal for option editing
	*/
	function showOptionModal(_x, _x2, _x3) {
		return _showOptionModal.apply(this, arguments);
	}
	function _showOptionModal() {
		_showOptionModal = _asyncToGenerator(function* (title, currentValue, type) {
			if (activeResolve) {
				activeResolve(null);
				activeResolve = null;
			}
			const existingDialog = document.querySelector("dialog[data-grtf-modal]");
			if (existingDialog) {
				existingDialog.close();
				existingDialog.remove();
			}
			return new Promise((resolve) => {
				var _dialog$querySelector, _dialog$querySelector2, _dialog$querySelector3;
				activeResolve = resolve;
				const dialog = document.createElement("dialog");
				dialog.dataset.grtfModal = "";
				dialog.className = "Box Box--overlay d-flex flex-column anim-fade-in fast";
				dialog.style.cssText = `
      width: 448px;
      padding: 0;
      border: 1px solid var(--color-border-default, #30363d);
      border-radius: 6px;
      background-color: var(--bgColor-default, var(--color-canvas-overlay, #161b22));
      color: var(--color-fg-default, #c9d1d9);
      box-shadow: var(--color-shadow-large, 0 8px 24px rgba(1, 4, 9, 0.2));
      position: fixed;
      top: 10%;
      left: 50%;
      transform: translateX(-50%);
      margin: 0;
      display: flex;
    `;
				const isBoolean = type === "boolean";
				dialog.innerHTML = `
      <div class="Box-header d-flex flex-items-center">
        <h3 class="Box-title flex-auto">${title}</h3>
        <button class="btn-octicon" type="button" id="modal-close" aria-label="Close">
          <svg aria-hidden="true" height="16" viewBox="0 0 16 16" width="16" fill="currentColor"><path d="M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z"></path></svg>
        </button>
      </div>
      <div class="Box-body">
        ${isBoolean ? `
          <div class="form-checkbox">
            <label>
              <input type="checkbox" id="modal-input" ${currentValue === "true" ? "checked" : ""}>
              Enable
            </label>
          </div>
          ` : `
          <input type="text" id="modal-input" class="form-control input-block" value="${currentValue}" spellcheck="false">
          `}
      </div>
      <div class="Box-footer text-right">
        <button class="btn btn-secondary mr-2" type="button" id="modal-cancel">Cancel</button>
        <button class="btn btn-primary" type="button" id="modal-save">Save</button>
      </div>
    `;
				if (!document.getElementById("grtf-modal-style")) {
					const style = document.createElement("style");
					style.id = "grtf-modal-style";
					style.textContent = `
        dialog[data-grtf-modal]::backdrop {
          background-color: rgba(0, 0, 0, 0.7);
          backdrop-filter: blur(2px);
        }
        dialog[data-grtf-modal] {
          background-color: var(--bgColor-default, var(--color-canvas-overlay, #161b22)) !important;
        }
      `;
					document.head.appendChild(style);
				}
				document.body.appendChild(dialog);
				dialog.showModal();
				const input = dialog.querySelector("#modal-input");
				const close = () => {
					activeResolve = null;
					dialog.close();
					document.body.removeChild(dialog);
				};
				(_dialog$querySelector = dialog.querySelector("#modal-save")) === null || _dialog$querySelector === void 0 || _dialog$querySelector.addEventListener("click", () => {
					const result = isBoolean ? input.checked ? "true" : "false" : input.value;
					const resolveFn = resolve;
					close();
					resolveFn(result);
				});
				(_dialog$querySelector2 = dialog.querySelector("#modal-cancel")) === null || _dialog$querySelector2 === void 0 || _dialog$querySelector2.addEventListener("click", () => {
					const resolveFn = resolve;
					close();
					resolveFn(null);
				});
				(_dialog$querySelector3 = dialog.querySelector("#modal-close")) === null || _dialog$querySelector3 === void 0 || _dialog$querySelector3.addEventListener("click", () => {
					const resolveFn = resolve;
					close();
					resolveFn(null);
				});
				dialog.addEventListener("cancel", () => {
					activeResolve = null;
					document.body.removeChild(dialog);
					resolve(null);
				});
				setTimeout(() => {
					if (isBoolean) input.focus();
					else {
						input.focus();
						input.select();
					}
				}, 0);
			});
		});
		return _showOptionModal.apply(this, arguments);
	}

//#endregion
//#region src/useOption.ts
/** Option management Hook */
	function useOption(key, title, defaultValue, type = "text") {
		const option = signal(typeof GM_getValue !== "undefined" ? GM_getValue(key, defaultValue) : defaultValue);
		if (typeof GM_setValue !== "undefined" && typeof GM_registerMenuCommand !== "undefined") {
			effect(() => {
				GM_setValue(key, option());
			});
			GM_registerMenuCommand(title, _asyncToGenerator(function* () {
				const result = yield showOptionModal(title, option(), type);
				if (result !== null) option(result);
			}));
		}
		return option;
	}

//#endregion
//#region src/index.ts
/** Main entry point for the userscript */
	function main() {
		const displayFormatOption = useOption("DISPLAY_FORMAT", "Change display format", "YY-MM-DD HH:mm");
		const tooltipFormatOption = useOption("TOOLTIP_FORMAT", "Change tooltip format", "YYYY-MM-DD HH:mm:ss");
		const debugLogOption = useOption("DEBUG_LOG", "Enable debug log", "false", "boolean");
		const loggerLevel = computed(() => debugLogOption() === "true" ? LogLevels.verbose : LogLevels.info);
		const runUpdate = () => {
			updateAllElements(displayFormatOption(), tooltipFormatOption());
		};
		effect(() => {
			runUpdate();
		});
		effect(() => {
			logger.level = loggerLevel();
		});
		logger.info(`GitHub Relative Time Format(v${version}) is loaded`);
		const debouncedUpdate = (0, ts_debounce.debounce)(runUpdate, 100);
		/** Initialize MutationObserver to monitor DOM changes for new relative-time elements */
		const initObserver = () => {
			new MutationObserver((mutations) => {
				let shouldUpdate = false;
				for (const mutation of mutations) {
					const { target, type } = mutation;
					if (type === "attributes" || type === "characterData") {
						if (isInsideRelativeTime(target)) {
							shouldUpdate = true;
							break;
						}
					} else if (type === "childList") {
						if (isInsideRelativeTime(target) || isContainingRelativeTime(target)) {
							shouldUpdate = true;
							break;
						}
					}
				}
				if (shouldUpdate) debouncedUpdate();
			}).observe(document.body, {
				childList: true,
				subtree: true,
				attributes: true,
				characterData: true,
				attributeFilter: ["datetime", "format"]
			});
		};
		initObserver();
	}
	main();

//#endregion
})(tsDebounce, dayjs);