Last active
May 23, 2019 09:55
-
-
Save joelcardinal/040745aefcf368d39a97911080eb2913 to your computer and use it in GitHub Desktop.
Lists pages stylesheet/inline CSS. Also reports CSS selectors used on page from stylesheet/inline and inline JS.
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
/* | |
TODO: add check for used Font Family, refactor | |
*/ | |
(function getStyleSheetsCssData(){ | |
var styleSheets = document.styleSheets, | |
data = { | |
cssData : { | |
allUsedSelectorText : [] | |
}, | |
jsData : [] | |
}, | |
cssData = data.cssData, | |
jsData = data.jsData, | |
debug = false, | |
debugCount = 0, | |
debugMaxCount = 2000, | |
errorCount = 0, | |
maxErrorCount = 50; | |
// adding inline scripts | |
var scripts = document.querySelectorAll('script'); | |
if(scripts.length){ | |
jsData | |
for(var i=0,len = scripts.length;i<len;i++){ | |
var script = document.querySelectorAll('script')[i]; | |
if( !script.getAttribute('src')){ | |
jsData.push(script.outerHTML); | |
} | |
} | |
} | |
// iterate over all stylesheets | |
for(var ii = 0, lenn = styleSheets.length; ii < lenn; ii++){ | |
var cssFileName; | |
if(!styleSheets[ii].href){ | |
cssFileName = "inline"; | |
}else{ | |
cssFileName = styleSheets[ii].href.split('/').pop(); | |
} | |
if(!styleSheets[ii].rules){ | |
var msg = "Skipping "+cssFileName+", no CSS rules found. Likely the file is over-optimized and missing the last semi-colon of every rule which breaks styleguide API preventing the ability to parse."; | |
console.warn(msg); | |
continue | |
} | |
if(debug){ | |
console.log("Found Stylesheet"); | |
console.log(styleSheets[ii]); | |
console.log("-------"); | |
} | |
if(!cssData[cssFileName]){ | |
cssData[cssFileName] = { | |
styles : { | |
usedSelectorText : [], | |
classes : [], | |
cssText : [], | |
selectorText : [], | |
selectorsToRules : {}, | |
errors : [] | |
}, | |
media : { | |
conditionText : [], | |
usedSelectorText : [], | |
cssText : [] | |
}, | |
fontface : { | |
cssText : [], | |
fontFamily : [] | |
}, | |
keyframes : { | |
cssText : [], | |
name : [] | |
}, | |
supports : { | |
conditionText : [], | |
usedSelectorText : [], | |
cssText : [] | |
}, | |
unknown : [] | |
}; | |
} | |
// iterate over array of stylesheet rules | |
for(var iii = 0, lennn = styleSheets[ii].rules.length;iii<lennn;iii++){ | |
if(debug){ | |
console.log(styleSheets[ii].rules[iii]); | |
} | |
try{ | |
var styleType = Object.getPrototypeOf(styleSheets[ii].rules[iii]).toString(); | |
if( /Style/.test(styleType) ){ | |
// typical rule | |
var cssText = styleSheets[ii].rules[iii].cssText, | |
selectorText = styleSheets[ii].rules[iii].selectorText, | |
rules = styleSheets[ii].rules[iii].style.cssText; | |
// dirty checking for class, starts with "." | |
// could add to other styleTypes but probably not very useful, leaving for now | |
// TODO: evaluate if useful | |
var selectorArray = selectorText.split(','); | |
for(var iiii = 0, lennnn = selectorArray.length;iiii<lennnn;iiii++){ | |
var individualSelectorArray = selectorArray[iiii].split(' '); | |
for(var iiiii = 0, lennnnn = individualSelectorArray.length;iiiii<lennnnn;iiiii++){ | |
var individualSelector = individualSelectorArray[iiiii]; | |
if(/^\./.test(individualSelector) && cssData[cssFileName].styles.classes.indexOf(individualSelector) === -1){ | |
cssData[cssFileName].styles.classes.push(individualSelector); | |
} | |
} | |
} | |
if(document.querySelectorAll(selectorText).length && cssData[cssFileName].styles.usedSelectorText.indexOf(selectorText) === -1){ | |
cssData[cssFileName].styles.usedSelectorText.push(selectorText); | |
if(cssData.allUsedSelectorText.indexOf(selectorText) === -1){ | |
cssData.allUsedSelectorText.push(selectorText); | |
} | |
} | |
cssData[cssFileName].styles.cssText.push(cssText); | |
cssData[cssFileName].styles.selectorText.push(selectorText); | |
// TODO: evaluate if useful, if so, add selectorsToRules to other styleTypes? | |
cssData[cssFileName].styles.selectorsToRules[selectorText] = rules; | |
}else if( /Media/.test(styleType) ){ | |
// media query | |
var conditionText = styleSheets[ii].rules[iii].conditionText, | |
cssText = styleSheets[ii].rules[iii].cssText; | |
cssData[cssFileName].media.conditionText.push(conditionText); | |
cssData[cssFileName].media.cssText.push(cssText); | |
for(var x = 0, xlen = styleSheets[ii].rules[iii].cssRules.length; x < xlen; x++){ | |
var selectorText = styleSheets[ii].rules[iii].cssRules[x].selectorText; | |
if(document.querySelectorAll(selectorText).length && cssData[cssFileName].media.usedSelectorText.indexOf(selectorText) === -1){ | |
cssData[cssFileName].media.usedSelectorText.push(selectorText); | |
if(cssData.allUsedSelectorText.indexOf(selectorText) === -1){ | |
cssData.allUsedSelectorText.push(selectorText); | |
} | |
} | |
} | |
}else if( /FontFace/.test(styleType) ){ | |
// font face | |
var cssText = styleSheets[ii].rules[iii].cssText, | |
fontFamily = styleSheets[ii].rules[iii].style.fontFamily; | |
cssData[cssFileName].fontface.cssText.push(cssText); | |
cssData[cssFileName].fontface.fontFamily.push(fontFamily); | |
}else if( /Keyframes/.test(styleType) ){ | |
// keyframe | |
var cssText = styleSheets[ii].rules[iii].cssText, | |
keyName = styleSheets[ii].rules[iii].name; | |
cssData[cssFileName].keyframes.cssText.push(cssText); | |
cssData[cssFileName].keyframes.name.push(keyName); | |
}else if( /Supports/.test(styleType) ){ | |
// supports | |
var conditionText = styleSheets[ii].rules[iii].conditionText, | |
cssText = styleSheets[ii].rules[iii].cssText; | |
cssData[cssFileName].supports.conditionText.push(conditionText); | |
cssData[cssFileName].supports.cssText.push(cssText); | |
for(var xx = 0, xxlen = styleSheets[ii].rules[iii].cssRules.length; xx < xxlen; xx++){ | |
var selectorText = styleSheets[ii].rules[iii].cssRules[xx].selectorText; | |
if(document.querySelectorAll(selectorText).length && cssData[cssFileName].supports.usedSelectorText.indexOf(selectorText) === -1){ | |
cssData[cssFileName].supports.usedSelectorText.push(selectorText); | |
if(cssData.allUsedSelectorText.indexOf(selectorText) === -1){ | |
cssData.allUsedSelectorText.push(selectorText); | |
} | |
} | |
} | |
}else{ | |
if(debug){ | |
console.log('UNKNOWN STYLETYPE'); | |
console.log(styleType); | |
console.log(styleSheets[ii].rules[iii]); | |
cssData[cssFileName].unknown.push(styleSheets[ii].rules[iii]); | |
} | |
} | |
}catch(e){ | |
if(debug){ | |
console.log('ERROR'); | |
console.log(e); | |
console.log(styleSheets[ii].rules[iii]); | |
} | |
errorCount ++ | |
if(errorCount === maxErrorCount){ | |
// There could be a lot of errors, so we'll exit early | |
console.log("MAX ERROR COUNT REACHED"); | |
return | |
} | |
} | |
debugCount ++ | |
if(debug && debugCount === debugMaxCount){return} | |
} | |
} | |
console.log("DATA:"); | |
//console.log(Data); | |
return data; | |
}()); | |
/* | |
function getAllPageCss(){ | |
// dirty checking for class starts with "." in it | |
// TODO: evaluate if useful | |
var allElements = document.querySelectorAll('*'), | |
classes = []; | |
for(var i = 0, len = allElements.length;i<len;i++){ | |
var element = allElements[i]; | |
if(element.classList && element.classList.value){ | |
var classListArray = element.classList.value.split(' '); | |
for(var ii = 0, lenn = classListArray.length;ii<lenn;ii++){ | |
classes.push(classListArray[ii]); | |
} | |
} | |
} | |
console.log("getAllPageCss - classes"); | |
console.log(classes); | |
return classes; | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment