Rewrites imgur image embeds to a rimgo instance
// ==UserScript==
// @name imgur embed rewriter
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Rewrites imgur image embeds to a rimgo instance
// @match *://*/*
// @run-at document-end
// @grant GM_registerMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
(function () {
'use strict';
const defaults = { badge: true, position: 'top-right', style: 'white-shadow', instance: 'https://rimgo.example.com' };
function get(key) { return GM_getValue(key, defaults[key]); }
function getRimgo() { return get('instance').replace(/\/+$/, ''); }
const IMGUR = /https?:\/\/(\w+\.)?imgur\.com\/(\w+)+(\.[a-zA-Z]{3,4})/;
function badgeCSS() {
const positions = {
'top-right': 'top:6px;right:6px;',
'top-left': 'top:6px;left:6px;',
'bottom-right': 'bottom:6px;right:6px;',
'bottom-left': 'bottom:6px;left:6px;',
};
const filters = {
'white-shadow': 'invert(1) drop-shadow(0px 1px 3px rgba(0,0,0,0.9))',
'grey': 'grayscale(1) brightness(1.4) drop-shadow(0px 1px 2px rgba(0,0,0,0.5))',
'dark': 'brightness(0.2) drop-shadow(0px 1px 2px rgba(255,255,255,0.5))',
};
return `position:absolute;${positions[get('position')]}width:18px;height:18px;opacity:0.85;filter:${filters[get('style')]};pointer-events:none;z-index:9999;`;
}
function addBadge(el) {
if (!get('badge') || el.dataset.rimgoBadge) return;
el.dataset.rimgoBadge = '1';
const wrapper = document.createElement('div');
wrapper.style.cssText = 'position:relative;display:inline-block;';
const badge = document.createElement('img');
badge.src = `${getRimgo()}/static/img/rimgo.svg`;
badge.dataset.rimgo = '1';
badge.style.cssText = badgeCSS();
el.parentNode.insertBefore(wrapper, el);
wrapper.appendChild(el);
wrapper.appendChild(badge);
}
function redirectImg(el) {
if (el.dataset.rimgo) return;
if (!IMGUR.test(el.src)) return;
el.dataset.rimgo = '1';
el.src = el.src.replace(/https?:\/\/(\w+\.)?imgur\.com/, getRimgo());
addBadge(el);
}
function walk(root) {
const walker = document.createNodeIterator(
root,
NodeFilter.SHOW_ELEMENT,
node => node.nodeName === 'IMG' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
);
let node;
while ((node = walker.nextNode())) {
redirectImg(node);
}
}
const observer = new MutationObserver(mutations => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node.nodeType !== Node.ELEMENT_NODE) continue;
if (node.nodeName === 'IMG') redirectImg(node);
else walk(node);
}
}
});
walk(document.body);
observer.observe(document.body, { childList: true, subtree: true });
GM_registerMenuCommand(`Instance: ${get('instance')} — change`, () => {
const current = get('instance');
const next = prompt('Enter rimgo instance URL:', current);
if (next && next.trim()) {
GM_setValue('instance', next.trim().replace(/\/+$/, ''));
location.reload();
}
});
GM_registerMenuCommand(`Badge: ${get('badge') ? 'on' : 'off'} — toggle`, () => {
GM_setValue('badge', !get('badge')); location.reload();
});
GM_registerMenuCommand(`Position: ${get('position')} — change`, () => {
const o = ['top-right','top-left','bottom-right','bottom-left'];
GM_setValue('position', o[(o.indexOf(get('position')) + 1) % o.length]); location.reload();
});
GM_registerMenuCommand(`Style: ${get('style')} — change`, () => {
const o = ['white-shadow','grey','dark'];
GM_setValue('style', o[(o.indexOf(get('style')) + 1) % o.length]); location.reload();
});
})();