diff --git a/Recipe.min.js b/Recipe.min.js index 73db83a..ba37864 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -437,63 +437,63 @@ function getPatternUsage(results, domClasses, cssClasses) { return results; } -void function() { - - window.HtmlUsage = {}; - - // This function has been added to the elementAnalyzers in - // CSSUsage.js under onready() - // is an HTMLElement passed in by elementAnalyzers - window.HtmlUsage.GetNodeName = function (element) { - - // If the browser doesn't recognize the element - throw it away - if(element instanceof HTMLUnknownElement) { - return; - } - - var node = element.nodeName; - - var tags = HtmlUsageResults.tags || (HtmlUsageResults.tags = {}); - var tag = tags[node] || (tags[node] = 0); - tags[node]++; - - GetAttributes(element, node); - } - - function GetAttributes(element, node) { - for(var i = 0; i < element.attributes.length; i++) { - var att = element.attributes[i]; - - if(IsValidAttribute(element, att.nodeName)) { - var attributes = HtmlUsageResults.attributes || (HtmlUsageResults.attributes = {}); - var attribute = attributes[att.nodeName] || (attributes[att.nodeName] = {}); - var attributeTag = attribute[node] || (attribute[node] = {count: 0}); - attributeTag.count++; - } - } - } - - function IsValidAttribute(element, attname) { - // We need to convert className - if(attname == "class") { - attname = "className"; - } - - if(attname == "classname") { - return false; - } - - // Only keep attributes that are not data - if(attname.indexOf('data-') != -1) { - return false; - } - - if(typeof(element[attname]) == "undefined") { - return false; - } - - return true; - } +void function() { + + window.HtmlUsage = {}; + + // This function has been added to the elementAnalyzers in + // CSSUsage.js under onready() + // is an HTMLElement passed in by elementAnalyzers + window.HtmlUsage.GetNodeName = function (element) { + + // If the browser doesn't recognize the element - throw it away + if(element instanceof HTMLUnknownElement) { + return; + } + + var node = element.nodeName; + + var tags = HtmlUsageResults.tags || (HtmlUsageResults.tags = {}); + var tag = tags[node] || (tags[node] = 0); + tags[node]++; + + GetAttributes(element, node); + } + + function GetAttributes(element, node) { + for(var i = 0; i < element.attributes.length; i++) { + var att = element.attributes[i]; + + if(IsValidAttribute(element, att.nodeName)) { + var attributes = HtmlUsageResults.attributes || (HtmlUsageResults.attributes = {}); + var attribute = attributes[att.nodeName] || (attributes[att.nodeName] = {}); + var attributeTag = attribute[node] || (attribute[node] = {count: 0}); + attributeTag.count++; + } + } + } + + function IsValidAttribute(element, attname) { + // We need to convert className + if(attname == "class") { + attname = "className"; + } + + if(attname == "classname") { + return false; + } + + // Only keep attributes that are not data + if(attname.indexOf('data-') != -1) { + return false; + } + + if(typeof(element[attname]) == "undefined") { + return false; + } + + return true; + } }(); void function() { try { @@ -1099,7 +1099,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName) { + function createValueArray(value, propertyName, stripUrlValue) { // Trim value on the edges value = value.trim(); @@ -1119,10 +1119,15 @@ void function() { try { value = value.replace(/('|‘|’|")/g, ""); } + // Collapse whitespace + value = value.trim().replace(/\s+/g, " "); + // Divide at commas to separate different font names value = value.split(/\s*,\s*/g); + + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/g); return value; - case '--var': // Replace strings by dummies @@ -1132,7 +1137,7 @@ void function() { try { // Replace url(...) functions by dummies value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - + // Remove group contents (...), {...} and [...] value = value.replace(/[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, " "); value = value.replace(/[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, " "); @@ -1140,28 +1145,37 @@ void function() { try { value = value.replace(/[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]*)[}])*[}])*[}])*[}])*[}]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); - break; default: - - // Replace strings by dummies - value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // Replace url(...) functions by dummies - if (value.indexOf("(") != -1) { - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + // Don't divide commas and spaces if we want the inside of Url values + if (stripUrlValue){ + // Replace strings by dummies + value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') + .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + + // Replace url(...) functions by dummies + if (value.indexOf("(") != -1) { + value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + } + + // Collapse whitespace + value = value.trim().replace(/\s+/g, " "); + + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/g); } - } - // Collapse whitespace - value = value.trim().replace(/\s+/g, " "); - - // Divide at commas and spaces to separate different values - value = value.split(/\s*(?:,|[/])\s*|\s+/g); + + // This fixes a bug where there is only one item and it's not split by the value.split + // What ends up happening is that this function returns a string, not an array. + // This causes an issue because when we do .length in the for loop after this, it returns the length of the string, not the array. + if( typeof value === 'string' ) { + value = [ value ]; + } return value; } @@ -1346,7 +1360,8 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); + var stripUrlValue = true; + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue, normalizedKey, stripUrlValue); var values = new Array(); for(var j = specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); @@ -1778,214 +1793,214 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* - RECIPE: z-index on static flex items - ------------------------------------------------------------- - Author: Francois Remy - Description: Get count of flex items who should create a stacking context but do not really -*/ - -void function() { - - window.CSSUsage.StyleWalker.recipesToRun.push( function zstaticflex(/*HTML DOM Element*/ element, results) { - if(!element.parentElement) return; - - // the problem happens if the element is a flex item with static position and non-auto z-index - if(getComputedStyle(element.parentElement).display != 'flex') return results; - if(getComputedStyle(element).position != 'static') return results; - if(getComputedStyle(element).zIndex != 'auto') { - results.likely = 1; - } - - // the problem might happen if z-index could ever be non-auto - if(element.CSSUsage["z-index"] && element.CSSUsage["z-index"].valuesArray.length > 0) { - results.possible = 1; - } - - }); -}(); - -// -// This file is only here to create the TSV -// necessary to collect the data from the crawler -// -void function() { - - /* String hash function - /* credits goes to http://erlycoder.com/49/javascript-hash-functions-to-convert-string-into-integer-hash- */ - const hashCodeOf = (str) => { - var hash = 5381; var char = 0; - for (var i = 0; i < str.length; i++) { - char = str.charCodeAt(i); - hash = ((hash << 5) + hash) + char; - } - return hash; - } - - var ua = navigator.userAgent; - var uaName = ua.indexOf('Edge')>=0 ? 'EDGE' :ua.indexOf('Chrome')>=0 ? 'CHROME' : 'FIREFOX'; - window.INSTRUMENTATION_RESULTS = { - UA: uaName, - UASTRING: ua, - UASTRING_HASH: hashCodeOf(ua), - URL: location.href, - TIMESTAMP: Date.now(), - css: {/* see CSSUsageResults */}, - html: {/* see HtmlUsageResults */}, - dom: {}, - scripts: {/* "bootstrap.js": 1 */}, - }; - window.INSTRUMENTATION_RESULTS_TSV = []; - - /* make the script work in the context of a webview */ - try { - var console = window.console || (window.console={log:function(){},warn:function(){},error:function(){}}); - console.unsafeLog = console.log; - console.log = function() { - try { - this.unsafeLog.apply(this,arguments); - } catch(ex) { - // ignore - } - }; - } catch (ex) { - // we tried... - } -}(); - -window.onCSSUsageResults = function onCSSUsageResults(CSSUsageResults) { - // Collect the results (css) - INSTRUMENTATION_RESULTS.css = CSSUsageResults; - INSTRUMENTATION_RESULTS.html = HtmlUsageResults; - INSTRUMENTATION_RESULTS.recipe = RecipeResults; - - // Convert it to a more efficient format - INSTRUMENTATION_RESULTS_TSV = convertToTSV(INSTRUMENTATION_RESULTS); - - // Remove tabs and new lines from the data - for(var i = INSTRUMENTATION_RESULTS_TSV.length; i--;) { - var row = INSTRUMENTATION_RESULTS_TSV[i]; - for(var j = row.length; j--;) { - row[j] = (''+row[j]).replace(/(\s|\r|\n)+/g, ' '); - } - } - - // Convert into one signle tsv file - var tsvString = INSTRUMENTATION_RESULTS_TSV.map((row) => (row.join('\t'))).join('\n'); - appendTSV(tsvString); - - // Add it to the document dom - function appendTSV(content) { - if(window.debugCSSUsage) console.log("Trying to append"); - var output = document.createElement('script'); - output.id = "css-usage-tsv-results"; - output.textContent = tsvString; - output.type = 'text/plain'; - document.querySelector('head').appendChild(output); - var successfulAppend = checkAppend(); - } - - function checkAppend() { - if(window.debugCSSUsage) if(window.debugCSSUsage) console.log("Checking append"); - var elem = document.getElementById('css-usage-tsv-results'); - if(elem === null) { - if(window.debugCSSUsage) console.log("Element not appended"); - if(window.debugCSSUsage) console.log("Trying to append again"); - appendTSV(); - } - else { - if(window.debugCSSUsage) console.log("Element successfully found"); - } - } - - /** convert the instrumentation results to a spreadsheet for analysis */ - function convertToTSV(INSTRUMENTATION_RESULTS) { - if(window.debugCSSUsage) console.log("Converting to TSV"); - - var VALUE_COLUMN = 4; - var finishedRows = []; - var currentRowTemplate = [ - INSTRUMENTATION_RESULTS.UA, - INSTRUMENTATION_RESULTS.UASTRING_HASH, - INSTRUMENTATION_RESULTS.URL, - INSTRUMENTATION_RESULTS.TIMESTAMP, - 0 - ]; - - currentRowTemplate.push('ua'); - convertToTSV({identifier: INSTRUMENTATION_RESULTS.UASTRING}); - currentRowTemplate.pop(); - - - - - - - - - - - currentRowTemplate.push('recipe'); - convertToTSV(INSTRUMENTATION_RESULTS['recipe']); - currentRowTemplate.pop(); - - var l = finishedRows[0].length; - finishedRows.sort((a,b) => { - for(var i = VALUE_COLUMN+1; ib[i]) return +1; - } - return 0; - }); - - return finishedRows; - - /** helper function doing the actual conversion */ - function convertToTSV(object) { - if(object==null || object==undefined || typeof object == 'number' || typeof object == 'string') { - finishedRows.push(new Row(currentRowTemplate, ''+object)); - } else { - for(var key in object) { - if({}.hasOwnProperty.call(object,key)) { - currentRowTemplate.push(key); - convertToTSV(object[key]); - currentRowTemplate.pop(); - } - } - } - } - - /** constructor for a row of our table */ - function Row(currentRowTemplate, value) { - - // Initialize an empty row with enough columns - var row = [ - /*UANAME: edge */'', - /*UASTRING: mozilla/5.0 (...) */'', - /*URL: http://.../... */'', - /*TIMESTAMP: 1445622257303 */'', - /*VALUE: 0|1|... */'', - /*DATATYPE: css|dom|html... */'', - /*SUBTYPE: props|types|api|... */'', - /*NAME: font-size|querySelector|... */'', - /*CONTEXT: count|values|... */'', - /*SUBCONTEXT: px|em|... */'', - /*... */'', - /*... */'', - ]; - - // Copy the column values from the template - for(var i = currentRowTemplate.length; i--;) { - row[i] = currentRowTemplate[i]; - } - - // Add the value to the row - row[VALUE_COLUMN] = value; - - return row; - } - - } +/* + RECIPE: z-index on static flex items + ------------------------------------------------------------- + Author: Francois Remy + Description: Get count of flex items who should create a stacking context but do not really +*/ + +void function() { + + window.CSSUsage.StyleWalker.recipesToRun.push( function zstaticflex(/*HTML DOM Element*/ element, results) { + if(!element.parentElement) return; + + // the problem happens if the element is a flex item with static position and non-auto z-index + if(getComputedStyle(element.parentElement).display != 'flex') return results; + if(getComputedStyle(element).position != 'static') return results; + if(getComputedStyle(element).zIndex != 'auto') { + results.likely = 1; + } + + // the problem might happen if z-index could ever be non-auto + if(element.CSSUsage["z-index"] && element.CSSUsage["z-index"].valuesArray.length > 0) { + results.possible = 1; + } + + }); +}(); + +// +// This file is only here to create the TSV +// necessary to collect the data from the crawler +// +void function() { + + /* String hash function + /* credits goes to http://erlycoder.com/49/javascript-hash-functions-to-convert-string-into-integer-hash- */ + const hashCodeOf = (str) => { + var hash = 5381; var char = 0; + for (var i = 0; i < str.length; i++) { + char = str.charCodeAt(i); + hash = ((hash << 5) + hash) + char; + } + return hash; + } + + var ua = navigator.userAgent; + var uaName = ua.indexOf('Edge')>=0 ? 'EDGE' :ua.indexOf('Chrome')>=0 ? 'CHROME' : 'FIREFOX'; + window.INSTRUMENTATION_RESULTS = { + UA: uaName, + UASTRING: ua, + UASTRING_HASH: hashCodeOf(ua), + URL: location.href, + TIMESTAMP: Date.now(), + css: {/* see CSSUsageResults */}, + html: {/* see HtmlUsageResults */}, + dom: {}, + scripts: {/* "bootstrap.js": 1 */}, + }; + window.INSTRUMENTATION_RESULTS_TSV = []; + + /* make the script work in the context of a webview */ + try { + var console = window.console || (window.console={log:function(){},warn:function(){},error:function(){}}); + console.unsafeLog = console.log; + console.log = function() { + try { + this.unsafeLog.apply(this,arguments); + } catch(ex) { + // ignore + } + }; + } catch (ex) { + // we tried... + } +}(); + +window.onCSSUsageResults = function onCSSUsageResults(CSSUsageResults) { + // Collect the results (css) + INSTRUMENTATION_RESULTS.css = CSSUsageResults; + INSTRUMENTATION_RESULTS.html = HtmlUsageResults; + INSTRUMENTATION_RESULTS.recipe = RecipeResults; + + // Convert it to a more efficient format + INSTRUMENTATION_RESULTS_TSV = convertToTSV(INSTRUMENTATION_RESULTS); + + // Remove tabs and new lines from the data + for(var i = INSTRUMENTATION_RESULTS_TSV.length; i--;) { + var row = INSTRUMENTATION_RESULTS_TSV[i]; + for(var j = row.length; j--;) { + row[j] = (''+row[j]).replace(/(\s|\r|\n)+/g, ' '); + } + } + + // Convert into one signle tsv file + var tsvString = INSTRUMENTATION_RESULTS_TSV.map((row) => (row.join('\t'))).join('\n'); + appendTSV(tsvString); + + // Add it to the document dom + function appendTSV(content) { + if(window.debugCSSUsage) console.log("Trying to append"); + var output = document.createElement('script'); + output.id = "css-usage-tsv-results"; + output.textContent = tsvString; + output.type = 'text/plain'; + document.querySelector('head').appendChild(output); + var successfulAppend = checkAppend(); + } + + function checkAppend() { + if(window.debugCSSUsage) if(window.debugCSSUsage) console.log("Checking append"); + var elem = document.getElementById('css-usage-tsv-results'); + if(elem === null) { + if(window.debugCSSUsage) console.log("Element not appended"); + if(window.debugCSSUsage) console.log("Trying to append again"); + appendTSV(); + } + else { + if(window.debugCSSUsage) console.log("Element successfully found"); + } + } + + /** convert the instrumentation results to a spreadsheet for analysis */ + function convertToTSV(INSTRUMENTATION_RESULTS) { + if(window.debugCSSUsage) console.log("Converting to TSV"); + + var VALUE_COLUMN = 4; + var finishedRows = []; + var currentRowTemplate = [ + INSTRUMENTATION_RESULTS.UA, + INSTRUMENTATION_RESULTS.UASTRING_HASH, + INSTRUMENTATION_RESULTS.URL, + INSTRUMENTATION_RESULTS.TIMESTAMP, + 0 + ]; + + currentRowTemplate.push('ua'); + convertToTSV({identifier: INSTRUMENTATION_RESULTS.UASTRING}); + currentRowTemplate.pop(); + + + + + + + + + + + currentRowTemplate.push('recipe'); + convertToTSV(INSTRUMENTATION_RESULTS['recipe']); + currentRowTemplate.pop(); + + var l = finishedRows[0].length; + finishedRows.sort((a,b) => { + for(var i = VALUE_COLUMN+1; ib[i]) return +1; + } + return 0; + }); + + return finishedRows; + + /** helper function doing the actual conversion */ + function convertToTSV(object) { + if(object==null || object==undefined || typeof object == 'number' || typeof object == 'string') { + finishedRows.push(new Row(currentRowTemplate, ''+object)); + } else { + for(var key in object) { + if({}.hasOwnProperty.call(object,key)) { + currentRowTemplate.push(key); + convertToTSV(object[key]); + currentRowTemplate.pop(); + } + } + } + } + + /** constructor for a row of our table */ + function Row(currentRowTemplate, value) { + + // Initialize an empty row with enough columns + var row = [ + /*UANAME: edge */'', + /*UASTRING: mozilla/5.0 (...) */'', + /*URL: http://.../... */'', + /*TIMESTAMP: 1445622257303 */'', + /*VALUE: 0|1|... */'', + /*DATATYPE: css|dom|html... */'', + /*SUBTYPE: props|types|api|... */'', + /*NAME: font-size|querySelector|... */'', + /*CONTEXT: count|values|... */'', + /*SUBCONTEXT: px|em|... */'', + /*... */'', + /*... */'', + ]; + + // Copy the column values from the template + for(var i = currentRowTemplate.length; i--;) { + row[i] = currentRowTemplate[i]; + } + + // Add the value to the row + row[VALUE_COLUMN] = value; + + return row; + } + + } }; // // Execution scheduler: diff --git a/cssUsage.src.js b/cssUsage.src.js index 000bc3d..64f89ff 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -437,63 +437,63 @@ function getPatternUsage(results, domClasses, cssClasses) { return results; } -void function() { - - window.HtmlUsage = {}; - - // This function has been added to the elementAnalyzers in - // CSSUsage.js under onready() - // is an HTMLElement passed in by elementAnalyzers - window.HtmlUsage.GetNodeName = function (element) { - - // If the browser doesn't recognize the element - throw it away - if(element instanceof HTMLUnknownElement) { - return; - } - - var node = element.nodeName; - - var tags = HtmlUsageResults.tags || (HtmlUsageResults.tags = {}); - var tag = tags[node] || (tags[node] = 0); - tags[node]++; - - GetAttributes(element, node); - } - - function GetAttributes(element, node) { - for(var i = 0; i < element.attributes.length; i++) { - var att = element.attributes[i]; - - if(IsValidAttribute(element, att.nodeName)) { - var attributes = HtmlUsageResults.attributes || (HtmlUsageResults.attributes = {}); - var attribute = attributes[att.nodeName] || (attributes[att.nodeName] = {}); - var attributeTag = attribute[node] || (attribute[node] = {count: 0}); - attributeTag.count++; - } - } - } - - function IsValidAttribute(element, attname) { - // We need to convert className - if(attname == "class") { - attname = "className"; - } - - if(attname == "classname") { - return false; - } - - // Only keep attributes that are not data - if(attname.indexOf('data-') != -1) { - return false; - } - - if(typeof(element[attname]) == "undefined") { - return false; - } - - return true; - } +void function() { + + window.HtmlUsage = {}; + + // This function has been added to the elementAnalyzers in + // CSSUsage.js under onready() + // is an HTMLElement passed in by elementAnalyzers + window.HtmlUsage.GetNodeName = function (element) { + + // If the browser doesn't recognize the element - throw it away + if(element instanceof HTMLUnknownElement) { + return; + } + + var node = element.nodeName; + + var tags = HtmlUsageResults.tags || (HtmlUsageResults.tags = {}); + var tag = tags[node] || (tags[node] = 0); + tags[node]++; + + GetAttributes(element, node); + } + + function GetAttributes(element, node) { + for(var i = 0; i < element.attributes.length; i++) { + var att = element.attributes[i]; + + if(IsValidAttribute(element, att.nodeName)) { + var attributes = HtmlUsageResults.attributes || (HtmlUsageResults.attributes = {}); + var attribute = attributes[att.nodeName] || (attributes[att.nodeName] = {}); + var attributeTag = attribute[node] || (attribute[node] = {count: 0}); + attributeTag.count++; + } + } + } + + function IsValidAttribute(element, attname) { + // We need to convert className + if(attname == "class") { + attname = "className"; + } + + if(attname == "classname") { + return false; + } + + // Only keep attributes that are not data + if(attname.indexOf('data-') != -1) { + return false; + } + + if(typeof(element[attname]) == "undefined") { + return false; + } + + return true; + } }(); void function() { try { @@ -1099,7 +1099,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName) { + function createValueArray(value, propertyName, stripUrlValue) { // Trim value on the edges value = value.trim(); @@ -1119,10 +1119,15 @@ void function() { try { value = value.replace(/('|‘|’|")/g, ""); } + // Collapse whitespace + value = value.trim().replace(/\s+/g, " "); + // Divide at commas to separate different font names value = value.split(/\s*,\s*/g); + + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/g); return value; - case '--var': // Replace strings by dummies @@ -1132,7 +1137,7 @@ void function() { try { // Replace url(...) functions by dummies value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - + // Remove group contents (...), {...} and [...] value = value.replace(/[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, " "); value = value.replace(/[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, " "); @@ -1140,28 +1145,37 @@ void function() { try { value = value.replace(/[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]*)[}])*[}])*[}])*[}])*[}]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); - break; default: - - // Replace strings by dummies - value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // Replace url(...) functions by dummies - if (value.indexOf("(") != -1) { - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + // Don't divide commas and spaces if we want the inside of Url values + if (stripUrlValue){ + // Replace strings by dummies + value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') + .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + + // Replace url(...) functions by dummies + if (value.indexOf("(") != -1) { + value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + } + + // Collapse whitespace + value = value.trim().replace(/\s+/g, " "); + + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/g); } - } - // Collapse whitespace - value = value.trim().replace(/\s+/g, " "); - - // Divide at commas and spaces to separate different values - value = value.split(/\s*(?:,|[/])\s*|\s+/g); + + // This fixes a bug where there is only one item and it's not split by the value.split + // What ends up happening is that this function returns a string, not an array. + // This causes an issue because when we do .length in the for loop after this, it returns the length of the string, not the array. + if( typeof value === 'string' ) { + value = [ value ]; + } return value; } @@ -1346,7 +1360,8 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); + var stripUrlValue = true; + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue, normalizedKey, stripUrlValue); var values = new Array(); for(var j = specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); @@ -1778,217 +1793,217 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* - RECIPE: z-index on static flex items - ------------------------------------------------------------- - Author: Francois Remy - Description: Get count of flex items who should create a stacking context but do not really -*/ - -void function() { - - window.CSSUsage.StyleWalker.recipesToRun.push( function zstaticflex(/*HTML DOM Element*/ element, results) { - if(!element.parentElement) return; - - // the problem happens if the element is a flex item with static position and non-auto z-index - if(getComputedStyle(element.parentElement).display != 'flex') return results; - if(getComputedStyle(element).position != 'static') return results; - if(getComputedStyle(element).zIndex != 'auto') { - results.likely = 1; - } - - // the problem might happen if z-index could ever be non-auto - if(element.CSSUsage["z-index"] && element.CSSUsage["z-index"].valuesArray.length > 0) { - results.possible = 1; - } - - }); -}(); - -// -// This file is only here to create the TSV -// necessary to collect the data from the crawler -// -void function() { - - /* String hash function - /* credits goes to http://erlycoder.com/49/javascript-hash-functions-to-convert-string-into-integer-hash- */ - const hashCodeOf = (str) => { - var hash = 5381; var char = 0; - for (var i = 0; i < str.length; i++) { - char = str.charCodeAt(i); - hash = ((hash << 5) + hash) + char; - } - return hash; - } - - var ua = navigator.userAgent; - var uaName = ua.indexOf('Edge')>=0 ? 'EDGE' :ua.indexOf('Chrome')>=0 ? 'CHROME' : 'FIREFOX'; - window.INSTRUMENTATION_RESULTS = { - UA: uaName, - UASTRING: ua, - UASTRING_HASH: hashCodeOf(ua), - URL: location.href, - TIMESTAMP: Date.now(), - css: {/* see CSSUsageResults */}, - html: {/* see HtmlUsageResults */}, - dom: {}, - scripts: {/* "bootstrap.js": 1 */}, - }; - window.INSTRUMENTATION_RESULTS_TSV = []; - - /* make the script work in the context of a webview */ - try { - var console = window.console || (window.console={log:function(){},warn:function(){},error:function(){}}); - console.unsafeLog = console.log; - console.log = function() { - try { - this.unsafeLog.apply(this,arguments); - } catch(ex) { - // ignore - } - }; - } catch (ex) { - // we tried... - } -}(); - -window.onCSSUsageResults = function onCSSUsageResults(CSSUsageResults) { - // Collect the results (css) - INSTRUMENTATION_RESULTS.css = CSSUsageResults; - INSTRUMENTATION_RESULTS.html = HtmlUsageResults; - INSTRUMENTATION_RESULTS.recipe = RecipeResults; - - // Convert it to a more efficient format - INSTRUMENTATION_RESULTS_TSV = convertToTSV(INSTRUMENTATION_RESULTS); - - // Remove tabs and new lines from the data - for(var i = INSTRUMENTATION_RESULTS_TSV.length; i--;) { - var row = INSTRUMENTATION_RESULTS_TSV[i]; - for(var j = row.length; j--;) { - row[j] = (''+row[j]).replace(/(\s|\r|\n)+/g, ' '); - } - } - - // Convert into one signle tsv file - var tsvString = INSTRUMENTATION_RESULTS_TSV.map((row) => (row.join('\t'))).join('\n'); - appendTSV(tsvString); - - // Add it to the document dom - function appendTSV(content) { - if(window.debugCSSUsage) console.log("Trying to append"); - var output = document.createElement('script'); - output.id = "css-usage-tsv-results"; - output.textContent = tsvString; - output.type = 'text/plain'; - document.querySelector('head').appendChild(output); - var successfulAppend = checkAppend(); - } - - function checkAppend() { - if(window.debugCSSUsage) if(window.debugCSSUsage) console.log("Checking append"); - var elem = document.getElementById('css-usage-tsv-results'); - if(elem === null) { - if(window.debugCSSUsage) console.log("Element not appended"); - if(window.debugCSSUsage) console.log("Trying to append again"); - appendTSV(); - } - else { - if(window.debugCSSUsage) console.log("Element successfully found"); - } - } - - /** convert the instrumentation results to a spreadsheet for analysis */ - function convertToTSV(INSTRUMENTATION_RESULTS) { - if(window.debugCSSUsage) console.log("Converting to TSV"); - - var VALUE_COLUMN = 4; - var finishedRows = []; - var currentRowTemplate = [ - INSTRUMENTATION_RESULTS.UA, - INSTRUMENTATION_RESULTS.UASTRING_HASH, - INSTRUMENTATION_RESULTS.URL, - INSTRUMENTATION_RESULTS.TIMESTAMP, - 0 - ]; - - currentRowTemplate.push('ua'); - convertToTSV({identifier: INSTRUMENTATION_RESULTS.UASTRING}); - currentRowTemplate.pop(); - - currentRowTemplate.push('css'); - convertToTSV(INSTRUMENTATION_RESULTS['css']); - currentRowTemplate.pop(); - - currentRowTemplate.push('dom'); - convertToTSV(INSTRUMENTATION_RESULTS['dom']); - currentRowTemplate.pop(); - - currentRowTemplate.push('html'); - convertToTSV(INSTRUMENTATION_RESULTS['html']); - currentRowTemplate.pop(); - - currentRowTemplate.push('recipe'); - convertToTSV(INSTRUMENTATION_RESULTS['recipe']); - currentRowTemplate.pop(); - - var l = finishedRows[0].length; - finishedRows.sort((a,b) => { - for(var i = VALUE_COLUMN+1; ib[i]) return +1; - } - return 0; - }); - - return finishedRows; - - /** helper function doing the actual conversion */ - function convertToTSV(object) { - if(object==null || object==undefined || typeof object == 'number' || typeof object == 'string') { - finishedRows.push(new Row(currentRowTemplate, ''+object)); - } else { - for(var key in object) { - if({}.hasOwnProperty.call(object,key)) { - currentRowTemplate.push(key); - convertToTSV(object[key]); - currentRowTemplate.pop(); - } - } - } - } - - /** constructor for a row of our table */ - function Row(currentRowTemplate, value) { - - // Initialize an empty row with enough columns - var row = [ - /*UANAME: edge */'', - /*UASTRING: mozilla/5.0 (...) */'', - /*URL: http://.../... */'', - /*TIMESTAMP: 1445622257303 */'', - /*VALUE: 0|1|... */'', - /*DATATYPE: css|dom|html... */'', - /*SUBTYPE: props|types|api|... */'', - /*NAME: font-size|querySelector|... */'', - /*CONTEXT: count|values|... */'', - /*SUBCONTEXT: px|em|... */'', - /*... */'', - /*... */'', - ]; - - // Copy the column values from the template - for(var i = currentRowTemplate.length; i--;) { - row[i] = currentRowTemplate[i]; - } - - // Add the value to the row - row[VALUE_COLUMN] = value; - - return row; - } - - } +/* + RECIPE: z-index on static flex items + ------------------------------------------------------------- + Author: Francois Remy + Description: Get count of flex items who should create a stacking context but do not really +*/ + +void function() { + + window.CSSUsage.StyleWalker.recipesToRun.push( function zstaticflex(/*HTML DOM Element*/ element, results) { + if(!element.parentElement) return; + + // the problem happens if the element is a flex item with static position and non-auto z-index + if(getComputedStyle(element.parentElement).display != 'flex') return results; + if(getComputedStyle(element).position != 'static') return results; + if(getComputedStyle(element).zIndex != 'auto') { + results.likely = 1; + } + + // the problem might happen if z-index could ever be non-auto + if(element.CSSUsage["z-index"] && element.CSSUsage["z-index"].valuesArray.length > 0) { + results.possible = 1; + } + + }); +}(); + +// +// This file is only here to create the TSV +// necessary to collect the data from the crawler +// +void function() { + + /* String hash function + /* credits goes to http://erlycoder.com/49/javascript-hash-functions-to-convert-string-into-integer-hash- */ + const hashCodeOf = (str) => { + var hash = 5381; var char = 0; + for (var i = 0; i < str.length; i++) { + char = str.charCodeAt(i); + hash = ((hash << 5) + hash) + char; + } + return hash; + } + + var ua = navigator.userAgent; + var uaName = ua.indexOf('Edge')>=0 ? 'EDGE' :ua.indexOf('Chrome')>=0 ? 'CHROME' : 'FIREFOX'; + window.INSTRUMENTATION_RESULTS = { + UA: uaName, + UASTRING: ua, + UASTRING_HASH: hashCodeOf(ua), + URL: location.href, + TIMESTAMP: Date.now(), + css: {/* see CSSUsageResults */}, + html: {/* see HtmlUsageResults */}, + dom: {}, + scripts: {/* "bootstrap.js": 1 */}, + }; + window.INSTRUMENTATION_RESULTS_TSV = []; + + /* make the script work in the context of a webview */ + try { + var console = window.console || (window.console={log:function(){},warn:function(){},error:function(){}}); + console.unsafeLog = console.log; + console.log = function() { + try { + this.unsafeLog.apply(this,arguments); + } catch(ex) { + // ignore + } + }; + } catch (ex) { + // we tried... + } +}(); + +window.onCSSUsageResults = function onCSSUsageResults(CSSUsageResults) { + // Collect the results (css) + INSTRUMENTATION_RESULTS.css = CSSUsageResults; + INSTRUMENTATION_RESULTS.html = HtmlUsageResults; + INSTRUMENTATION_RESULTS.recipe = RecipeResults; + + // Convert it to a more efficient format + INSTRUMENTATION_RESULTS_TSV = convertToTSV(INSTRUMENTATION_RESULTS); + + // Remove tabs and new lines from the data + for(var i = INSTRUMENTATION_RESULTS_TSV.length; i--;) { + var row = INSTRUMENTATION_RESULTS_TSV[i]; + for(var j = row.length; j--;) { + row[j] = (''+row[j]).replace(/(\s|\r|\n)+/g, ' '); + } + } + + // Convert into one signle tsv file + var tsvString = INSTRUMENTATION_RESULTS_TSV.map((row) => (row.join('\t'))).join('\n'); + appendTSV(tsvString); + + // Add it to the document dom + function appendTSV(content) { + if(window.debugCSSUsage) console.log("Trying to append"); + var output = document.createElement('script'); + output.id = "css-usage-tsv-results"; + output.textContent = tsvString; + output.type = 'text/plain'; + document.querySelector('head').appendChild(output); + var successfulAppend = checkAppend(); + } + + function checkAppend() { + if(window.debugCSSUsage) if(window.debugCSSUsage) console.log("Checking append"); + var elem = document.getElementById('css-usage-tsv-results'); + if(elem === null) { + if(window.debugCSSUsage) console.log("Element not appended"); + if(window.debugCSSUsage) console.log("Trying to append again"); + appendTSV(); + } + else { + if(window.debugCSSUsage) console.log("Element successfully found"); + } + } + + /** convert the instrumentation results to a spreadsheet for analysis */ + function convertToTSV(INSTRUMENTATION_RESULTS) { + if(window.debugCSSUsage) console.log("Converting to TSV"); + + var VALUE_COLUMN = 4; + var finishedRows = []; + var currentRowTemplate = [ + INSTRUMENTATION_RESULTS.UA, + INSTRUMENTATION_RESULTS.UASTRING_HASH, + INSTRUMENTATION_RESULTS.URL, + INSTRUMENTATION_RESULTS.TIMESTAMP, + 0 + ]; + + currentRowTemplate.push('ua'); + convertToTSV({identifier: INSTRUMENTATION_RESULTS.UASTRING}); + currentRowTemplate.pop(); + + currentRowTemplate.push('css'); + convertToTSV(INSTRUMENTATION_RESULTS['css']); + currentRowTemplate.pop(); + + currentRowTemplate.push('dom'); + convertToTSV(INSTRUMENTATION_RESULTS['dom']); + currentRowTemplate.pop(); + + currentRowTemplate.push('html'); + convertToTSV(INSTRUMENTATION_RESULTS['html']); + currentRowTemplate.pop(); + + currentRowTemplate.push('recipe'); + convertToTSV(INSTRUMENTATION_RESULTS['recipe']); + currentRowTemplate.pop(); + + var l = finishedRows[0].length; + finishedRows.sort((a,b) => { + for(var i = VALUE_COLUMN+1; ib[i]) return +1; + } + return 0; + }); + + return finishedRows; + + /** helper function doing the actual conversion */ + function convertToTSV(object) { + if(object==null || object==undefined || typeof object == 'number' || typeof object == 'string') { + finishedRows.push(new Row(currentRowTemplate, ''+object)); + } else { + for(var key in object) { + if({}.hasOwnProperty.call(object,key)) { + currentRowTemplate.push(key); + convertToTSV(object[key]); + currentRowTemplate.pop(); + } + } + } + } + + /** constructor for a row of our table */ + function Row(currentRowTemplate, value) { + + // Initialize an empty row with enough columns + var row = [ + /*UANAME: edge */'', + /*UASTRING: mozilla/5.0 (...) */'', + /*URL: http://.../... */'', + /*TIMESTAMP: 1445622257303 */'', + /*VALUE: 0|1|... */'', + /*DATATYPE: css|dom|html... */'', + /*SUBTYPE: props|types|api|... */'', + /*NAME: font-size|querySelector|... */'', + /*CONTEXT: count|values|... */'', + /*SUBCONTEXT: px|em|... */'', + /*... */'', + /*... */'', + ]; + + // Copy the column values from the template + for(var i = currentRowTemplate.length; i--;) { + row[i] = currentRowTemplate[i]; + } + + // Add the value to the row + row[VALUE_COLUMN] = value; + + return row; + } + + } }; // // Execution scheduler: diff --git a/src/cssUsage.js b/src/cssUsage.js index b8700c3..f05b52d 100644 --- a/src/cssUsage.js +++ b/src/cssUsage.js @@ -602,7 +602,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName) { + function createValueArray(value, propertyName, stripUrlValue) { // Trim value on the edges value = value.trim(); @@ -622,10 +622,15 @@ void function() { try { value = value.replace(/('|‘|’|")/g, ""); } + // Collapse whitespace + value = value.trim().replace(/\s+/g, " "); + // Divide at commas to separate different font names value = value.split(/\s*,\s*/g); + + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/g); return value; - case '--var': // Replace strings by dummies @@ -635,7 +640,7 @@ void function() { try { // Replace url(...) functions by dummies value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - + // Remove group contents (...), {...} and [...] value = value.replace(/[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, " "); value = value.replace(/[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, " "); @@ -643,28 +648,37 @@ void function() { try { value = value.replace(/[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]*)[}])*[}])*[}])*[}])*[}]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); - break; default: - - // Replace strings by dummies - value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // Replace url(...) functions by dummies - if (value.indexOf("(") != -1) { - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + // Don't divide commas and spaces if we want the inside of Url values + if (stripUrlValue){ + // Replace strings by dummies + value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') + .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + + // Replace url(...) functions by dummies + if (value.indexOf("(") != -1) { + value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + } + + // Collapse whitespace + value = value.trim().replace(/\s+/g, " "); + + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/g); } - } - // Collapse whitespace - value = value.trim().replace(/\s+/g, " "); - - // Divide at commas and spaces to separate different values - value = value.split(/\s*(?:,|[/])\s*|\s+/g); + + // This fixes a bug where there is only one item and it's not split by the value.split + // What ends up happening is that this function returns a string, not an array. + // This causes an issue because when we do .length in the for loop after this, it returns the length of the string, not the array. + if( typeof value === 'string' ) { + value = [ value ]; + } return value; } @@ -849,7 +863,8 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); + var stripUrlValue = true; + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue, normalizedKey, stripUrlValue); var values = new Array(); for(var j = specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); diff --git a/src/recipes/archive/SVGInUrl.js b/src/recipes/archive/SVGInUrl.js new file mode 100644 index 0000000..d3720c0 --- /dev/null +++ b/src/recipes/archive/SVGInUrl.js @@ -0,0 +1,34 @@ +/* + RECIPE: SVGInUrl + ------------------------------------------------------------- + Author: Joshua Berenhaus + Description: Find CSS Properties with url("___.svg") or url(data:image/svg+xml___) +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGInUrl( element, results) { + if(element.CSSUsage){ + var x = Object.keys(element.CSSUsage); + + + for(var n = 0; n < x.length; n++){ + var value = element.CSSUsage[Object.keys(element.CSSUsage)[n]] //Grab the value of each item in the object + //we want to know which are urls + if(/url\((.+\.svg.?)\)/.test(value)){ + results['SVGInUrl'] = results['SVGInUrl'] || {count : 0} + results['SVGInUrl'].count++; + break; + // } else if (/url\((data\:image\/svg\+xml.+)\)/.test(value)){ + } else if (/svg\+xml\;base64/.test(value)){ + results['SVGInUrlExplicit'] = results['SVGInUrlExplicit'] || {count : 0} + results['SVGInUrlExplicit'].count++; + break; + } + } + } + return results; + }); +}(); + + + diff --git a/src/recipes/archive/SVGSyntaxUsed.js b/src/recipes/archive/SVGSyntaxUsed.js new file mode 100644 index 0000000..6d83c88 --- /dev/null +++ b/src/recipes/archive/SVGSyntaxUsed.js @@ -0,0 +1,20 @@ +/* + RECIPE: SVGSyntaxUsed + ------------------------------------------------------------- + Author: Joshua Berenhaus + Description: tag found +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGSyntaxUsed( element, results) { + if(element.nodeName == "svg") { + results['SVGSyntaxUsed'] = results['SVGSyntaxUsed'] || { count: 0 }; + results['SVGSyntaxUsed'].count++; + } + + return results; + }); +}(); + + + diff --git a/src/recipes/archive/SVGUsedOnHtmlElementData.js b/src/recipes/archive/SVGUsedOnHtmlElementData.js new file mode 100644 index 0000000..41205c9 --- /dev/null +++ b/src/recipes/archive/SVGUsedOnHtmlElementData.js @@ -0,0 +1,28 @@ +/* + RECIPE: SVGUsedOnHtmlElementData + ------------------------------------------------------------- + Author: Joshua Berenhaus + Description: Find instances that match <___ data="___.svg"> or <___ type="image/svg+xml" data="___.svg"> +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnHtmlElementData( element, results) { + for(var n = 0; n < element.attributes.length; n++) { + if(element.attributes[n].name == "type" && element.attributes[n].value.indexOf("image/svg+xml") != -1) { + if(element.attributes[n+1].name == "data" && element.attributes[n+1].value.indexOf(".svg") != -1){ + results['SVGUsedOnHtmlElementDataExplicit'] = results['SVGUsedOnHtmlElementDataExplicit'] || { count: 0 }; + results['SVGUsedOnHtmlElementDataExplicit'].count++; + break; + } + } else if (element.attributes[n].name == "data" && element.attributes[n].value.indexOf(".svg") != -1){ + results['SVGUsedOnHtmlElementData'] = results['SVGUsedOnHtmlElementData'] || { count: 0 }; + results['SVGUsedOnHtmlElementData'].count++; + break; + } + } + return results; + }); +}(); + + + diff --git a/src/recipes/archive/SVGUsedOnHtmlElementSrc.js b/src/recipes/archive/SVGUsedOnHtmlElementSrc.js new file mode 100644 index 0000000..679e381 --- /dev/null +++ b/src/recipes/archive/SVGUsedOnHtmlElementSrc.js @@ -0,0 +1,29 @@ +/* + RECIPE: SVGUsedOnHtmlElementSrc + ------------------------------------------------------------- + Author: Joshua Berenhaus + Description: Find instances of - ------------------------------------------------------------- - Author: - Description: - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function ( element, results) { - return results; - }); -}(); - -*/ \ No newline at end of file diff --git a/tests/recipes/microsoftedge.svg b/tests/recipes/microsoftedge.svg new file mode 100644 index 0000000..9434322 --- /dev/null +++ b/tests/recipes/microsoftedge.svg @@ -0,0 +1 @@ + diff --git a/tests/recipes/svginvestigation.html b/tests/recipes/svginvestigation.html new file mode 100644 index 0000000..ab650b1 --- /dev/null +++ b/tests/recipes/svginvestigation.html @@ -0,0 +1,61 @@ + + + + + SVG Investigation + + + + + + + +

+ This is text with a SVG border image +

+ + +

+ This is text with a SVG background image +

+ + +

SVG Image as svg file url + +

+ + +

SVG Image as base64 data image + +

+ + +

SVG as some other type of element as explicit object data + +

+ + +

SVG as some other type of element as object data + +

+ + + +   + + + + +