您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Non-brittle shim for expanding titles. Restores the full title string and expands it when hovering over the entire post card. You will be able to see titles without any truncation. (Version agnostic)
// ==UserScript== // @name Kemono Longer Expanded Title Cards on Hover // @namespace http://tampermonkey.net/ // @version 2.2 // @description Non-brittle shim for expanding titles. Restores the full title string and expands it when hovering over the entire post card. You will be able to see titles without any truncation. (Version agnostic) // @match https://kemono.cr/* // @run-at document-start // @grant none // @license MIT // ==/UserScript== (function () { "use strict"; // 1) Inject CSS immediately (works even if the shim fails for any reason) try { const style = document.createElement("style"); style.textContent = ` .post-card { position: relative !important; /* Set positioning context for the absolute header */ } .post-card__header { padding: 5px !important; z-index: 1 !important; color: #fff !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; max-width: 100% !important; display: block !important; position: relative !important; } .post-card:hover .post-card__header { white-space: normal !important; overflow: visible !important; background: #2e1905 !important; color: #fff !important; padding: 4px 6px !important; z-index: 9999 !important; position: absolute !important; width: auto !important; max-width: 300px !important; border-radius: 6px !important; }`; (document.head || document.documentElement).appendChild(style); } catch (e) { // ignore } // 2) Inject a minimal page-context shim that targets only: // "".concat(X.slice(0, 50), "...") // It returns the original full X, not the 50-char slice. // This avoids brittle function replacement and bundler assumptions. const shim = function () { try { const S = String.prototype; const origSlice = S.slice; const origConcat = S.concat; // Side channel to connect slice -> concat for the exact pattern let lastSliceValue = null; let lastSliceSource = null; Object.defineProperty(S, "slice", { configurable: true, writable: true, value: function (start, end) { // Call the real slice first const src = String(this); const out = origSlice.call(src, start, end); // Only record when pattern matches exactly slice(0, 50) and src was // actually longer (so truncation was intended). if ( start === 0 && end === 50 && typeof out === "string" && src.length > 50 ) { lastSliceValue = out; lastSliceSource = src; } else { // Any other slice clears the channel lastSliceValue = null; lastSliceSource = null; } return out; }, }); Object.defineProperty(S, "concat", { configurable: true, writable: true, value: function (...args) { // Only target: "".concat(<recent-slice-0-50>, "...") // i.e. receiver is "", 2 args, last is "...", first equals the last // recorded slice result. try { if ( (this === "" || String(this) === "") && args.length === 2 && args[1] === "..." && typeof args[0] === "string" && lastSliceValue !== null && args[0] === lastSliceValue ) { // Return the original full string (undo truncation entirely) return lastSliceSource; } } catch (e) { // fall through to original } return origConcat.apply(this, args); }, }); } catch (e) { // If anything goes wrong, fail silently rather than breaking the page } }; // Ensure the shim runs in the page context (not the userscript sandbox) try { const s = document.createElement("script"); s.textContent = `(${shim})();`; (document.head || document.documentElement).appendChild(s); s.remove(); } catch (e) { // ignore } })();