GitHub PR File Filter

Hide and mark files as viewed using regex pattern.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         GitHub PR File Filter
// @namespace    btilford
// @author       btilford
// @version      0.1
// @license      MIT
// @description  Hide and mark files as viewed using regex pattern.
// @match        https://github.com/*/*/pull/*/files*
// @grant        unsafeWindow
// ==/UserScript==

(function githubPrFilter() {
    'use strict';
    console.debug('Loading PR file filter');
    function selectFiles(pattern) {
        const regex = new RegExp(pattern);
        const files = [...window.document.querySelectorAll('.file')];
        console.debug('Filtering %d files in PR with pattern %s', files.length, regex);
        return files.filter(_ => {
            const link = _.querySelector('.link-gray-dark');
            return regex.test(link.title) || regex.test(link.innerText);
        });
    }

    const container = unsafeWindow.document.createElement('div');
    container.className = 'select-menu-list';
    container.style = 'width: 280px; margin-bottom: 8px;';

    const pattern = unsafeWindow.document.createElement('input');
    pattern.name = 'filter-pattern';
    pattern.placeholder = 'regex';
    pattern.title = 'File matching regex';
    pattern.className = 'form-control form-control subnav-search-input input-contrast';
    pattern.style = 'margin: 8px 4px; width: 270px;';

    container.appendChild(pattern);


    const btnClasses = 'js-reviewed-toggle ml-2 mr-1 px-2 py-1 rounded-1 f6 text-normal border js-reviewed-file bg-blue-2 border-blue-light';
    const hide = unsafeWindow.document.createElement('button');
    hide.style = 'color: rgb(201, 209, 217);';
    hide.innerHTML = '<label>hide</label>';
    hide.className = btnClasses;
    hide.onclick = () => {
        const ptn = pattern.value;
        const files = selectFiles(ptn);
        console.debug('hiding %d files matching pattern %s', files.length, ptn);
        files.forEach(_ => {
            const open = _.querySelector('.open .file-info button.btn-octicon');
            if(open) {
                open.click();
            }
        });
    }
    container.appendChild(hide);

    const viewed = unsafeWindow.document.createElement('button');
    viewed.style = 'color: rgb(201, 209, 217);';
    viewed.innerHTML = '<label>viewed</label>';
    viewed.className = btnClasses;
    viewed.onclick = () => {
        const ptn = pattern.value;
        const files = selectFiles(ptn);
        console.debug('hiding %d files matching pattern %s', files.length, ptn);
        files.forEach(_ => {
            const unchecked = _.querySelector('.file-actions input.js-reviewed-checkbox:not(:checked)[type=checkbox]');
            if(unchecked) {
                //unchecked.checked = true;
                unchecked.click();
            }
        });
    }
    container.appendChild(viewed);

    const parent = unsafeWindow.document.querySelector('.diffbar-item.details-overlay.select-menu.js-file-filter .select-menu-modal .select-menu-header');
    console.log('Inserting regex filter on %o', parent);
    parent.insertAdjacentElement('afterend', container);

    // Your code here...
})();