// ==UserScript== // @name 5chサムネイル表示他 // @description r(文字列未選択時):ホバー中のレスへのアンカーを記入(R:追記) r(文字列選択時):選択文字列を引用(R:追記) m:ホバー中のレスの10番前からを表示 ,:ホバー中のレス以降を表示 .:ホバー中のレス以前を表示 d:書き込み欄にスクロール y:ホバー中の画像をyandexで画像検索 l:ホバー中のレスへのリンクをコピー // @version 0.1.25 // @run-at document-idle // @match *://*.5ch.net/test/read.cgi/* // @match *://*.5ch.net/*/ // @match *://*.5ch.net/*/SETTING.TXT // @match *://*.shitaraba.net/bbs/read.cgi/* // @match *://*.shitaraba.net/bbs/read_archive.cgi/* // @match *://*.2chan.net/* // @grant GM_addStyle // @grant GM.setClipboard // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @require https://code.jquery.com/jquery-3.4.1.min.js // @require https://code.jquery.com/ui/1.12.1/jquery-ui.min.js // @namespace https://greasyfork.org/users/181558 // @downloadURL none // ==/UserScript== (function() { const enableHoverZoom = 1; // 1:画像サムネイルのホバーズームを有効 const DEFAULT_MAIL_ADDRESS = ""; // メールアドレス初期値 ""、"sage"、その他に変更可 const inlineImageThumbnailHeight = 65; // 画像サムネイルの縦サイズ(px) const inlineImageThumbnailBokashi = 0; // 画像サムネイルのぼかしの強さ(0~10くらい) const WAIT = performance.now() * 0.5; // ページ開始後のウエイト 不安定なときは大きくする const WAIT_IMAGE_EMBED_INTERVAL = 500; // 画像埋め込みの頻度(ミリ秒) const WAIT_VIDEO_EMBED_INTERVAL = 500; // 動画埋め込みの頻度(ミリ秒) const NUMBER_IMAGE_EMBED_AT_ONCE = 3; // 画像埋め込みの速度(枚数) const inlineImageThumbnailPreloadRadius = window.innerHeight * 1; // 画面外の上下何画面分までを「画面内」とするか const ALTERNATIVE_THUMBNAIL = 0; // 1:別方式のサムネイル const CONFIRM_FOR_Y = 1; // 1:yキーでyandex検索をする時URLの確認を求める 0:求めない const CONFIRM_FOR_MCP = 0; // 1:M,.キーでURLの確認を求める 0:求めない const QUOTE_STYLE = "color:#008080;"; // 引用文のスタイル "";なら無効 const CH5_QUOTE_POPUP_SCALING_LOWER_LIMIT = 0.98; // 引用ポップアップが画面下に収まらない時縮小する倍率の下限 0.5~1ぐらい const POPUP_STYLE = 0; // 引用ポップアップの見た目 0:シンプル 1:原型維持 const DEBUG_TIMER = 0; // 1ならかかった時間を計測 const debug = 0; // 1:verbose const EXPERIMENTAL_COMPLEMENT_YOUTUBE_URL_PARTIAL = 0; // 1:不完全なYouTube URLもリンク化する(実験的) const marginH = 200; // 元絵と拡大画像の横の余白px const POPUP_Z_INDEX = 10000; // ポップアップ画像がどれくらい手前に来るか const FORCE_USE_HALF_WIDTH = 0; // 1:ホバーズームで必ず画面の横半分のサイズ const marginPe = 8; const isfvw = eleget0('#fvw_menu') const MINIMUM_ROWS = (window.navigator.userAgent.toLowerCase().indexOf('firefox') != -1) ? 2 : 3; var maey = 0; var poppedUrl = ""; var yandexUrl = ""; var mousex = 0; var mousey = 0; var lastEle = ""; var resFloat = false; var resListen = false; var maet = 0; String.prototype.match0 = function(re) { let tmp = this.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } $.fn.animate2 = function(properties, duration, ease) { ease = ease || 'ease'; var $this = this; var cssOrig = { transition: $this.css('transition') }; return $this.queue(next => { properties['transition'] = 'all ' + duration + 'ms ' + ease; $this.css(properties); setTimeout(function() { $this.css(cssOrig); next(); }, duration); }); }; document.addEventListener("mousemove", function(e) { mousex = e.clientX; mousey = e.clientY; }, false); if (/\.2chan\.net/.test(new URL(location.href).hostname)) { // ふたば $('#ftxa:visible').css({ "padding": "0.5em", "font-size": "14px", "line-height": "1.2", "font-family": "sans-serif" }) //14pxで1.2emか15pxで1.1emか setFloatKakikomi2({ textareaXP: '#ftxa', submitbuttonXP: '//input[@type="submit" and @value="返信する"]', wid: '55%', minwid: 700 }) $('#ftxa:visible').on("change click", () => { floatKakikomi2({ textareaXP: '//textarea[@id="ftxa"]', submitbuttonXP: '//input[@type="submit" and @value="返信する"]', wid: '55%', minwid: 700 }) }) $(eleget0('//input[@type="submit" and @value="返信する"]')).on("click", () => { setTimeout(() => { $('#ftxa:visible').attr("rows", MINIMUM_ROWS) }, 500) }) // レスにホバーしてキー入力 $(document).on("keypress", e => { if (e.target.tagName == 'INPUT' || e.target.tagName == 'TEXTAREA' || e.target.isContentEditable) return; var key = (e.shiftKey ? "Shift+" : "") + (e.altKey ? "Alt+" : "") + (e.ctrlKey ? "Ctrl+" : "") + e.key; var selectedStr = window.getSelection().toString() ? ">" + window.getSelection().toString().replace(/^\r\n/, "").replace(/\r?\n/g, "\r\n>").replace(/^\r?\n|\r?\n$/, "\r\n").replace(/([^\n])$/, "$1\n") : null; if ($('#ftxa:visible').length) { if ((selectedStr && (key === "r" || key === "Shift+R"))) { // r::(文字列選択中)ホバー中のレスを引用(R::追記) $('div.slp1').hide() $('#ftxa:visible').attr("rows", MINIMUM_ROWS) $('#ftxa:visible').val((key === "Shift+R" ? $('#ftxa:visible').val() + ($('#ftxa:visible').val()?.slice(-1) != "\n" ? "\n" : "") : "") + selectedStr) floatKakikomi2({ textareaXP: '//textarea[@id="ftxa"]', submitbuttonXP: '//input[@type="submit" and @value="返信する"]', wid: '55%', minwid: 700 }) return false; } if ((!selectedStr && (key === "r" || key === "Shift+R"))) { // r::(文字列不選択)ホバー中のレスNo.を引用(R::追記) レス番にホバーならレス番>本文がキターならレス番>本文ホバーなら本文を引用の順に優先 $('div.slp1').hide() let cno = eleget0('span.cno:hover') let honbun = !cno && eleget0('table:hover blockquote') if (honbun?.innerText == "キタ━━━(゚∀゚)━━━!!") honbun = null if (!cno && !honbun) cno = eleget0('table:hover span.cno') if (honbun) { $(honbun).effect("highlight", 500) } else { if (cno) $(cno).effect("highlight", 500); } $('#ftxa:visible').attr("rows", MINIMUM_ROWS) if (cno || honbun) $('#ftxa:visible').val((key === "Shift+R" ? $('#ftxa:visible').val() + ($('#ftxa:visible').val()?.slice(-1) != "\n" ? "\n" : "") : "") + (honbun ? ">" + honbun?.innerText?.replace(/^\r\n/, "").replace(/\r?\n/g, "\r\n>").replace(/^\r?\n|\r?\n$/, "\r\n").replace(/([^\n])$/, "$1\n") : cno ? ">" + cno.textContent + "\n" : "")) floatKakikomi2({ textareaXP: '//textarea[@id="ftxa"]', submitbuttonXP: '//input[@type="submit" and @value="返信する"]', wid: '55%', minwid: 700 }) return false; } } }); $('body').on('mouseup', function(e) { if (window.getSelection) { var selectedStr = window.getSelection().toString(); if (selectedStr != '' && selectedStr != '\n') { popup2(`r:引用\nR:引用(追記)`, 8); //popup2(`『${selectedStr}』を\nr:引用\nR:引用(追記)`, 5); } } }); } if (/shitaraba/.test(location.href)) { // したらば quote(); setTimeout(hNukiURLHokan, 0); setInterval(videoUmekomi, WAIT_VIDEO_EMBED_INTERVAL); setInterval(imageUmekomi, WAIT_IMAGE_EMBED_INTERVAL); if (enableHoverZoom) setInterval(onmove, 16.667); setFloatKakikomi2({ textareaXP: '//textarea[@name="MESSAGE"]', submitbuttonXP: '//div[@id="form_write"]/form[@method="POST"]/input[@value="書き込む"]' }) return; } if (location.href.match(/SETTING.TXT$/)) { // SETTING var e = document.body.innerText.match(/BBS_LINE_NUMBER=(\d*)/); if (e) { pref(getIta() + " : line_number", e[1]); } var e = document.body.innerText.match(/BBS_MESSAGE_COUNT=(\d*)/); if (e) { pref(getIta() + " : message_count", e[1]); } // alert((getIta()+" "+e[1] )); return; } function getIta() { let name = location.href.match(/^https?:\/\/.+\.5ch\.net\/test\/read.cgi\/([^\/]+)/) || location.href.match(/^https?:\/\/.+\.5ch\.net\/([^\/]+)/); if (name) name = name[1] // alert(name) return name; } var line_number = pref(getIta() + " : line_number") || null; var message_count = pref(getIta() + " : message_count") || null; // alert(line_number) if (location.href.match(/^https?:\/\/.+\.5ch\.net\/[^/]+\/$/) && eleget0('//div[last()]/form[@method="POST"]/p/input[@value="新規スレッド作成"]')) { // 板トップ elegeta('//div[@class="NEW_THREAD"]/form[@method="POST"]/p/textarea').forEach(mes => { mes.setAttribute("stretchabletextarea", "1"); mes.setAttribute("wrap", "on"); mes.style.width = "90%"; mes.addEventListener("input", () => kakikomiStretch(mes)); mes.addEventListener("focus", () => kakikomiStretch(mes)); }); elegeta('//textarea[not(@stretchabletextarea)]').forEach(mes => { mes.setAttribute("stretchabletextarea", "1"); mes.setAttribute("wrap", "on"); mes.style.width = "90%"; mes.addEventListener("input", () => kakikomiStretch(mes, "nearest")); mes.addEventListener("focus", () => kakikomiStretch(mes, "nearest")); }); return; function kakikomiStretch(target, scrollBlock = "center") { if (target.value == "") target.style.height = "100px"; let lineHeight = target.style.height.match("px") ? Number((target.style.height || "0px").replace("px", "")) : 0; //getAttribute("rows")); let height = target.scrollHeight; //+12; let clientHeight = Math.min(document.documentElement.clientHeight, window.innerHeight) - 165; for (let i = 0; i < 200 && (height >= target.offsetHeight) && target.offsetHeight < clientHeight; i++) { lineHeight += 10; target.style.height = lineHeight + "px"; } setTimeout(() => { target.scrollIntoView({ behavior: "smooth", block: scrollBlock, inline: "center" }); }, 17); displayLineLimit(target); } } if (/^https?:\/\/.+\.5ch\.net\/test\/read\.cgi\/.+/.test(location.href) == false) { return; } // httpならhttpsに if (location.href.indexOf("http://") != -1) { location.href = location.href.replace(/^http:\/\//, "https://"); return; } if (location.href.indexOf("subback.html") != -1) { return; } if (location.href.match(/\/\/.*\.5ch\.net\/\w*\/$/)) { return; } $(".mascot").attr("style", ""); let serverColor = colorFromText(new URL(location.href).hostname, 50, 30); $(document.body).append(`${document.title}`); $(eleget0('//ul/li[@class="menubottomnav"]/a[@class="menuitem" and text()="全部"]/../../..')).before(`${document.title}`); function colorFromText(txt, s, l) { return !txt ? "hsl(0,50%,50%)" : `hsl(${Array.from(txt).map(ch => ch.charCodeAt(0)).reduce((a, b) => a+b)**3%360}, ${s}%, ${l}%)`; } // レスにホバーしてキー入力 $(document).on("keypress", e => { if (e.target.tagName == 'INPUT' || e.target.tagName == 'TEXTAREA' || e.target.isContentEditable) return; var key = (e.shiftKey ? "Shift+" : "") + (e.altKey ? "Alt+" : "") + (e.ctrlKey ? "Ctrl+" : "") + e.key; var selectedStr = window.getSelection().toString() ? ">" + window.getSelection().toString().replace(/^\r\n/, "").replace(/\r\n/g, "\r\n>").replace(/^\r\n|\r\n$/, "\r\n") : null; let num = getNearest('.post'); let current = location.href + ((location.href.match(/^https?:\/\/.+\.5ch\.net\/test\/read\.cgi\/\w+\/\d+$/)) ? "/" : ""); // /18246213874 で終わるとバグる if ($('form>p>textarea').length) { if ((selectedStr && (key === "r" || key === "Shift+R"))) { // r::(文字列選択中)ホバー中のレスを引用(R::追記) let res = getNearest('div.message'); if (num && (num?.id >= 2 || (num?.id == 1 && $(window).scrollTop() < 500))) { $(getNearest('div.post')).effect("highlight", 500); floatKakikomi2({ string: ">>" + num?.id + "\r\n" + // (selectedStr ? selectedStr : (res.innerText.replace(/^>.*$\n/gm, "").replace(/^(.+)$/gm, ">$1"))) + "\r\n",(e.key == "R"||e.key == "C") ); // 引用の引用をしない (selectedStr ? selectedStr : (res.innerText.replace(/^(.+)$/gm, ">$1"))) + "\r\n", //string: (selectedStr ? selectedStr : (res.innerText.replace(/^(.+)$/gm, ">$1"))) + "\r\n", addMode: (e.key == "R" || e.key == "C"), command: e.key == "r" ? "resetHeight" : null }); //$('form>p>textarea').effect("highlight", 500); } return false; } if (key == "r" || key == "Shift+R") { // r::ホバー中のレスにアンカー R::レスにアンカー(追記) if (num?.id >= 2 || (num?.id == 1 && $(window).scrollTop() < 500)) { $(getNearest('div.post')).effect("highlight", 500); // floatKakikomi2(">>" + num.id + "\n", e.key == "R", e.key == "r" ? "resetHeight" : null); floatKakikomi2({ string: ">>" + num?.id + "\n", addMode: e.key == "R", command: e.key == "r" ? "resetHeight" : null }); //$('form>p>textarea').effect("highlight", 500); } else { floatKakikomi2({ string: "", addMode: e.key == "R", command: e.key == "r" ? "resetHeight" : null }); } return false; } } if (key === "m" || key === "," || key === "Shift+M" || key === "Shift+<") { // ,::そのレス以降を表示 m::そのレスの10個前以降を表示 (Shiftを押しながらだと新しいタブで開く) let num = getNearest('.post'); if (num) { let num2 = (num.id) - (/m/i.test(key) ? 10 : 0); $(getNearest('div.post')).effect("highlight"); let last = current.replace(/\/l\d+$/, "/").replace(/^.*\/([0-9]{0,4})?-?([0-9n]{0,4}?$)/gm, "$2"); let url = current.replace(/\/l\d+$/, "/").replace(/\/[0-9\-]{0,4}-?[0-9n]{0,4}?$/gm, "/").replace(/(\d)$/, "$1/") + Math.max(1, num2) + "-" + last; if (CONFIRM_FOR_MCP && !confirm(url)) return; if (/Shift\+/i.test(key)) { window.open(url) } else { location.href = url; } } return false; } if (key === "." || key === "Shift+>") { // .::そのレス以前を表示 (Shiftを押しながらだと新しいタブで開く) let num = getNearest('.post'); if (num) { let num2 = (num.id) - (e.key === "m" ? 10 : 0); $(getNearest('div.post')).effect("highlight"); if (num2 > 1) { let url = current.replace(/\/l\d+$/, "/").replace(/(\/[0-9]{0,4})-?[0-9n]{0,4}?$/gm, "$1") + "-" + Math.max(1, num2); if (CONFIRM_FOR_MCP && !confirm(url)) return; // location.href = url; if (/Shift\+/i.test(key)) { window.open(url) } else { location.href = url; } } } return false; } if (key === "l") { // l::ホバー中のレスへのリンクをコピー if (num) { $(getNearest('div.post')).effect("highlight", 500); GM.setClipboard(document.title + "\r\n" + location.href.replace(/\/l\d+$/, "").replace(/\/[0-9\-]{0,4}-?[0-9n]{0,4}?$/gm, "/").replace(/(\d)$/, "$1/") + num.id + "\r\n"); } return false; } /* if (key === "Shift+F") { // F::re.Find2chで検索 let query = prompt("re.Find2chでキーワード検索します\n\nhttps://refind2ch.org/search?q=${キーワード}&sort=rate\n\n"); if (query) window.open(`https://refind2ch.org/search?q=${query}&sort=rate`); return false; }*/ if (key === "y" && yandexUrl) { // y::ホバー中の画像をyandex画像検索で検索 if (!CONFIRM_FOR_Y || window.confirm(yandexUrl + "\n\nを開きます。よろしいですか?")) window.open(yandexUrl); return false; } }); $(document).on("keydown", e => { if (e.target.tagName == 'INPUT' || e.target.tagName == 'TEXTAREA' || e.target.isContentEditable) return; var key = (e.shiftKey ? "Shift+" : "") + (e.altKey ? "Alt+" : "") + (e.ctrlKey ? "Ctrl+" : "") + e.key; //if ($('form>p>textarea').length) { if (key === "d") { // d::書き込み欄にスクロール scrollKakikomi(0, 0, 1); //return false; } //} }); /* document.addEventListener("mousemove", function(e) { mousex = e.clientX; mousey = e.clientY; }, false); */ if (enableHoverZoom) setInterval(onmove, 16.667); function onmove() { let ele = document.elementFromPoint(mousex, mousey); if (lastEle !== ele) { $('img.hzP').remove(); poppedUrl = ""; } if (ele) if (ele.tagName === "IMG" && lastEle !== ele) { poppedUrl = pe(ele); yandexUrl = poppedUrl.match(/\;base64\,/i) ? null : "https://yandex.com/images/search?rpt=imageview&url=" + poppedUrl; } lastEle = ele; } function pe(a) { // var panel = a.cloneNode(true); var panel = document.createElement("img") if (!a) return; var src = "" if (a.parentNode && a.parentNode.tagName == "A" && a.parentNode.href.match(/\.png|\.jpg|\.jpeg|\.gif|\.bmp/i)) { src = decodeURIComponent(a.parentNode.href.replace(/https?:\/\/jump\.5ch\.net\/\?|https?:\/\/jbbs\.shitaraba\.net\/bbs\/link\.cgi\?url=/, "")); } else if (a.parentNode && a.parentNode.parentNode && a.parentNode.parentNode.tagName == "A" && a.parentNode.parentNode.href.match(/\.png|\.jpg|\.jpeg|\.gif|\.bmp/i)) { src = decodeURIComponent(a.parentNode.parentNode.href.replace(/https?:\/\/jump\.5ch\.net\/\?|https?:\/\/jbbs\.shitaraba\.net\/bbs\/link\.cgi\?url=/, "")); } panel.className = "hzP"; //notifyMe(panel.src) panel.src = src; setSize(a, panel, a); document.body.appendChild(panel); panel.addEventListener('load', e => { setSize(e.target, e.target, a); }); return panel.src; } function setSize(a, b, s) { var panel = b; let imgAspect = a.naturalWidth / a.naturalHeight; // svg等だとNaN 要.onload let clientAspect = window.innerWidth / 2 / window.innerHeight; let peStyle = 'margin:2px; border-radius:3px; color:#ffffff; box-shadow:3px 3px 8px #0008; border:2px solid #fff;'; let boxPos = (mousey < (window.innerHeight / 2) ? "bottom:0px;" : "top:0px;") + ((mousex < document.documentElement.clientWidth / 2) ? "right:0px; " : "left:0px;"); panel.className = "ignoreMe hzP"; let amariWidth = (mousex < document.documentElement.clientWidth / 2) ? (document.documentElement.clientWidth - (s.getBoundingClientRect()).right) : (s.getBoundingClientRect().left); if (imgAspect && ((window.innerHeight * imgAspect - marginPe) < amariWidth - marginH)) { panel.setAttribute("style", `all:initial;float:none; width:${(window.innerHeight)*imgAspect-marginPe}px; height:${((window.innerHeight))-marginPe}px;${boxPos} z-index:${POPUP_Z_INDEX}; position:fixed; ${peStyle}`); // 縦目いっぱい if (debug) popup(`余り左右:${amariWidth} naturalWidth:${a.naturalWidth} naturalHeight:${a.naturalHeight} a:${Math.round(imgAspect*100)/100} 縦目いっぱい`) } else if (imgAspect && (((amariWidth - marginH) / imgAspect) <= window.innerHeight)) { //&& (amariWidth - marginH - marginPe) > a.width * 2.5)) { panel.setAttribute("style", `all:initial;float:none; width:${amariWidth-marginH-marginPe}px; height:${(amariWidth-marginH)/imgAspect-marginPe}px;${boxPos} z-index:${POPUP_Z_INDEX}; position:fixed; ${peStyle}`); // 元絵の左右にくっつき最大 if (debug) popup(`余り左右:${amariWidth} naturalWidth:${a.naturalWidth} naturalHeight:${a.naturalHeight} a:${Math.round(imgAspect*100)/100} くっつき`) } else if (!imgAspect || window.innerWidth * 0.48 / imgAspect - marginPe <= window.innerHeight) { panel.setAttribute("style", `all:initial;float:none; width:${window.innerWidth*0.48-marginPe}px; height:${window.innerWidth*0.48/imgAspect-marginPe}px; ${boxPos} z-index:${POPUP_Z_INDEX}; position:fixed; ${peStyle}`); // 横48% if (debug) popup(`余り左右:${amariWidth} naturalWidth:${a.naturalWidth} naturalHeight:${a.naturalHeight} a:${Math.round(imgAspect*100)/100} width:${window.innerWidth*0.48-marginPe}px; height:${window.innerWidth*0.48/imgAspect-marginPe}px; 48%`) } else { panel.setAttribute("style", `all:initial;float:none; width:${(window.innerHeight)*imgAspect-marginPe}px; height:${((window.innerHeight))-marginPe}px;${boxPos} z-index:${POPUP_Z_INDEX}; position:fixed; ${peStyle}`); // 縦目いっぱい if (debug) popup(`余り左右:${amariWidth} naturalWidth:${a.naturalWidth} naturalHeight:${a.naturalHeight} a:${Math.round(imgAspect*100)/100} 縦目いっぱい2`) } } function getNearest(xpath) { let e = document.elementFromPoint(mousex, mousey); return e.closest(xpath) } // 書き込み欄までスクロール function scrollKakikomi(loop = 0, tolatestres = 0, onkey = 0) { //d:: if (resFloat) return; var ele = elegeta('.thread .post')?.filter(e => e.offsetHeight)?.slice(-1)?.find(e => e) //dc(loop) if (ele && (eleget0('//form/p/textarea[@name="MESSAGE"]') || onkey)) { window.scroll({ top: ele?.getBoundingClientRect()?.bottom + window.pageYOffset - window.innerHeight + 200, left: 0, behavior: "instant" }) } else if (loop) setTimeout(() => { scrollKakikomi(loop - 1, tolatestres) }, 500); } // setTimeout(hNukiURLHokan, WAIT); setTimeout(hNukiURLHokan, 0); setTimeout(() => { scrollKakikomi(10, 1) }, 1); //setTimeout(() => { scrollKakikomi(10, 1) }, WAIT); setTimeout(() => { setInterval(videoUmekomi, WAIT_VIDEO_EMBED_INTERVAL); setInterval(imageUmekomi, WAIT_IMAGE_EMBED_INTERVAL); let ma = $(xa('//input[@placeholder="メールアドレス(省略可)"]')); ma.dblclick(() => { ma.val(ma.val() == "sage" ? "" : "sage"); floatKakikomi2(); }); // 細かい調整 $("div.formbox").css("margin", "0"); $('input[placeholder="メールアドレス(省略可)"]').val(DEFAULT_MAIL_ADDRESS); //$(eleget0('//p/input[@name="mail"]')).css("ime-mode", "inactive"); $("form>p>textarea").click(() => { floatKakikomi2(); }); quote(); }, WAIT); return; function quote() { if (QUOTE_STYLE != "") { elegeta('//div[@class="message"]|//dd').forEach(e => { if (/〉|》|>|>[^>\d]+/m.test(e.textContent)) { e.outerHTML = e.outerHTML.replace(/\s*(((〉|》|>|>)[^>]+))(?!([^<]+)?>)/gmi, `$1`).replace(/
\s*(((〉|》|>|>)[^>]+))(?!([^<]+)?>)/gmi, `
$1`).replace(/
\s*(((〉|》|>|>)[^>]+))(?!([^<]+)?>)/gmi, `
$1`) //notifyMe(e.textContent) } }); // 引用に着色,タグの外側だけ置き換え // これをやるとシステムのサムネ添付が終わる setTimeout(() => { popuponquote() }, location.href.match0(/shitaraba/) ? 2000 : 0) } setTimeout(() => { elegeta('//a[@class="reply_link"]').forEach(e => e.setAttribute("onclick", "return false;")) }, location.href.match0(/shitaraba/) ? 2000 : 0) document.addEventListener("click", c => { let e = c.target.closest(".t5quote,.allpopup,.reply_link"); if (e) { let word = e.textContent.replace(/^〉+|^》+|^>+|^>+/gm, "").trim() let t = (word.match0(/^[0-9-]+$/) && eleget0(`//div[@id="${word?.match0(/^\d+/)?.replace(/post/,"")}"]`)) || elegeta('.message').filter(f => !f.closest(".ch5pu")).find(c => c.textContent.indexOf(word) !== -1); if ($(t).is(":hidden")) $(t.closest(".post")).show(0).css({ "display": "table" }) // 学園祭で消していたら出す t.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" }); $(t.closest(".post")).effect("highlight", 750); } }) } // h抜きのURLをリンクにする function hNukiURLHokan() { // document.querySelectorAll("div.post,dd").forEach(function(obj) { document.querySelectorAll("div.post:not([data-urlcomplemented]),dd:not([data-urlcomplemented])").forEach(function(obj) { var html = obj.innerHTML; if (obj.innerText.match(/^ttps?:\/\//gm)) { var newhtml = html.replace(/[^h](ttps?:\/\/[^<]+)/gm, "$1"); } if (EXPERIMENTAL_COMPLEMENT_YOUTUBE_URL_PARTIAL && obj.innerText.match(/^(youtu\.be\/|www\.youtube\.com\/watch\?v=|www\.youtube\.com\/shorts\/)([a-zA-Z0-9_\-]{11})/gm)) { var newhtml = html.replace(/([^<]+)(youtu\.be\/|www\.youtube\.com\/watch\?v=|www\.youtube\.com\/shorts\/)([a-zA-Z0-9_\-]{11}[^<]*)/gm, "$1$2$3") } if (newhtml) { obj.innerHTML = newhtml; obj.setAttribute("data-urlcomplemented", 1) } }); } function setFloatKakikomi2({ textareaXP = '//form/p/textarea[@name="MESSAGE"]', submitbuttonXP = '//input[@class="submitbtn btn"]', wid = "70%", minwid = 900 } = {}) { var mes = eleget0(textareaXP); if (mes) { mes.addEventListener("input", () => floatKakikomi2({ textareaXP: textareaXP, submitbuttonXP: submitbuttonXP, wid: wid, minwid: minwid })); mes.addEventListener("focus", () => floatKakikomi2({ textareaXP: textareaXP, submitbuttonXP: submitbuttonXP, wid: wid, minwid: minwid })); // floatKakikomi2(textareaXP,submitbuttonXP}) resListen = 1; } } // 書き込み欄調整、クリックでフロート化 function floatKakikomi2({ string = null, addMode = 0, command = "", textareaXP = '//form/p/textarea[@name="MESSAGE"]', submitbuttonXP = '//input[@class="submitbtn btn"]', wid = '70%', minwid = 900 } = {}) { var textarea = eleget0(textareaXP); var submitbutton = eleget0(submitbuttonXP) if (!resFloat) { $(window).resize(() => { $(textarea).css({ "width": wid, "min-width": Math.min(minwid, (window.innerWidth - 100)) + "px", "max-width": (window.innerWidth - 100) + "px" }).attr("wrap", "on").attr("tabIndex", "1"); kakikomiStretch2(textareaXP, "resetHeight") }); } resListen || setFloatKakikomi2() resFloat = true; let curRes = $(textarea).val(); $(textarea).css({ "z-index": "10", "position": "fixed", "right": "1em", "bottom": "3em", "height": "auto" }).attr("tabIndex", "1"); // $(textarea).css({ "width": wid, "min-width": Math.min(minwid, (window.innerWidth - 100)) + "px", "max-width": (window.innerWidth - 100) + "px" }).attr("wrap", "on").attr("tabIndex", "1"); // $(submitbutton).css({ "z-index": "10", "position": "fixed", "right": "1em", "bottom": "0em" }).attr("tabIndex", "2"); $(textarea).css({ "width": wid, "min-width": Math.min(minwid, (window.innerWidth - 100)) + "px", "max-width": (window.innerWidth - 100) + "px" }).attr("wrap", "on").attr("tabIndex", "1").attr("floated", ""); $(submitbutton).css({ "z-index": "10", "position": "fixed", "right": "1em", "bottom": "0em" }).attr("tabIndex", "2").attr("floated", ""); if (string > "") $(textarea).val((addMode ? curRes + ((curRes == "" || curRes.slice(-1) == "\n") ? "" : "\n") : "") + string); $(textarea).focus().attr("stretchabletextarea", "1"); if ((textarea).value == "" || command === "resetHeight") textarea.rows = MINIMUM_ROWS; kakikomiStretch2(textareaXP); } function kakikomiStretch2(xp, command = "") { // if ($(elegeta(xp)).is(":hidden").length) return if ($(elegeta(xp)).is(":hidden")) return let target = eleget0(xp); var targetvalue = target ? target.value : "" if (command === "resetHeight" || targetvalue.length < 100 || targetvalue.match(/\n/gm).length < 5) target.rows = MINIMUM_ROWS; let lineHeight = Number(target.getAttribute("rows")); let height = target.scrollHeight; //+12; let clientHeight = Math.min(document.documentElement.clientHeight, window.innerHeight) - 165; for (let i = 0; i < 90 && (height >= target.offsetHeight) && target.offsetHeight < clientHeight; i++) { lineHeight++; target.setAttribute("rows", lineHeight); } displayLineLimit(target); return target; } function displayLineLimit(target) { let line = target.value.split(/\r\n|\r|\n/).length; if (line_number && message_count) { target.style.backgroundColor = line > line_number * 2 ? "#fff0f0" : (new Blob([target.value]).size) > message_count ? "#fffff0" : "#ffffff"; } } function sortDescendMiddle(array) { return array.sort((a, b) => { return Math.abs(a.getBoundingClientRect().top - document.documentElement.clientHeight / 2) > Math.abs(b.getBoundingClientRect().top - document.documentElement.clientHeight / 2) ? 1 : -1 }); } // 画像と動画をインライン埋め込み function imageUmekomi() { // 画像埋め込み var i = 0; sw1("removeSysThumbs"); for (let a of sortDescendMiddle(elegeta('//a[@imge="af"]/div[@div="thumb5ch"]'))) { if (isinscreen(a)) setTimeout((function(a) { return function() { { a.remove(); } } })(a), WAIT_IMAGE_EMBED_INTERVAL * 3 / NUMBER_IMAGE_EMBED_AT_ONCE) } sw2("removeSysThumbs"); sw1("umegazo") for (let ele of sortDescendMiddle(elegeta('//a[not(@imge)]'))) { let isImg = 0; var url = ele.href || ($(ele).text()); url = url.replace(/^(ttps?:\/\/)/m, "h$1"); try { var urlImg = decodeURIComponent(url.replace(/https?:\/\/jump\.5ch\.net\/\?|https?:\/\/jbbs\.shitaraba\.net\/bbs\/link\.cgi\?url=/, "")) //.replace(/https?:\/\/jbbs\.shitaraba\.net\/bbs\/link\.cgi\?url=/,""); } catch (e) { var urlImg = url.replace(/https?:\/\/jump\.5ch\.net\/\?|https?:\/\/jbbs\.shitaraba\.net\/bbs\/link\.cgi\?url=/, "") } if ($(ele).text().match(/\.jpg|\.jpeg|\.png|\.gif|\.bmp/)) { isImg = 1; } else { isImg = 0; } if (!isImg) ele.setAttribute("imge", "!i"); if ((!isinscreen(ele))) continue; // 画面内に無い if (isImg) { //notifyMe(url)//notifyMe(decodeURIComponent(urlImg)) let next = ele.children ? ele.children[0] : null; if (next && next.tagName === "DIV") { // システムのサムネイルあり if (ALTERNATIVE_THUMBNAIL) next.outerHTML = '
'; ele.setAttribute("imge", "rp"); } else { // if ( /^ttp/.test(ele.textContent)){ // システムのサムネ添付はhtmlに変更があると諦めて中断される $(ele).after($('
')); ele.setAttribute("imge", "af"); } if (++i >= NUMBER_IMAGE_EMBED_AT_ONCE) break; // 一度に設定枚数ずつしかやらない } } sw2("umegazo") }; function videoUmekomi() { sw1("umedouga") // ニコ動埋め込み(PrivacyBadger等は要Disable) for (let ele of sortDescendMiddle(elegeta('//a[contains(@href,"www.nicovideo.jp")][not(@nde)]|//a[contains(@href,"//nico.ms/sm")][not(@nde)]'))) { if ((!isinscreen(ele))) continue; // 画面内に無い let url = ele.innerText.replace(/^ttp/i, "http"); ele.setAttribute("nde", "nde"); var nico = url.match(/h?ttps?:\/\/www.nicovideo.jp\/watch\/(.*)/i); if (!nico) var nico = url.match(/h?https:\/\/nico\.ms\/(.*)/i); if (!nico) continue $(ele).after(`
`) // 埋め込み外部プレイヤー版 break; // 一度に1つずつしかやらない } sw2("umedouga") sw1("umeYT") // youtube埋め込み for (let ele of sortDescendMiddle(elegeta('//a[contains(@href,"youtube.com")][not(@yte)]|//a[contains(@href,"youtu.be")][not(@yte)]'))) { if ((!isinscreen(ele))) continue; // 画面内に無い // let url = ele.innerText; let url = ele.href; ele.setAttribute("yte", "yte"); // var sm = (url.match(/h?ttps?:\/\/youtu\.be\/([^&?]+.*)[\?\&]t=(\d*).*$/i) || url.match(/h?ttps?:\/\/w?w?w?m?\.youtube\.com\/watch\?v=([^&]+.*)&t=(\d*).*$/i)) || url.match(/h?ttps?:\/\/youtu\.be\/([^&?]+)/i) || url.match(/h?ttps?:\/\/w?w?w?m?\.youtube\.com\/watch\?v=([^&]+)/i); //var sm = (url.match(/h?ttps?:\/\/youtu\.be\/([^&?]+.*)[\?\&]t=(\d*).*$/i) || url.match(/h?ttps?:\/\/w?w?w?m?\.youtube\.com\/watch\?v=([^&]+.*)&t=(\d*).*$/i)) || url.match(/h?ttps?:\/\/youtu\.be\/([^&?]+)/i) || url.match(/h?ttps?:\/\/youtube\.com\/shorts\/([^&?]+)/i) || url.match(/h?ttps?:\/\/w?w?w?m?\.youtube\.com\/watch\?v=([^&]+)/i); // var sm = (url.match(/h?ttps?:\/\/youtu\.be\/([a-zA-Z0-9_\-]{11}).*[\?\&]t=(\d*).*$/i) || url.match(/h?ttps?:\/\/w?w?w?m?\.youtube\.com\/watch\?v=([a-zA-Z0-9_\-]{11}).*&t=(\d*).*$/i)) || url.match(/h?ttps?:\/\/youtu\.be\/([a-zA-Z0-9_\-]{11})/i) || url.match(/h?ttps?:\/\/youtube\.com\/shorts\/([a-zA-Z0-9_\-]{11})/i) || url.match(/h?ttps?:\/\/w?w?w?m?\.youtube\.com\/watch\?v=([a-zA-Z0-9_\-]{11})/i); // var sm = (url.match(/h?ttps?:\/\/youtu\.be\/([a-zA-Z0-9_\-]{11}).*[\?\&]t=(\d*).*$/i) || url.match(/h?ttps?:\/\/(?:www\.)?youtube\.com\/watch\?v=([a-zA-Z0-9_\-]{11}).*&t=(\d*).*$/i)) || url.match(/h?ttps?:\/\/youtu\.be\/([a-zA-Z0-9_\-]{11})/i) || url.match(/h?ttps?:\/\/(?:www\.)?youtube\.com\/shorts\/([a-zA-Z0-9_\-]{11})/i) || url.match(/h?ttps?:\/\/(?:www\.)?youtube\.com\/watch\?v=([a-zA-Z0-9_\-]{11})/i); var sm = (url.match(/(?:h?ttps?:\/\/)youtu\.be\/([a-zA-Z0-9_\-]{11}).*[\?\&]t=(\d*).*$/i) || url.match(/(?:h?ttps?:\/\/)(?:www\.)?youtube\.com\/watch\?v=([a-zA-Z0-9_\-]{11}).*&t=(\d*).*$/i)) || url.match(/(?:h?ttps?:\/\/)youtu\.be\/([a-zA-Z0-9_\-]{11})/i) || url.match(/(?:h?ttps?:\/\/)(?:www\.)?youtube\.com\/shorts\/([a-zA-Z0-9_\-]{11})/i) || url.match(/(?:h?ttps?:\/\/)(?:www\.)?youtube\.com\/watch\?v=([a-zA-Z0-9_\-]{11})/i); if (!sm) continue $(ele).after('