Created
April 24, 2019 23:02
-
-
Save tomhodgins/d224a7c5f9fc457c6760836335349916 to your computer and use it in GitHub Desktop.
Run this script with TamperMonkey to use CSSOMTools in the browser console on every website
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
// ==UserScript== | |
// @name CSSOMTools | |
// @namespace cssomtools | |
// @version 1.0 | |
// @description Tools for working with CSS | |
// @homepage https://github.com/tomhodgins/cssomtools | |
// @author Tommy Hodgins | |
// @match *://*/* | |
// ==/UserScript== | |
// Make plugin available as `cssomtools` and `ç` | |
var func = cssomtools = \u00e7 = (function() { | |
function hasRules(object) { return object && object.cssRules && object.cssRules.length; } | |
// Takes a string | |
// Returns a CSSStyleSheet object | |
function parse(string) { | |
string = string || ''; | |
var iframe = document.createElement('iframe'); | |
document.head.appendChild(iframe); | |
var style = iframe.contentDocument.createElement('style'); | |
style.textContent = string; | |
iframe.contentDocument.head.appendChild(style); | |
var stylesheet = iframe.contentDocument.styleSheets[0]; | |
document.head.removeChild(iframe); | |
return stylesheet; | |
} | |
// Takes a CSSStyleSheet or CSSRule object, or an array containing them | |
// Returns the objects passed in after processing with callback function | |
function process(object, callback) { | |
object = object || all(); | |
callback = callback || function(rule) { return rule; }; | |
function readRules(list) { | |
if (hasRules(list)) { | |
Array.prototype.slice.call(list.cssRules).forEach(function(rule) { | |
callback(rule); | |
if (hasRules(rule)) { | |
readRules(rule); | |
} | |
}); | |
} | |
} | |
if (Array.isArray(object)) { | |
object.map(function(child) { return process(child, callback); }); | |
} else { | |
readRules(object); | |
} | |
return object; | |
} | |
// Takes a CSSStyleSheet, CSSRule object, an array containing them, or a string | |
// Returns a stylesheet | |
function add(object, stylesheet, index) { | |
stylesheet = stylesheet || (all().length && all()[all().length - 1]) || parse(); | |
index = index || stylesheet.cssRules.length; | |
if (Array.isArray(object)) { | |
object.forEach(function(child){ return add(child, stylesheet, index) }); | |
} else if (hasRules(object)) { | |
Array.prototype.slice.call(object.cssRules).forEach(function(child){ | |
return add(child, stylesheet, index) | |
}); | |
} else if (object.cssText) { | |
stylesheet.insertRule(object.cssText, index); | |
} else if (typeof object === 'string') { | |
add(parse(object), stylesheet, index) | |
} | |
return stylesheet; | |
} | |
// Takes a CSSStyleSheet or CSSRule object, or an array containing them | |
// Returns the original object, minus all CSSRule objects | |
function remove(object) { | |
object = object || parse(); | |
if (Array.isArray(object)) { | |
object.map(remove); | |
} else if (hasRules(object)) { | |
Array.prototype.slice.call(object.cssRules).map(remove); | |
} else if (object.parentRule) { | |
object.parentRule.deleteRule( | |
Array.prototype.slice.call(object.parentRule.cssRules).indexOf(object) | |
); | |
} else if (object.parentStyleSheet) { | |
object.parentStyleSheet.deleteRule( | |
Array.prototype.slice.call(object.parentStyleSheet.cssRules).indexOf(object) | |
); | |
} | |
return object; | |
} | |
// Takes a CSSStyleSheet or CSSRule object, or an array containing them | |
// Returns a string | |
function stringify(object) { | |
object = object || all(); | |
function stringifyRule(rule) { | |
return rule.cssText || ''; | |
} | |
if (Array.isArray(object)) { | |
return object.map(stringify).join('\n'); | |
} else if (hasRules(object)) { | |
return Array.prototype.slice.call(object.cssRules).map(stringifyRule).join('\n'); | |
} else { | |
return stringifyRule(object); | |
} | |
} | |
// Returns an array of all CSS stylesheets whose cssRules you're allowed to access from document.styleSheets | |
function all() { | |
return Array.prototype.slice.call(document.styleSheets).map(function(stylesheet) { | |
try { stylesheet.cssRules; } | |
catch(error) { return null; } | |
return stylesheet; | |
}).filter(hasRules); | |
} | |
// Takes a CSSStyleSheet and a test function | |
// Returns an object with a cssRules property containing all matching CSSRule objects | |
function filter(stylesheet, test) { | |
stylesheet = stylesheet || parse(); | |
test = test || function(rule) { return rule; }; | |
var output = {cssRules: []}; | |
process( | |
stylesheet, | |
function(rule) { | |
if (test(rule)) { | |
output.cssRules.push(rule); | |
} | |
} | |
); | |
return output; | |
} | |
// Takes a string, and optionally an array of stylesheet objects | |
// Returns an object containing all rules with selectors containing the string | |
function selector(string, option, list) { | |
string = string || ''; | |
option = option || false; | |
list = list || all(); | |
if (list.cssRules) { | |
list = [list]; | |
} | |
return list.map(function(stylesheet) { | |
return filter( | |
stylesheet, | |
function(rule) { | |
if (option) { | |
return rule.selectorText && rule.selectorText.trim() === string; | |
} else { | |
return rule.selectorText && rule.selectorText.indexOf(string) !== -1; | |
} | |
} | |
); | |
}).filter(hasRules); | |
} | |
// Takes a string, and optionally an array of stylesheet objects | |
// Returns an object containing all rules with properties containing the string | |
function property(string, option, list) { | |
string = string || ''; | |
option = option || false; | |
list = list || all(); | |
if (list.cssRules) { | |
list = [list]; | |
} | |
return list.map(function(stylesheet) { | |
return filter( | |
stylesheet, | |
function(rule) { | |
return rule.style && Array.prototype.slice.call(rule.style).some(function(prop) { | |
if (option) { | |
return prop.trim() === string; | |
} else { | |
return prop.indexOf(string) !== -1; | |
} | |
}); | |
} | |
); | |
}).filter(hasRules); | |
} | |
// Takes a string, and optionally an array of stylesheet objects | |
// Returns an object containing all rules with values containing the string | |
function value(string, option, list) { | |
string = string || ''; | |
option = option || false; | |
list = list || all(); | |
if (list.cssRules) { | |
list = [list]; | |
} | |
return list.map(function(stylesheet) { | |
return filter( | |
stylesheet, | |
function(rule) { | |
return rule.style && Array.prototype.slice.call(rule.style).some(function(prop) { | |
if (option) { | |
return rule.style.getPropertyValue(prop).trim() === string; | |
} else { | |
return rule.style.getPropertyValue(prop).indexOf(string) !== -1; | |
} | |
}); | |
} | |
); | |
}).filter(hasRules); | |
} | |
// Takes a string, and optionally an array of stylesheet objects | |
// Returns an object containing all media queries with condition text containing the string | |
function query(string, option, list) { | |
string = string || ''; | |
option = option || false; | |
list = list || all(); | |
if (list.cssRules) { | |
list = [list]; | |
} | |
return list.map(function(stylesheet) { | |
return filter( | |
stylesheet, | |
function(rule) { | |
if (option) { | |
return rule.media && rule.media.mediaText.trim() === string; | |
} else { | |
return rule.media && rule.media.mediaText.indexOf(string) !== -1; | |
} | |
} | |
); | |
}).filter(hasRules); | |
} | |
return { | |
parse: parse, | |
process: process, | |
add: add, | |
remove: remove, | |
stringify: stringify, | |
all: all, | |
filter: filter, | |
selector: selector, | |
property: property, | |
value: value, | |
query: query | |
}; | |
})(); | |
// Make each library function available as a short and long alias | |
var func = i /*nput*/ = parse = cssomtools.parse | |
var func = /*pro*/ c /*ess*/ = process = cssomtools.process | |
var func = /*ad*/ d = add = cssomtools.add | |
var func = r /*emove*/ = remove = cssomtools.remove | |
var func = o /*utput*/ = stringify = cssomtools.stringify | |
var func = a /*ll*/ = all = cssomtools.all | |
var func = f /*ilter*/ = filter = cssomtools.filter | |
var func = s /*elector*/ = selector = cssomtools.selector | |
var func = p /*roperty*/ = property = cssomtools.property | |
var func = v /*alue*/ = value = cssomtools.value | |
var func = q /*uery*/ = query = cssomtools.query |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment