Open2ch Find Link Modifier

レス番号リンクのハイフン削除と、安価があればそれも含める修正。表示数(/lXX)を動的に変更。プリセットボタン付き。

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name          Open2ch Find Link Modifier
// @namespace     https://greasyfork.org/ja/users/864059
// @version       0.6
// @description   レス番号リンクのハイフン削除と、安価があればそれも含める修正。表示数(/lXX)を動的に変更。プリセットボタン付き。
// @author        七色の彩り
// @match         https://find.open2ch.net/*
// @icon         https://open2ch.net/favicon.ico
// @grant         none
// @require       https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @license       MIT
// ==/UserScript==

(function() {
    'use strict';

    let targetLValue = localStorage.getItem('open2ch_find_l_value') || '50';
    let observer = null;

    function injectUI() {
        if ($('#l-modifier-container').length) return;
        const customStyle = `<style>
            .l-preset-btn { margin-left: 5px; padding: 2px 6px; font-size: 11px; cursor: pointer; background: #eee; border: 1px solid #ccc; border-radius: 3px; display: inline-block; }
            .l-preset-btn:hover { background: #ddd; }
            #l-modifier-container { margin-top: 0px; display: flex; align-items: center; flex-wrap: wrap; color: #333; }
        </style>`;
        const uiHtml = `
            <div id="l-modifier-container">
                <span style="font-size: 12px; font-weight: bold; margin-right: 5px;">スレタイリンク</span>
                <input type="text" id="l-value-input" class="form-control"
                       value="${targetLValue === 'all' ? '' : targetLValue}"
                       placeholder="${targetLValue === 'all' ? 'ALL' : ''}"
                       style="width: 60px; height: 28px; display: inline-block; text-align: center;">
                <div id="l-presets">
                    <span class="l-preset-btn" data-val="10">l10</span>
                    <span class="l-preset-btn" data-val="30">l30</span>
                    <span class="l-preset-btn" data-val="50">l50</span>
                    <span class="l-preset-btn" data-val="100">l100</span>
                    <span class="l-preset-btn" data-val="all">ALL</span>
                </div>
            </div>`;
        $('head').append(customStyle);
        $('.input-group').after(uiHtml);

        $('#l-value-input').on('input', function() {
            updateLValue($(this).val() === '' ? 'all' : $(this).val());
        });
        $('.l-preset-btn').on('click', function() {
            const val = $(this).data('val');
            $('#l-value-input').val(val === 'all' ? '' : val).attr('placeholder', val === 'all' ? 'ALL' : '');
            updateLValue(val);
        });
    }

    function updateLValue(val) {
        targetLValue = val;
        localStorage.setItem('open2ch_find_l_value', val);
        fixFindLinks();
    }

    function fixFindLinks() {
        // 監視を一時停止して無限ループを防ぐ
        if (observer) observer.disconnect();

        // 1. スレタイおよびli要素の修正
        $('.result .subject a, li.list-group-item[url]').each(function() {
            let attrName = $(this).is('a') ? 'href' : 'url';
            let url = $(this).attr(attrName);
            if (!url || !url.includes('/test/read.cgi/')) return;

            if (!$(this).data('original-url')) $(this).data('original-url', url);

            let base = $(this).data('original-url').replace(/\/l\d+$/, '');
            let newUrl = (targetLValue === 'all') ? base : `${base}/l${targetLValue}`;
            if (url !== newUrl) $(this).attr(attrName, newUrl);
        });

        // 2. レス番号リンクの修正
        $('.result .content .th').each(function() {
            const $th = $(this);
            const $link = $th.find('a').first();
            let href = $link.attr('href');
            if (!href) return;

            if (!$link.data('original-href')) $link.data('original-href', href);

            let newHref = $link.data('original-href').replace(/-$/, '');
            $link.text($link.text().replace(/-$/, ''));

            const thText = $th.text();
            const matches = thText.match(/(?:>>|!aku|!kaijo|!cap|!set|!sub)(\d+)/g);
            if (matches) {
                const nums = matches.map(m => m.match(/\d+/)[0]);
                const uniqueNums = [...new Set(nums)];
                newHref += ',' + uniqueNums.join(',');
            }

            if (href !== newHref) $link.attr('href', newHref);
        });

        // 監視を再開
        if (observer) observer.observe(document.body, { childList: true, subtree: true });
    }

    $(function() {
        injectUI();

        observer = new MutationObserver(function() {
            // UIが消えていれば再注入
            if (!$('#l-modifier-container').length) injectUI();
            fixFindLinks();
        });

        fixFindLinks();
    });

})();