Fxxk GitHub's new UI

Move repo information to the top.

اعتبارا من 25-06-2020. شاهد أحدث إصدار.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

ستحتاج إلى تثبيت إضافة مثل Stylus لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتتمكن من تثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

(لدي بالفعل مثبت أنماط للمستخدم، دعني أقم بتثبيته!)

// ==UserScript==
// @name         Fxxk GitHub's new UI
// @name:zh-CN   拒绝 GitHub 新 UI
// @namespace    Aloxaf
// @version      0.1.2
// @description  Move repo information to the top.
// @description:zh-CN 将 repo 信息移动至顶部
// @author       Aloxaf
// @match        https://github.com/*/*
// @grant        GM_addStyle
// @run-at       document-start
// ==/UserScript==

// jshint esversion: 6

GM_addStyle(`
.Box-header {
    padding: 8px 16px !important;
}
`);

function $(e) {
    return document.querySelector(e);
}

function rename_node(node, name) {
    let ele = document.createElement(name);
    let old_attrs = node.attributes;
    let new_attrs = ele.attributes;

    for(let i = 0, len = old_attrs.length; i < len; i++) {
        new_attrs.setNamedItem(old_attrs.item(i).cloneNode());
    }

    do {
        ele.appendChild(node.firstChild);
    } while (node.firstChild);

    node.parentNode.replaceChild(ele, node);

    return ele;
}

function xpath(s) {
    return document.evaluate(s, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}

function set_about(content) {
    console.log('setting about');
    let about = xpath('//h2[text() = "About"]/following-sibling::p[1]');
    about.className = "f4";

    let url = xpath('//h2[text() = "About"]/following-sibling::div[1]/span/a');
    if (url) {
        url.innerText = url.href;
        url.removeAttribute('class');
        about.appendChild(url);
    }

    content.insertBefore(about, content.children[1]);
}

function set_topics(content) {
    console.log('setting topics');
    let topics = xpath('//h3[text() = "Topics"]/following-sibling::div[1]');
    topics.className = "repository-topics-container mt-2 mb-3 js-topics-list-container";
    content.insertBefore(topics, content.children[2]);
}

function set_summary(content) {
    console.log('setting summary');
    let overall_summary = document.createElement('div');
    overall_summary.className = "overall-summary border-bottom-0 mb-0 rounded-bottom-0";

    let summary = xpath('//h2[text() = "Git stats"]/following-sibling::ul[1]');
    summary.className = "numbers-summary";

    // Add contributors
    console.log('setting contributors');
    let contributors = document.createElement('li');
    let contri_nums = xpath('//a[contains(text(), "Contributors")]/span/text()'); // ?.textContent ?? 1;
    contri_nums = contri_nums ? contri_nums.textContent : 1;
    let contri_href = xpath('//a[contains(text(), "Contributors")]/@href');
    contri_href = contri_href ? contri_href.value : `//${window.location.host}/${window.location.pathname}/graphs/contributors`;
    contributors.innerHTML = `<a href="${contri_href}">
      <svg class="octicon octicon-organization" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M16 12.999c0 .439-.45 1-1 1H7.995c-.539 0-.994-.447-.995-.999H1c-.54 0-1-.561-1-1 0-2.634 3-4 3-4s.229-.409 0-1c-.841-.621-1.058-.59-1-3 .058-2.419 1.367-3 2.5-3s2.442.58 2.5 3c.058 2.41-.159 2.379-1 3-.229.59 0 1 0 1s1.549.711 2.42 2.088C9.196 9.369 10 8.999 10 8.999s.229-.409 0-1c-.841-.62-1.058-.59-1-3 .058-2.419 1.367-3 2.5-3s2.437.581 2.495 3c.059 2.41-.158 2.38-1 3-.229.59 0 1 0 1s3.005 1.366 3.005 4z"></path></svg>
      <span class="num text-emphasized">
        ${contri_nums}
      </span>
      contributors
    </a>`;
    summary.appendChild(contributors);

    // Add license
    console.log('setting license');
    let license = document.createElement('li');
    license.appendChild(xpath('//h3[text() = "License"]/following-sibling::div[1]/a'));
    license.children[0].className = "link-gray-dark no-underline d-inline-block";
    summary.appendChild(license);

    overall_summary.appendChild(summary);
    content.insertBefore(overall_summary, content.children[3]);

    for (let li of summary.childNodes) {
        li.className = '';
    }

    // Add languages progress
    console.log('setting languages');
    let progress = xpath('//h2[text() = "Languages"]/following-sibling::div[1]/span');
    let languages = document.createElement('div');
    languages.className = 'repository-lang-stats';
    languages.appendChild(rename_node(xpath('//h2[text() = "Languages"]/following-sibling::ul[1]'), 'ol'));
    languages.children[0].className = 'repository-lang-stats-numbers';
    for (let li of languages.children[0].children) {
        li.removeAttribute('class');
        li.children[0].removeAttribute('class');
        let svg = li.children[0].children[0];
        svg = rename_node(svg, "span");
        svg.className = "color-block language-color";
        svg.style.backgroundColor = svg.style.color;
    }
    let details = document.createElement('details');
    details.className = "details-reset";
    summary = document.createElement('summary');
    summary.appendChild(progress);
    details.appendChild(summary);
    details.appendChild(languages);

    content.insertBefore(details, content.children[4]);
}

function fxxk() {
    'use strict';
    let content = $('.repository-content');

    set_about(content);

    set_topics(content);

    set_summary(content);

    // Hide new tab
    $('.file-navigation').className += " in-mid-page";
    $('.repository-content > div > .flex-shrink-0:last-child').style.display = 'hidden';
    content = $('.repository-content > div > .flex-shrink-0');
    content.className = content.className.replace('col-md-9', '');
};

function wait_for(condition, callback) {
    if(!condition()) {
        console.log('waiting');
        window.setTimeout(wait_for.bind(null, condition, callback), 100);
    } else {
        console.log('done');
        callback();
    }
}

(function () {
    'use strict'
    let code = xpath('//a[./span[@data-content="Code"]]');
    if (/ selected /.test(code.className)) {
        fxxk();
    }
    code.addEventListener('click', () => {
        wait_for(() => {
            return xpath('//h2[text() = "About"]/following-sibling::p[1]') &&
                xpath('//h2[text() = "Languages"]/following-sibling::div[1]/span') &&
                xpath('//h3[text() = "Topics"]/following-sibling::div[1]');
        }, fxxk);
    });
})();