// ==UserScript==
// @name Fxxk GitHub's new UI
// @name:zh-CN 拒绝 GitHub 新 UI
// @namespace Aloxaf
// @version 0.1.18
// @description Move repo information to the top.
// @description:zh-CN 将 repo 信息移动至顶部
// @author Aloxaf
// @match https://github.com/*/*
// @run-at document-start
// ==/UserScript==
// jshint esversion: 6
// GreasyMonkey 4.0+ doesn't support GM_addStyle
// https://stackoverflow.com/questions/23683439/gm-addstyle-equivalent-in-tampermonkey
function GM_addStyle(css) {
const style = document.getElementById("GM_addStyleBy8626") || (function () {
const style = document.createElement('style');
style.type = 'text/css';
style.id = "GM_addStyleBy8626";
document.head.appendChild(style);
return style;
})();
const sheet = style.sheet;
sheet.insertRule(css, (sheet.rules || sheet.cssRules || []).length);
}
function log(e) {
return console.log(e);
}
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, root = document) {
return document.evaluate(s, root, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
function set_about(content) {
log('setting about');
let about = xpath('//h2[text() = "About"]/following-sibling::p[1]');
if (about) {
about.className = "f4";
} else {
about = xpath('//h2[text() = "About"]/following-sibling::div[1]')
}
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) {
log('setting topics');
let topics = xpath('//h3[text() = "Topics"]/following-sibling::div[1]');
if (!topics) {
topics = document.createElement("div");
}
topics.className = "repository-topics-container mt-2 mb-3 js-topics-list-container";
content.insertBefore(topics, content.children[1]);
}
function set_releases(summary) {
log('setting releases');
let tags = xpath('.//a[contains(@href, "/tags")]', summary);
let release_div = xpath('//div[contains(./h2/a/text(), "Releases")]');
let release_cnt;
if (release_div) {
release_cnt = xpath('./h2/a/span', release_div);
}
if (release_cnt) {
release_cnt = release_cnt.textContent;
} else if (xpath('./a', release_div)) {
release_cnt = xpath('./a/span', release_div).textContent;
} else {
release_cnt = "0";
}
if (release_div) {
tags.href = xpath('./h2/a', release_div).href;
} else {
tags.href = tags.href.replace(/tags$/, 'releases')
}
tags.childNodes[3].textContent = release_cnt;
tags.childNodes[4].textContent = " releases ";
}
function set_contributors(summary) {
log('setting contributors');
let contributors = document.createElement('li');
let contri_nums = xpath('//h2/a[contains(text(), "Contributors")]/span/text()'); // ?.textContent ?? 1;
contri_nums = contri_nums ? contri_nums.textContent : 1;
let contri_href = xpath('//h2/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);
}
function set_license(summary) {
log('setting license');
let _license = xpath('//h3[text() = "License"]/following-sibling::div[1]/a');
if (_license) {
let license = document.createElement('li');
license.appendChild(_license);
license.children[0].className = "link-gray-dark no-underline d-inline-block";
summary.appendChild(license);
}
}
function set_languages(content, overall_summary, summary) {
log('setting languages');
let progress = xpath('//h2[text() = "Languages"]/following-sibling::div[1]/span');
if (progress) {
overall_summary.className += " border-bottom-0 mb-0 rounded-bottom-0";
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[2]);
}
}
function set_summary(content) {
log('setting summary');
let overall_summary = document.createElement('div');
overall_summary.className = "overall-summary";
let summary = xpath('//h2[text() = "Git stats"]/following-sibling::ul[1]');
summary.className = "numbers-summary";
set_releases(summary);
set_contributors(summary);
set_license(summary);
overall_summary.appendChild(summary);
content.insertBefore(overall_summary, content.children[1]);
for (let li of summary.childNodes) {
li.className = '';
}
set_languages(content, overall_summary, summary);
}
function is_main_page() {
return /^\/[^/]+\/[^/]+\/?(tree\/[^/]+\/?)?$/.test(window.location.pathname);
}
function fxxk() {
log(`start ${Date.now()}`);
let code = xpath('//a[./span[@data-content="Code"]]');
if (!(/ selected /.test(code.className) && is_main_page())) {
return;
}
let content = $('.repository-content');
set_summary(content);
set_topics(content);
set_about(content);
// Hide new tab
$('.file-navigation').className += " in-mid-page";
$('.repository-content > div > .flex-shrink-0:last-child').style.display = 'none';
content = $('.repository-content > div > .flex-shrink-0');
content.className = content.className.replace('col-md-9', '');
log(`end ${Date.now()}`);
}
function wait_for(condition, callback) {
if (!condition()) {
log('waiting');
window.setTimeout(wait_for.bind(null, condition, callback, 50));
} else {
log('cancel waiting');
callback();
}
}
let style = [`
.Box-header {
padding: 8px 16px !important;
}`,`
.file-navigation.in-mid-page {
margin-top: 16px;
}
`];
(function () {
log('script start');
wait_for(() => document.head, () => {
for (let s of style) {
GM_addStyle(s);
}
});
document.addEventListener('pjax:success', fxxk);
if (is_main_page()) {
wait_for(
() => {
return xpath('//a[./span[@data-content="Code"]]') &&
(xpath('//h2[text() = "About"]/following-sibling::p[1]') ||
xpath('//h2[text() = "About"]/following-sibling::div[1]'))
},
fxxk
)
}
})();