Last active
February 13, 2019 12:16
-
-
Save ZAYEC77/14a2b05db6a1453680411c2019785e48 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var diff = -0.12; | |
async function changeRule(style) { | |
var result = {}; | |
for (var i = 0; i < style.length; i++) { | |
try { | |
var property = style[i]; | |
var value = style[property]; | |
if (!value) { | |
continue; | |
} | |
var colors = getColors(value); | |
var newValue = value; | |
for (var k = 0; k < colors.length; k++) { | |
newValue = newValue.replace(colors[k], getNewColor(colors[k])); | |
} | |
var urls = getUrls(value); | |
for (var k = 0; k < urls.length; k++) { | |
newValue = newValue.replace(urls[k], await getNewUrl(urls[k])); | |
} | |
if (newValue != value) { | |
style[property] = newValue; | |
result[property] = newValue; | |
} | |
} catch (e) { | |
console.error(e); | |
} | |
} | |
return result; | |
} | |
function isEqualColors(c1, c2) { | |
return c1[0] == c2[0] && c1[1] == c2[1] && c1[2] == c2[2]; | |
} | |
async function getNewUrl(value) { | |
var match = value.match(/url\("([+:;,=\/\w-_.]+)"\)/); | |
return new Promise(async function(resolve, reject) { | |
if (!match[1]) { | |
reject(value) | |
} | |
var url = match[1]; | |
try { | |
var img = await loadImage(url); | |
var canvas = document.createElement("canvas"); | |
var ctx = canvas.getContext("2d"); | |
var originalPixels = null; | |
var currentPixels = null; | |
canvas.width = img.naturalWidth; | |
canvas.height = img.naturalHeight; | |
ctx.drawImage(img, 0, 0); | |
ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, img.width, img.height); | |
originalPixels = ctx.getImageData(0, 0, img.naturalWidth, img.naturalHeight); | |
currentPixels = ctx.getImageData(0, 0, img.naturalWidth, img.naturalHeight); | |
var changedPixels = 0; | |
for (var I = 0, L = originalPixels.data.length; I < L; I += 4) { | |
if (currentPixels.data[I + 3] > 0) { | |
var rbg = [originalPixels.data[I], originalPixels.data[I + 1], originalPixels.data[I + 2]]; | |
var newRgb = changeColorTone(rbg); | |
if (!isEqualColors(rbg, newRgb)) { | |
currentPixels.data[I] = newRgb[0]; | |
currentPixels.data[I + 1] = newRgb[1]; | |
currentPixels.data[I + 2] = newRgb[2]; | |
changedPixels++; | |
} | |
} | |
} | |
if (changedPixels == 0) { | |
reject('skip'); | |
} | |
ctx.putImageData(currentPixels, 0, 0); | |
var result = 'url("' + canvas.toDataURL("image/png") + '")'; | |
canvas.remove(); | |
canvas = null; | |
img = null; | |
resolve(result); | |
} catch (e) { | |
reject(e); | |
} | |
}) | |
} | |
async function loadImage(url) { | |
return new Promise(function(resolve, reject) { | |
var image = new Image(1, 1); | |
image.onload = function() { | |
resolve(this); | |
}; | |
image.onerror = function(e) { | |
reject(e); | |
}; | |
image.src = url; | |
}); | |
} | |
function changeColorTone(rgb) { | |
var hsl = rgbToHsl.apply(this, rgb) | |
hsl[0] += diff; | |
return hslToRgb.apply(this, hsl) | |
} | |
function getNewColor(color) { | |
var rgb = getRGB(color); | |
if (rgb.length) { | |
var newRgb = changeColorTone(rgb); | |
var result = ['rgb(', | |
Math.round(newRgb[0]), | |
', ', | |
Math.round(newRgb[1]), | |
', ', | |
Math.round(newRgb[2]), | |
')' | |
].join(''); | |
return result; | |
} | |
return color; | |
} | |
function getColors(value) { | |
return value.match(/rgba?\((\d{1,3}), ?(\d{1,3}), ?(\d{1,3})\)?(?:, ?(\d(?:\.\d?))\))?/g) || []; | |
} | |
function getUrls(value) { | |
return value.match(/url\("([+:;,=\/\w-_.]+)"\)/g) || []; | |
} | |
function getRGB(str) { | |
var match = str.match(/rgba?\((\d{1,3}), ?(\d{1,3}), ?(\d{1,3})\)?(?:, ?(\d(?:\.\d?))\))?/); | |
return match ? [ | |
match[1], | |
match[2], | |
match[3] | |
] : []; | |
} | |
function rgbToHsl(r, g, b) { | |
r /= 255, g /= 255, b /= 255; | |
var max = Math.max(r, g, b), | |
min = Math.min(r, g, b); | |
var h, s, l = (max + min) / 2; | |
if (max == min) { | |
h = s = 0; // achromatic | |
} else { | |
var d = max - min; | |
s = l > 0.5 ? d / (2 - max - min) : d / (max + min); | |
switch (max) { | |
case r: | |
h = (g - b) / d + (g < b ? 6 : 0); | |
break; | |
case g: | |
h = (b - r) / d + 2; | |
break; | |
case b: | |
h = (r - g) / d + 4; | |
break; | |
} | |
h /= 6; | |
} | |
return [h, s, l]; | |
} | |
function hslToRgb(h, s, l) { | |
var r, g, b; | |
if (s == 0) { | |
r = g = b = l; // achromatic | |
} else { | |
function hue2rgb(p, q, t) { | |
if (t < 0) t += 1; | |
if (t > 1) t -= 1; | |
if (t < 1 / 6) return p + (q - p) * 6 * t; | |
if (t < 1 / 2) return q; | |
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; | |
return p; | |
} | |
var q = l < 0.5 ? l * (1 + s) : l + s - l * s; | |
var p = 2 * l - q; | |
r = hue2rgb(p, q, h + 1 / 3); | |
g = hue2rgb(p, q, h); | |
b = hue2rgb(p, q, h - 1 / 3); | |
} | |
return [r * 255, g * 255, b * 255]; | |
} | |
async function main() { | |
var css = readCss(); | |
for (var i = 0; i < document.styleSheets.length; i++) { | |
if (document.styleSheets[i]) { | |
try { | |
for (var j = 0; j < document.styleSheets[i].rules.length; j++) { | |
var rule = document.styleSheets[i].rules[j]; | |
if (rule.selectorText === '.top-menu > ul > li > div.active' || | |
rule.selectorText === '.at-new-basket .icon' || | |
rule.selectorText === '.datatable tr:hover' || | |
rule.selectorText.startsWith('.orderPage .input') | |
) { | |
if (css[rule.selectorText]) { | |
delete css[rule.selectorText]; | |
} | |
continue; | |
} | |
if (document.styleSheets[i].rules[j].style) { | |
var properties = await changeRule(document.styleSheets[i].rules[j].style); | |
if (Object.keys(properties).length) { | |
if (!css[rule.selectorText]) { | |
css[rule.selectorText] = {}; | |
} | |
for (var property in properties) { | |
if (properties[property]) { | |
css[rule.selectorText][property] = properties[property]; | |
} | |
} | |
} | |
} | |
} | |
} catch (e) { | |
console.error(e); | |
} | |
} | |
} | |
var elements = document.getElementsByTagName("*"); | |
for (var i = 0; i < elements.length; i++) { | |
if (elements[i].style) { | |
await changeRule(elements[i].style); | |
} | |
} | |
return css; | |
} | |
function readCss() { | |
return JSON.parse(localStorage.getItem('css')) || {}; | |
} | |
function writeCss(css) { | |
localStorage.setItem('css', JSON.stringify(css)); | |
} | |
function download(filename, text) { | |
var element = document.createElement('a'); | |
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); | |
element.setAttribute('download', filename); | |
element.style.display = 'none'; | |
document.body.appendChild(element); | |
element.click(); | |
document.body.removeChild(element); | |
} | |
function optimizeCss(css) { | |
var images = {}; | |
for (var selector in css) { | |
var rule = css[selector]; | |
for (var property in rule) { | |
var value = rule[property]; | |
if (property == 'background-image' && value.startsWith('url("data:image')) { | |
if (!images[value]) { | |
images[value] = []; | |
} | |
images[value].push(selector); | |
} | |
} | |
} | |
for (var img in images) { | |
var selectors = images[img]; | |
if (selectors.length > 1) { | |
for (var i = 0; i < selectors.length; i++) { | |
delete css[selectors[i]]['background-image']; | |
} | |
css[selectors.join(',')] = { | |
'background-image': img | |
}; | |
} | |
} | |
return css; | |
} | |
(async () => { | |
var css = await main(); | |
css = optimizeCss(css); | |
writeCss(css); | |
var result = []; | |
for (var selector in css) { | |
var rule = css[selector]; | |
result.push(selector); | |
result.push('{\n'); | |
for (var property in rule) { | |
result.push('\t'); | |
result.push(property); | |
result.push(': '); | |
result.push(rule[property]); | |
result.push(';\n'); | |
} | |
result.push('}\n'); | |
} | |
download('styles.css', result.join('')); | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment