// ==UserScript==
// @name GitHub Code Colors
// @version 0.1.1
// @description Userscript that adds a color swatch next to the code color definition
// @license https://creativecommons.org/licenses/by-sa/4.0/
// @namespace http://github.com/Mottie
// @include https://github.com/*
// @grant GM_addStyle
// @run-at document-idle
// @author Rob Garrison
// ==/UserScript==
/* global GM_addStyle */
(function() {
"use strict";
GM_addStyle(".ghcc-block { width:12px; height:12px; display:inline-block; vertical-align:middle; margin-right:4px; border:1px solid #555; }");
var busy = false,
done = false,
addColors = function() {
busy = true;
if (document.querySelector(".highlight")) {
var addNode, loop,
indx = 0,
// #123 or #123456
regexHex = /^#([0-9A-F]{6}|[0-9A-F]{3})$/i,
// rgb(0,0,0) or rgba(0,0,0,0.2)
regexRGB = /^rgba?$/i,
// hsl(0,0%,0%) or hsla(0,0%,0%,0.2);
regexHSL = /^hsla?$/i,
els = document.querySelectorAll(".pl-c1"),
len = els.length,
// don't use a div, because GitHub-Dark adds a :hover background color definition on divs
block = document.createElement("span");
block.className = "ghcc-block";
addNode = function(el, val) {
var node = block.cloneNode();
node.style.backgroundColor = val;
el.insertBefore(node, el.childNodes[0]);
};
loop = function() {
var el, txt, tmp,
// max number of DOM insertions per loop
max = 0;
while ( max < 20 && indx < len ) {
if (indx >= len) { return; }
el = els[indx];
txt = el.textContent;
if (regexHex.test(txt)) {
if (!el.querySelector(".ghcc-block")) {
addNode(el, txt);
max++;
}
} else if (regexRGB.test(txt)) {
if (!el.querySelector(".ghcc-block")) {
addNode(el, txt += "(" + els[++indx].textContent + ")");
max++;
}
} else if (regexHSL.test(txt)) {
if (!el.querySelector(".ghcc-block")) {
tmp = /a$/i.test(txt);
// traverse this HTML... & els only contains the pl-c1 nodes
// <span class="pl-c1">hsl</span>(<span class="pl-c1">1</span>, <span class="pl-c1">1</span><span class="pl-k">%</span>,
// <span class="pl-c1">1</span><span class="pl-k">%</span>);
txt += "(" + els[++indx].textContent + "," + els[++indx].textContent + "%," +
els[++indx].textContent + "%" + (tmp ? "," + els[++indx].textContent : "") + ")";
// sometimes (previews only?) the .pl-k span is nested inside the .pl-c1 span, so we end up with "%%"
addNode(el, txt.replace(/%%/g, "%"));
max++;
}
}
indx++;
}
if (indx < len) {
setTimeout(function(){
loop();
}, 200);
}
};
loop();
done = true;
}
busy = false;
},
targets = document.querySelectorAll("#js-repo-pjax-container, #js-pjax-container, .js-preview-body");
Array.prototype.forEach.call(targets, function(target) {
new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
// preform checks before adding code wrap to minimize function calls
if (done && !busy && mutation.target === target) {
addColors();
}
});
}).observe(target, {
childList: true,
subtree: true
});
});
addColors();
})();