Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
StackExchange Source Highlight: 転載サイトで StackOverflow, SuperUser等のStackExchangeサービスへのリンクをハイライトするUserScriptです(Chrome拡張機能)
// ==UserScript==
// @name StackExchange Source Highlight
// @namespace https://gist.github.com/syusui-s/67a81c0b7357e86b9531746bc84f22ce/
// @version 1.4.0
// @description 転載サイトで StackOverflow, SuperUser等のStackExchangeサービスへのリンクをハイライトします
// @license CC0-1.0
// @author syusui-s
// @match https://codeday.me/*
// @match https://*.coder.work/*
// @match https://www.366service.com/jp/qa/*
// @match https://www.codeflow.site/ja/article/*
// @match https://www.it-swarm-ja.tech/ja/*
// @match https://qastack.jp/*
// @match https://python5.com/*
// @match https://www.py4u.net/discuss/*
// @match https://code.i-harness.com/*
// @match https://stackoverrun.com/*
// @match http://*.uwenku.com/*
// @match https://steakrecords.com/*
// @match https://living-sun.com/*
// @match https://jpcloud.net/q/*
// @match https://*.ojit.com/so/*
// @match https://www.javaer101.com/*
// @match https://www.debugcn.com/*
// @match https://www.fixes.pub/*
// @match https://cloud6.net/*
// @match https://www.it-mure.jp.net/*
// @match https://base64.work/*
// @match https://webdevqa.jp.net/*
// @match https://www.titanwolf.org/*
// @grant none
// @run-at document-end
// @downloadURL https://gist.github.com/syusui-s/67a81c0b7357e86b9531746bc84f22ce/raw/highlight_stackexchange_source.user.js
// @updateURL https://gist.github.com/syusui-s/67a81c0b7357e86b9531746bc84f22ce/raw/highlight_stackexchange_source.user.js
// ==/UserScript==
(function() {
'use strict';
function xPathSelectorAllUnordered(xpath, doc) {
const xPathResult = document.evaluate(xpath, doc, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE);
const results = [];
for (;;) {
const node = xPathResult.iterateNext();
if (node == undefined) break;
results.push(node);
}
return results;
}
const markClass = '__stackexchange_source_highlight__';
const illegalLicenseOrigins = ['https://code.i-harness.com', 'https://living-sun.com/'];
const query = 'a[href^="https://stackoverflow.com/"], a[href^="http://stackoverflow.com/"], a[href*="stackexchange.com/"], a[href^="https://superuser.com/"], a[href^="https://serverfault.com/"]';
const xPathQuery = "//a[contains(text(), '原文') or contains(text(), 'ソース') or contains(text(), 'source') or contains(text(), 'Source')]";
const style = document.createElement('style');
style.textContent = `@keyframes blink { 65% { opacity: 0.0; } }`;
document.head.appendChild(style);
const linkStyle = {
fontSize: '1em',
color: 'red',
animation: 'blink 1s step-end infinite',
textDecoration: 'underline',
fontWeight: 'bold',
fontSize: '1.25em',
};
const sources = [...document.querySelectorAll(query)]
.filter(elem => !elem.classList.contains(markClass))
.filter((elem) => {
// User page should be ignored
if (/\/users\/\d+\/[\w-]+/.test(elem.href)) {
return false;
}
return true;
})
.map((elem) => {
// qastackはリンク先が間違っていることがあるので修正
if (location.host === 'qastack.jp') {
elem.href = elem.href.replace(/^https?:\/\/stackoverflow.com\/\/(.*)$/, '$1');
elem.href = elem.href.replace(/^https?:\/\/qastack.jp\/\w+\/\d+\/(.*)$/, 'https://$1');
elem.href = elem.href.replace(/^(https?:\/\/stackoverflow.com\/)(?!questions)\w+(\/\d+\/.*)$/, '$1questions$2');
}
return elem;
});
[...sources].forEach(elem => {
Object.assign(elem.style, linkStyle);
elem.appendChild(document.createTextNode('(転載元に移動)'));
elem.classList.add(markClass);
});
const maybeSources = [...xPathSelectorAllUnordered(xPathQuery, document)]
.filter(elem => !elem.classList.contains(markClass));
[...maybeSources].forEach(elem => {
Object.assign(elem.style, linkStyle, { color: 'darkorange' });
elem.appendChild(document.createTextNode('(恐らく転載元)'));
elem.classList.add(markClass);
});
const hasSource = (sources.length > 0 || maybeSources.length > 0) && !illegalLicenseOrigins.includes(location.origin);
const warn = document.createElement('div');
Object.assign(warn.style, {
position: 'fixed',
top: 0,
padding: '10px',
fontSize: '16px',
textAlign: 'center',
color: 'red',
background: 'white',
width: '100vw',
border: '5px solid red',
opacity: '0.9',
zIndex: '2147483647',
});
const text = document.createElement('span');
Object.assign(text.style, {
animation: 'blink 1s ease-out infinite',
fontSize: '32px',
fontWeight: 'bold',
});
if (hasSource) {
text.textContent = 'このサイトは転載サイトです。';
} else {
text.textContent = '⚠原典へのリンクが見つかりませんでした。ライセンス違反サイトの可能性があります。';
}
warn.appendChild(text);
const createListFromLink = (el) => {
const li = document.createElement('li');
const link = document.createElement('a');
Object.assign(link, { href: el.href, textContent: el.textContent });
li.appendChild(link);
return li;
};
const sourcesDiv = document.createElement('div');
const sourcesElem = document.createElement('ul');
sourcesDiv.appendChild(document.createTextNode('転載元へのリンク'));
[...sources].map(createListFromLink).forEach((e) => sourcesElem.appendChild(e));
sourcesDiv.appendChild(sourcesElem);
sourcesDiv.appendChild(document.createTextNode('転載元の可能性があるリンク'));
const maybeSourcesElem = document.createElement('ul');
[...maybeSources].map(createListFromLink).forEach((e) => maybeSourcesElem.appendChild(e));
sourcesDiv.appendChild(maybeSourcesElem);
warn.appendChild(sourcesDiv);
const br = document.createElement('br');
warn.appendChild(br);
const back = document.createElement('button');
back.addEventListener('click', () => history.back());
back.textContent = '🔙前のページに戻る';
warn.appendChild(back);
const proceed = document.createElement('button');
proceed.addEventListener('click', () => warn.remove());
proceed.textContent = '➡️閲覧を続ける';
warn.appendChild(proceed);
document.body.appendChild(warn);
})();
code.i-harness.com hard
codeday.me hard
ja.coder.work hard
python5.com hard
qastack.jp hard
stackoverrun.com hard
www.366service.com hard
www.codeflow.site hard
www.it-swarm-ja.tech hard
ja.it-reply.net hard
ja.uwenku.com hard
living-sun.com hard
steakrecords.com hard
jpcloud.net hard
ja.ojit.com hard
www.javaer101.com hard
www.debugcn.com hard
www.py4u.net hard
www.fixes.pub hard
cloud6.net hard
www.it-mure.jp.net hard
base64.work hard
webdevqa.jp.net hard
www.titanwolf.org hard
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment