From 27cbaf8b88e18cd5a7380270fd86d70a8a8cb794 Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Thu, 23 Mar 2017 17:00:44 -0700 Subject: [PATCH 01/13] commit --- Recipe.min.js | 683 ++++++++++++++------------- cssUsage.src.js | 696 +++++++++++++++------------- src/cssUsage.js | 14 +- src/recipes/svginvestigation.js | 27 ++ tests/recipes/svginvestigation.html | 17 + 5 files changed, 776 insertions(+), 661 deletions(-) create mode 100644 src/recipes/svginvestigation.js create mode 100644 tests/recipes/svginvestigation.html diff --git a/Recipe.min.js b/Recipe.min.js index b0f4926..b37f485 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -1,4 +1,4 @@ -void function() { +void function() { var _ = (a => new ArrayWrapper(a)); _.mapInline = mapInline; @@ -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 { @@ -936,7 +936,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName) { + function createValueArray(value, propertyName, doingSpecified) { // Trim value on the edges value = value.trim(); @@ -966,10 +966,12 @@ void function() { try { value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // Replace url(...) functions by dummies - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - + if(!doingSpecified){ + // 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, " "); @@ -1182,7 +1184,7 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, true); var values = new Array(); for(var j=specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); @@ -1540,287 +1542,324 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* - RECIPE: Experimental WebGL - ------------------------------------------------------------- - Author: Mustapha Jaber - Description: Find use of experimental-webgl in script. -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function experimentalWebgl(/*HTML DOM Element*/ element, results) { - var nodeName = element.nodeName; - var script = "experimental-webgl" - if (nodeName == "SCRIPT") - { - results[nodeName] = results[nodeName] || { count: 0, }; - // if inline script. ensure that it's not our recipe script and look for string of interest - if (element.text !== undefined && element.text.indexOf(script) != -1) - { - results[nodeName].count++; - } - else if (element.src !== undefined && element.src != "") - { - var xhr = new XMLHttpRequest(); - xhr.open("GET", element.src, false); - //xhr.setRequestHeader("Content-type", "text/javascript"); - xhr.send(); - if (xhr.status === 200 && xhr.responseText.indexOf(script) != -1) - { - results[nodeName].count++; - } - } - } - return results; - }); +/* + RECIPE: Experimental WebGL + ------------------------------------------------------------- + Author: Mustapha Jaber + Description: Find use of experimental-webgl in script. +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function experimentalWebgl(/*HTML DOM Element*/ element, results) { + var nodeName = element.nodeName; + var script = "experimental-webgl" + if (nodeName == "SCRIPT") + { + results[nodeName] = results[nodeName] || { count: 0, }; + // if inline script. ensure that it's not our recipe script and look for string of interest + if (element.text !== undefined && element.text.indexOf(script) != -1) + { + results[nodeName].count++; + } + else if (element.src !== undefined && element.src != "") + { + var xhr = new XMLHttpRequest(); + xhr.open("GET", element.src, false); + //xhr.setRequestHeader("Content-type", "text/javascript"); + xhr.send(); + if (xhr.status === 200 && xhr.responseText.indexOf(script) != -1) + { + results[nodeName].count++; + } + } + } + return results; + }); }(); -/* - RECIPE: Max-width on Replaced Elements - ------------------------------------------------------------- - Author: Greg Whitworth - Description: This is investigation for the CSSWG looking into - max-width with a % on a replaced element. If the results return - too large we may want to take the next step to roughly determine - if one of the parent's are depending on the sizing of its child. - For example, abspos, table cell, floats, etc. That will be more - computationally extensive so we'll start a simpler investigation first. - - Action Link: https://log.csswg.org/irc.w3.org/css/2017-03-01/#e778075 -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function MaxWidthPercentOnReplacedElem(element, results) { - // Bail if the element doesn't have the props we're looking for - if(!element.CSSUsage || !(element.CSSUsage["max-width"])) return; - - var replacedElems = ["INPUT", "TEXTAREA"]; - var maxWidth = element.CSSUsage['max-width']; - var width = element.CSSUsage['width']; - - if(!maxWidth.includes('%')) return; - - // We only want auto sized boxes - if(width && !width.includes('auto')) return; - - if(replacedElems.includes(element.nodeName)) { - - if(element.nodeName == "INPUT" && element.type != "text") { - return; - } - - // TSV eg: 5 recipe MaxWidthPercentOnReplacedElem INPUT count - results[element.nodeName] = results[element.nodeName] || { count: 0 }; - results[element.nodeName].count++; - } - - return results; - }); +/* + RECIPE: Max-width on Replaced Elements + ------------------------------------------------------------- + Author: Greg Whitworth + Description: This is investigation for the CSSWG looking into + max-width with a % on a replaced element. If the results return + too large we may want to take the next step to roughly determine + if one of the parent's are depending on the sizing of its child. + For example, abspos, table cell, floats, etc. That will be more + computationally extensive so we'll start a simpler investigation first. + + Action Link: https://log.csswg.org/irc.w3.org/css/2017-03-01/#e778075 +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function MaxWidthPercentOnReplacedElem(element, results) { + // Bail if the element doesn't have the props we're looking for + if(!element.CSSUsage || !(element.CSSUsage["max-width"])) return; + + var replacedElems = ["INPUT", "TEXTAREA"]; + var maxWidth = element.CSSUsage['max-width']; + var width = element.CSSUsage['width']; + + if(!maxWidth.includes('%')) return; + + // We only want auto sized boxes + if(width && !width.includes('auto')) return; + + if(replacedElems.includes(element.nodeName)) { + + if(element.nodeName == "INPUT" && element.type != "text") { + return; + } + + // TSV eg: 5 recipe MaxWidthPercentOnReplacedElem INPUT count + results[element.nodeName] = results[element.nodeName] || { count: 0 }; + results[element.nodeName].count++; + } + + return results; + }); +}(); +/* + RECIPE: Payment Request + ------------------------------------------------------------- + Author: Stanley Hon + Description: This counts any page that includes any script references to PaymentRequest +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function paymentrequest(/*HTML DOM Element*/ element, results) { + + if(element.nodeName == "SCRIPT") { + if (element.innerText.indexOf("PaymentRequest") != -1) { + results["use"] = results["use"] || { count: 0 }; + results["use"].count++; + } + } + + return results; + }); }(); /* - RECIPE: Payment Request + RECIPE: ------------------------------------------------------------- - Author: Stanley Hon - Description: This counts any page that includes any script references to PaymentRequest -*/ + Author: + Description: void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function paymentrequest(/*HTML DOM Element*/ element, results) { - - if(element.nodeName == "SCRIPT") { - if (element.innerText.indexOf("PaymentRequest") != -1) { - results["use"] = results["use"] || { count: 0 }; - results["use"].count++; - } - } - + window.CSSUsage.StyleWalker.recipesToRun.push( function ( element, results) { return results; }); }(); + +*/ /* RECIPE: ------------------------------------------------------------- Author: Description: +*/ void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function ( element, results) { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnImage( element, results) { + if(element.nodeName == "IMG") { + for(var n = 0; n < element.attributes.length; n++) { + if(element.attributes[n].name == "src") { + if(element.attributes[n].value.indexOf(".svg") != -1){ + results['imgsrc'] = results['imgsrc'] || { count: 0 }; + results['imgsrc'].count++; + break; + } + } + } + } + return results; }); }(); -*/ -// -// 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; - } - } +// +// 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 92dfc71..94c1c5e 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 { @@ -936,7 +936,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName) { + function createValueArray(value, propertyName, doingSpecified) { // Trim value on the edges value = value.trim(); @@ -966,10 +966,12 @@ void function() { try { value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // Replace url(...) functions by dummies - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - + if(!doingSpecified){ + // 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, " "); @@ -1182,7 +1184,7 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, true); var values = new Array(); for(var j=specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); @@ -1540,299 +1542,327 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* - RECIPE: Experimental WebGL - ------------------------------------------------------------- - Author: Mustapha Jaber - Description: Find use of experimental-webgl in script. -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function experimentalWebgl(/*HTML DOM Element*/ element, results) { - var nodeName = element.nodeName; - var script = "experimental-webgl" - if (nodeName == "SCRIPT") - { - results[nodeName] = results[nodeName] || { count: 0, }; - // if inline script. ensure that it's not our recipe script and look for string of interest - if (element.text !== undefined && element.text.indexOf(script) != -1) - { - results[nodeName].count++; - } - else if (element.src !== undefined && element.src != "") - { - var xhr = new XMLHttpRequest(); - xhr.open("GET", element.src, false); - //xhr.setRequestHeader("Content-type", "text/javascript"); - xhr.send(); - if (xhr.status === 200 && xhr.responseText.indexOf(script) != -1) - { - results[nodeName].count++; - } - } - } - return results; - }); +/* + RECIPE: Experimental WebGL + ------------------------------------------------------------- + Author: Mustapha Jaber + Description: Find use of experimental-webgl in script. +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function experimentalWebgl(/*HTML DOM Element*/ element, results) { + var nodeName = element.nodeName; + var script = "experimental-webgl" + if (nodeName == "SCRIPT") + { + results[nodeName] = results[nodeName] || { count: 0, }; + // if inline script. ensure that it's not our recipe script and look for string of interest + if (element.text !== undefined && element.text.indexOf(script) != -1) + { + results[nodeName].count++; + } + else if (element.src !== undefined && element.src != "") + { + var xhr = new XMLHttpRequest(); + xhr.open("GET", element.src, false); + //xhr.setRequestHeader("Content-type", "text/javascript"); + xhr.send(); + if (xhr.status === 200 && xhr.responseText.indexOf(script) != -1) + { + results[nodeName].count++; + } + } + } + return results; + }); }(); -/* - RECIPE: Max-width on Replaced Elements - ------------------------------------------------------------- - Author: Greg Whitworth - Description: This is investigation for the CSSWG looking into - max-width with a % on a replaced element. If the results return - too large we may want to take the next step to roughly determine - if one of the parent's are depending on the sizing of its child. - For example, abspos, table cell, floats, etc. That will be more - computationally extensive so we'll start a simpler investigation first. - - Action Link: https://log.csswg.org/irc.w3.org/css/2017-03-01/#e778075 -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function MaxWidthPercentOnReplacedElem(element, results) { - // Bail if the element doesn't have the props we're looking for - if(!element.CSSUsage || !(element.CSSUsage["max-width"])) return; - - var replacedElems = ["INPUT", "TEXTAREA"]; - var maxWidth = element.CSSUsage['max-width']; - var width = element.CSSUsage['width']; - - if(!maxWidth.includes('%')) return; - - // We only want auto sized boxes - if(width && !width.includes('auto')) return; - - if(replacedElems.includes(element.nodeName)) { - - if(element.nodeName == "INPUT" && element.type != "text") { - return; - } - - // TSV eg: 5 recipe MaxWidthPercentOnReplacedElem INPUT count - results[element.nodeName] = results[element.nodeName] || { count: 0 }; - results[element.nodeName].count++; - } - - return results; - }); +/* + RECIPE: Max-width on Replaced Elements + ------------------------------------------------------------- + Author: Greg Whitworth + Description: This is investigation for the CSSWG looking into + max-width with a % on a replaced element. If the results return + too large we may want to take the next step to roughly determine + if one of the parent's are depending on the sizing of its child. + For example, abspos, table cell, floats, etc. That will be more + computationally extensive so we'll start a simpler investigation first. + + Action Link: https://log.csswg.org/irc.w3.org/css/2017-03-01/#e778075 +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function MaxWidthPercentOnReplacedElem(element, results) { + // Bail if the element doesn't have the props we're looking for + if(!element.CSSUsage || !(element.CSSUsage["max-width"])) return; + + var replacedElems = ["INPUT", "TEXTAREA"]; + var maxWidth = element.CSSUsage['max-width']; + var width = element.CSSUsage['width']; + + if(!maxWidth.includes('%')) return; + + // We only want auto sized boxes + if(width && !width.includes('auto')) return; + + if(replacedElems.includes(element.nodeName)) { + + if(element.nodeName == "INPUT" && element.type != "text") { + return; + } + + // TSV eg: 5 recipe MaxWidthPercentOnReplacedElem INPUT count + results[element.nodeName] = results[element.nodeName] || { count: 0 }; + results[element.nodeName].count++; + } + + return results; + }); +}(); +/* + RECIPE: Payment Request + ------------------------------------------------------------- + Author: Stanley Hon + Description: This counts any page that includes any script references to PaymentRequest +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function paymentrequest(/*HTML DOM Element*/ element, results) { + + if(element.nodeName == "SCRIPT") { + if (element.innerText.indexOf("PaymentRequest") != -1) { + results["use"] = results["use"] || { count: 0 }; + results["use"].count++; + } + } + + return results; + }); }(); /* - RECIPE: Payment Request + RECIPE: ------------------------------------------------------------- - Author: Stanley Hon - Description: This counts any page that includes any script references to PaymentRequest -*/ + Author: + Description: void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function paymentrequest(/*HTML DOM Element*/ element, results) { - - if(element.nodeName == "SCRIPT") { - if (element.innerText.indexOf("PaymentRequest") != -1) { - results["use"] = results["use"] || { count: 0 }; - results["use"].count++; - } - } - + window.CSSUsage.StyleWalker.recipesToRun.push( function ( element, results) { return results; }); }(); + +*/ /* RECIPE: ------------------------------------------------------------- Author: Description: +*/ void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function ( element, results) { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnImage( element, results) { + if(element.nodeName == "IMG") { + for(var n = 0; n < element.attributes.length; n++) { + if(element.attributes[n].name == "src") { + if(element.attributes[n].value.indexOf(".svg") != -1){ + results['imgsrc'] = results['imgsrc'] || { count: 0 }; + results['imgsrc'].count++; + break; + } + } + } + } + return results; }); }(); -*/ -// -// 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; - } - - } +// +// 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 7bc04f7..8ca8dba 100644 --- a/src/cssUsage.js +++ b/src/cssUsage.js @@ -439,7 +439,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName) { + function createValueArray(value, propertyName, doingSpecified) { // Trim value on the edges value = value.trim(); @@ -469,10 +469,12 @@ void function() { try { value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // Replace url(...) functions by dummies - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - + if(!doingSpecified){ + // 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, " "); @@ -685,7 +687,7 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, true); var values = new Array(); for(var j=specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); diff --git a/src/recipes/svginvestigation.js b/src/recipes/svginvestigation.js new file mode 100644 index 0000000..458146a --- /dev/null +++ b/src/recipes/svginvestigation.js @@ -0,0 +1,27 @@ +/* + RECIPE: + ------------------------------------------------------------- + Author: + Description: +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnImage( element, results) { + if(element.nodeName == "IMG") { + for(var n = 0; n < element.attributes.length; n++) { + if(element.attributes[n].name == "src") { + if(element.attributes[n].value.indexOf(".svg") != -1){ + results['imgsrc'] = results['imgsrc'] || { count: 0 }; + results['imgsrc'].count++; + break; + } + } + } + } + + return results; + }); +}(); + + + diff --git a/tests/recipes/svginvestigation.html b/tests/recipes/svginvestigation.html new file mode 100644 index 0000000..bd9afa6 --- /dev/null +++ b/tests/recipes/svginvestigation.html @@ -0,0 +1,17 @@ + + + + + Max Width on Replaced Elements using % + + + + + + + + + + + + \ No newline at end of file From 0eeb555303ddf7063604b2b156e1f9a6860f37cf Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Fri, 24 Mar 2017 16:00:54 -0700 Subject: [PATCH 02/13] A whole bunch of changes that adds three svg tests and manually fixes the recipe file. Need to fix grunt because it's overwriting things I'm doing in cssUsage.js --- Recipe.min.js | 673 +++++++++--------- cssUsage.src.js | 181 ++--- src/cssUsage.js | 20 +- src/recipes/SVGInUrl.js | 52 ++ src/recipes/SVGSyntaxUsed.js | 20 + ...{svginvestigation.js => SVGUsedOnImage.js} | 2 +- .../{ => archive}/experimentalWebgl.js | 0 .../{ => archive}/max-width-replaced-elems.js | 0 src/recipes/{ => archive}/paymentrequest.js | 0 src/recipes/recipe-template.js | 13 - tests/recipes/startupshell.svg | 172 +++++ tests/recipes/svginvestigation.html | 25 +- 12 files changed, 667 insertions(+), 491 deletions(-) create mode 100644 src/recipes/SVGInUrl.js create mode 100644 src/recipes/SVGSyntaxUsed.js rename src/recipes/{svginvestigation.js => SVGUsedOnImage.js} (93%) rename src/recipes/{ => archive}/experimentalWebgl.js (100%) rename src/recipes/{ => archive}/max-width-replaced-elems.js (100%) rename src/recipes/{ => archive}/paymentrequest.js (100%) delete mode 100644 src/recipes/recipe-template.js create mode 100644 tests/recipes/startupshell.svg diff --git a/Recipe.min.js b/Recipe.min.js index b37f485..2a3767d 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 { @@ -936,7 +936,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName, doingSpecified) { + function createValueArray(value, propertyName) { // Trim value on the edges value = value.trim(); @@ -962,15 +962,15 @@ void function() { try { case '--var': - // Replace strings by dummies - value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + // // Replace strings by dummies + // value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') + // value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - if(!doingSpecified){ - // Replace url(...) functions by dummies - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - } + // if(false){ + // // 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, " "); @@ -984,15 +984,15 @@ void function() { try { default: - // Replace strings by dummies - value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + // // 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() "); - } + // // Replace url(...) functions by dummies + // if (value.indexOf("(") != -1) { + // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + // } } @@ -1184,7 +1184,7 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, true); + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); var values = new Array(); for(var j=specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); @@ -1542,117 +1542,82 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* - RECIPE: Experimental WebGL - ------------------------------------------------------------- - Author: Mustapha Jaber - Description: Find use of experimental-webgl in script. -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function experimentalWebgl(/*HTML DOM Element*/ element, results) { - var nodeName = element.nodeName; - var script = "experimental-webgl" - if (nodeName == "SCRIPT") - { - results[nodeName] = results[nodeName] || { count: 0, }; - // if inline script. ensure that it's not our recipe script and look for string of interest - if (element.text !== undefined && element.text.indexOf(script) != -1) - { - results[nodeName].count++; - } - else if (element.src !== undefined && element.src != "") - { - var xhr = new XMLHttpRequest(); - xhr.open("GET", element.src, false); - //xhr.setRequestHeader("Content-type", "text/javascript"); - xhr.send(); - if (xhr.status === 200 && xhr.responseText.indexOf(script) != -1) - { - results[nodeName].count++; - } - } - } - return results; - }); -}(); -/* - RECIPE: Max-width on Replaced Elements - ------------------------------------------------------------- - Author: Greg Whitworth - Description: This is investigation for the CSSWG looking into - max-width with a % on a replaced element. If the results return - too large we may want to take the next step to roughly determine - if one of the parent's are depending on the sizing of its child. - For example, abspos, table cell, floats, etc. That will be more - computationally extensive so we'll start a simpler investigation first. - - Action Link: https://log.csswg.org/irc.w3.org/css/2017-03-01/#e778075 -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function MaxWidthPercentOnReplacedElem(element, results) { - // Bail if the element doesn't have the props we're looking for - if(!element.CSSUsage || !(element.CSSUsage["max-width"])) return; - - var replacedElems = ["INPUT", "TEXTAREA"]; - var maxWidth = element.CSSUsage['max-width']; - var width = element.CSSUsage['width']; - - if(!maxWidth.includes('%')) return; - - // We only want auto sized boxes - if(width && !width.includes('auto')) return; - - if(replacedElems.includes(element.nodeName)) { - - if(element.nodeName == "INPUT" && element.type != "text") { - return; - } - - // TSV eg: 5 recipe MaxWidthPercentOnReplacedElem INPUT count - results[element.nodeName] = results[element.nodeName] || { count: 0 }; - results[element.nodeName].count++; - } - - return results; - }); -}(); -/* - RECIPE: Payment Request - ------------------------------------------------------------- - Author: Stanley Hon - Description: This counts any page that includes any script references to PaymentRequest -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function paymentrequest(/*HTML DOM Element*/ element, results) { - - if(element.nodeName == "SCRIPT") { - if (element.innerText.indexOf("PaymentRequest") != -1) { - results["use"] = results["use"] || { count: 0 }; - results["use"].count++; - } - } - - return results; - }); +/* + RECIPE: SVGUsedOnImage + ------------------------------------------------------------- + Author: + Description: +*/ + +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 + //alert(value); + // if(value == "url()"){ + // alert("url found"); + + // value + // var patttemp = new RegExp("url\((.+)\)"); + // if(patttemp.test(value)){ + // alert(value) + var patt = new RegExp("url\(.+(\.svg).+\)"); + if(patt.test(value)){ + results['svginurl'] = results['svginurl'] || {count : 0} + results['svginurl'].count++; + break; + // alert("found a url that has svg in it!") + } + // } + // } + } + } + + // for(var n = 0; n < element.CSSUsage.length; n++) { + // if(element.CSSUsage[n].value) + // if(element.attributes[n].name == "url") { + // if(element.attributes[n].value.indexOf(".svg") != -1){ + // results['imgsrc'] = results['imgsrc'] || { count: 0 }; + // results['imgsrc'].count++; + // break; + // } + // } + // } + return results; + }); }(); + + + + /* RECIPE: ------------------------------------------------------------- Author: Description: +*/ void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function ( element, results) { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGSyntaxUsed( element, results) { + if(element.nodeName == "svg") { + results['svgHTML'] = results['svgHTML'] || { count: 0 }; + results['svgHTML'].count++; + } + return results; }); }(); -*/ + + + /* - RECIPE: + RECIPE: SVGUsedOnImage ------------------------------------------------------------- Author: Description: @@ -1679,187 +1644,187 @@ void function() { -// -// 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; - } - - } +// +// 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 94c1c5e..b85920d 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -936,7 +936,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName, doingSpecified) { + function createValueArray(value, propertyName) { // Trim value on the edges value = value.trim(); @@ -962,15 +962,15 @@ void function() { try { case '--var': - // Replace strings by dummies - value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + // // Replace strings by dummies + // value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') + // value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - if(!doingSpecified){ - // Replace url(...) functions by dummies - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - } + // if(false){ + // // 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, " "); @@ -1184,7 +1184,7 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, true); + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); var values = new Array(); for(var j=specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); @@ -1542,117 +1542,82 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* - RECIPE: Experimental WebGL - ------------------------------------------------------------- - Author: Mustapha Jaber - Description: Find use of experimental-webgl in script. -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function experimentalWebgl(/*HTML DOM Element*/ element, results) { - var nodeName = element.nodeName; - var script = "experimental-webgl" - if (nodeName == "SCRIPT") - { - results[nodeName] = results[nodeName] || { count: 0, }; - // if inline script. ensure that it's not our recipe script and look for string of interest - if (element.text !== undefined && element.text.indexOf(script) != -1) - { - results[nodeName].count++; - } - else if (element.src !== undefined && element.src != "") - { - var xhr = new XMLHttpRequest(); - xhr.open("GET", element.src, false); - //xhr.setRequestHeader("Content-type", "text/javascript"); - xhr.send(); - if (xhr.status === 200 && xhr.responseText.indexOf(script) != -1) - { - results[nodeName].count++; - } - } - } - return results; - }); -}(); -/* - RECIPE: Max-width on Replaced Elements - ------------------------------------------------------------- - Author: Greg Whitworth - Description: This is investigation for the CSSWG looking into - max-width with a % on a replaced element. If the results return - too large we may want to take the next step to roughly determine - if one of the parent's are depending on the sizing of its child. - For example, abspos, table cell, floats, etc. That will be more - computationally extensive so we'll start a simpler investigation first. - - Action Link: https://log.csswg.org/irc.w3.org/css/2017-03-01/#e778075 -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function MaxWidthPercentOnReplacedElem(element, results) { - // Bail if the element doesn't have the props we're looking for - if(!element.CSSUsage || !(element.CSSUsage["max-width"])) return; - - var replacedElems = ["INPUT", "TEXTAREA"]; - var maxWidth = element.CSSUsage['max-width']; - var width = element.CSSUsage['width']; - - if(!maxWidth.includes('%')) return; - - // We only want auto sized boxes - if(width && !width.includes('auto')) return; - - if(replacedElems.includes(element.nodeName)) { - - if(element.nodeName == "INPUT" && element.type != "text") { - return; - } - - // TSV eg: 5 recipe MaxWidthPercentOnReplacedElem INPUT count - results[element.nodeName] = results[element.nodeName] || { count: 0 }; - results[element.nodeName].count++; - } - - return results; - }); -}(); -/* - RECIPE: Payment Request - ------------------------------------------------------------- - Author: Stanley Hon - Description: This counts any page that includes any script references to PaymentRequest -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function paymentrequest(/*HTML DOM Element*/ element, results) { - - if(element.nodeName == "SCRIPT") { - if (element.innerText.indexOf("PaymentRequest") != -1) { - results["use"] = results["use"] || { count: 0 }; - results["use"].count++; - } - } - - return results; - }); +/* + RECIPE: SVGUsedOnImage + ------------------------------------------------------------- + Author: + Description: +*/ + +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 + //alert(value); + // if(value == "url()"){ + // alert("url found"); + + // value + // var patttemp = new RegExp("url\((.+)\)"); + // if(patttemp.test(value)){ + // alert(value) + var patt = new RegExp("url\(.+(\.svg).+\)"); + if(patt.test(value)){ + results['svginurl'] = results['svginurl'] || {count : 0} + results['svginurl'].count++; + break; + // alert("found a url that has svg in it!") + } + // } + // } + } + } + + // for(var n = 0; n < element.CSSUsage.length; n++) { + // if(element.CSSUsage[n].value) + // if(element.attributes[n].name == "url") { + // if(element.attributes[n].value.indexOf(".svg") != -1){ + // results['imgsrc'] = results['imgsrc'] || { count: 0 }; + // results['imgsrc'].count++; + // break; + // } + // } + // } + return results; + }); }(); + + + + /* RECIPE: ------------------------------------------------------------- Author: Description: +*/ void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function ( element, results) { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGSyntaxUsed( element, results) { + if(element.nodeName == "svg") { + results['svgHTML'] = results['svgHTML'] || { count: 0 }; + results['svgHTML'].count++; + } + return results; }); }(); -*/ + + + /* - RECIPE: + RECIPE: SVGUsedOnImage ------------------------------------------------------------- Author: Description: diff --git a/src/cssUsage.js b/src/cssUsage.js index 8ca8dba..8c544da 100644 --- a/src/cssUsage.js +++ b/src/cssUsage.js @@ -439,7 +439,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName, doingSpecified) { + function createValueArray(value, propertyName) { // Trim value on the edges value = value.trim(); @@ -465,15 +465,15 @@ void function() { try { case '--var': - // Replace strings by dummies - value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + // // Replace strings by dummies + // value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') + // value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - if(!doingSpecified){ - // Replace url(...) functions by dummies - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - } + // if(false){ + // // 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, " "); @@ -687,7 +687,7 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, true); + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); var values = new Array(); for(var j=specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); diff --git a/src/recipes/SVGInUrl.js b/src/recipes/SVGInUrl.js new file mode 100644 index 0000000..c734e22 --- /dev/null +++ b/src/recipes/SVGInUrl.js @@ -0,0 +1,52 @@ +/* + RECIPE: SVGUsedOnImage + ------------------------------------------------------------- + Author: + Description: +*/ + +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 + //alert(value); + // if(value == "url()"){ + // alert("url found"); + + // value + // var patttemp = new RegExp("url\((.+)\)"); + // if(patttemp.test(value)){ + // alert(value) + var patt = new RegExp("url\(.+(\.svg).+\)"); + if(patt.test(value)){ + results['svginurl'] = results['svginurl'] || {count : 0} + results['svginurl'].count++; + break; + // alert("found a url that has svg in it!") + } + // } + // } + } + } + + // for(var n = 0; n < element.CSSUsage.length; n++) { + // if(element.CSSUsage[n].value) + // if(element.attributes[n].name == "url") { + // if(element.attributes[n].value.indexOf(".svg") != -1){ + // results['imgsrc'] = results['imgsrc'] || { count: 0 }; + // results['imgsrc'].count++; + // break; + // } + // } + // } + return results; + }); +}(); + + + diff --git a/src/recipes/SVGSyntaxUsed.js b/src/recipes/SVGSyntaxUsed.js new file mode 100644 index 0000000..4894d17 --- /dev/null +++ b/src/recipes/SVGSyntaxUsed.js @@ -0,0 +1,20 @@ +/* + RECIPE: + ------------------------------------------------------------- + Author: + Description: +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGSyntaxUsed( element, results) { + if(element.nodeName == "svg") { + results['svgHTML'] = results['svgHTML'] || { count: 0 }; + results['svgHTML'].count++; + } + + return results; + }); +}(); + + + diff --git a/src/recipes/svginvestigation.js b/src/recipes/SVGUsedOnImage.js similarity index 93% rename from src/recipes/svginvestigation.js rename to src/recipes/SVGUsedOnImage.js index 458146a..001d1f4 100644 --- a/src/recipes/svginvestigation.js +++ b/src/recipes/SVGUsedOnImage.js @@ -1,5 +1,5 @@ /* - RECIPE: + RECIPE: SVGUsedOnImage ------------------------------------------------------------- Author: Description: diff --git a/src/recipes/experimentalWebgl.js b/src/recipes/archive/experimentalWebgl.js similarity index 100% rename from src/recipes/experimentalWebgl.js rename to src/recipes/archive/experimentalWebgl.js diff --git a/src/recipes/max-width-replaced-elems.js b/src/recipes/archive/max-width-replaced-elems.js similarity index 100% rename from src/recipes/max-width-replaced-elems.js rename to src/recipes/archive/max-width-replaced-elems.js diff --git a/src/recipes/paymentrequest.js b/src/recipes/archive/paymentrequest.js similarity index 100% rename from src/recipes/paymentrequest.js rename to src/recipes/archive/paymentrequest.js diff --git a/src/recipes/recipe-template.js b/src/recipes/recipe-template.js deleted file mode 100644 index 79485b0..0000000 --- a/src/recipes/recipe-template.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - RECIPE: - ------------------------------------------------------------- - 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/startupshell.svg b/tests/recipes/startupshell.svg new file mode 100644 index 0000000..35d7769 --- /dev/null +++ b/tests/recipes/startupshell.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/recipes/svginvestigation.html b/tests/recipes/svginvestigation.html index bd9afa6..5527f23 100644 --- a/tests/recipes/svginvestigation.html +++ b/tests/recipes/svginvestigation.html @@ -5,13 +5,28 @@ Max Width on Replaced Elements using % - + + - - - + + +

This is text with a SVG border image

+ + + + + + + + + - \ No newline at end of file From a6281dabb74ee84fb624d53a3902d8105bbc2b19 Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Fri, 31 Mar 2017 11:04:26 -0700 Subject: [PATCH 03/13] Adding base64 image background --- tests/recipes/svginvestigation.html | 57 +++++++++++++++++------------ 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/tests/recipes/svginvestigation.html b/tests/recipes/svginvestigation.html index 5527f23..90efa52 100644 --- a/tests/recipes/svginvestigation.html +++ b/tests/recipes/svginvestigation.html @@ -1,32 +1,41 @@ - - - Max Width on Replaced Elements using % - - - - - - - + + + Max Width on Replaced Elements using % + + + + + + +

+ This is text with a SVG border image +

+

+ This is text with a SVG background image +

+ + - - - - - + + +   + + \ No newline at end of file From e8127ece3b1a00bca554fc5377a84b6b7260a395 Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Wed, 5 Apr 2017 14:03:50 -0700 Subject: [PATCH 04/13] 4/6 recipes implemented --- Recipe.min.js | 566 ++++++++++++------------ cssUsage.src.js | 118 ++--- src/cssUsage.js | 24 +- src/recipes/SVGInUrl.js | 38 +- src/recipes/SVGSyntaxUsed.js | 4 +- src/recipes/SVGUsedOnHtmlElementData.js | 28 ++ src/recipes/SVGUsedOnHtmlElementSrc.js | 24 + src/recipes/SVGUsedOnImage.js | 27 -- tests/recipes/svginvestigation.html | 28 +- 9 files changed, 441 insertions(+), 416 deletions(-) create mode 100644 src/recipes/SVGUsedOnHtmlElementData.js create mode 100644 src/recipes/SVGUsedOnHtmlElementSrc.js delete mode 100644 src/recipes/SVGUsedOnImage.js diff --git a/Recipe.min.js b/Recipe.min.js index 2a3767d..38975a6 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 { @@ -966,11 +966,9 @@ void function() { try { // value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') // value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // if(false){ - // // Replace url(...) functions by dummies - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - // } + // // 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, " "); @@ -1543,7 +1541,7 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); /* - RECIPE: SVGUsedOnImage + RECIPE: SVGInUrl ------------------------------------------------------------- Author: Description: @@ -1558,36 +1556,14 @@ void function() { 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 - //alert(value); - // if(value == "url()"){ - // alert("url found"); - - // value - // var patttemp = new RegExp("url\((.+)\)"); - // if(patttemp.test(value)){ - // alert(value) - var patt = new RegExp("url\(.+(\.svg).+\)"); - if(patt.test(value)){ - results['svginurl'] = results['svginurl'] || {count : 0} - results['svginurl'].count++; - break; - // alert("found a url that has svg in it!") - } - // } - // } + var patt = new RegExp("url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)"); + if(patt.test(value)){ + results['SVGInUrl'] = results['SVGInUrl'] || {count : 0} + results['SVGInUrl'].count++; + break; + } } - } - - // for(var n = 0; n < element.CSSUsage.length; n++) { - // if(element.CSSUsage[n].value) - // if(element.attributes[n].name == "url") { - // if(element.attributes[n].value.indexOf(".svg") != -1){ - // results['imgsrc'] = results['imgsrc'] || { count: 0 }; - // results['imgsrc'].count++; - // break; - // } - // } - // } + } return results; }); }(); @@ -1605,8 +1581,8 @@ void function() { void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function SVGSyntaxUsed( element, results) { if(element.nodeName == "svg") { - results['svgHTML'] = results['svgHTML'] || { count: 0 }; - results['svgHTML'].count++; + results['SVGSyntaxUsed'] = results['SVGSyntaxUsed'] || { count: 0 }; + results['SVGSyntaxUsed'].count++; } return results; @@ -1617,26 +1593,27 @@ void function() { /* - RECIPE: SVGUsedOnImage + RECIPE: SVGUsedOnHtmlElementData ------------------------------------------------------------- Author: Description: */ void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnImage( element, results) { - if(element.nodeName == "IMG") { - for(var n = 0; n < element.attributes.length; n++) { - if(element.attributes[n].name == "src") { - if(element.attributes[n].value.indexOf(".svg") != -1){ - results['imgsrc'] = results['imgsrc'] || { count: 0 }; - results['imgsrc'].count++; - break; - } + 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; }); }(); @@ -1644,187 +1621,212 @@ void function() { -// -// This file is only here to create the TSV -// necessary to collect the data from the crawler -// +/* + RECIPE: SVGUsedOnHtmlElementSrc + ------------------------------------------------------------- + Author: + Description: +*/ + 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.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnHtmlElementSrc( element, results) { + for(var n = 0; n < element.attributes.length; n++) { + if(element.attributes[n].name == "src") { + if(element.attributes[n].value.indexOf(".svg") != -1){ + results['SVGUsedOnHtmlElementSrc'] = results['SVGUsedOnHtmlElementSrc'] || { count: 0 }; + results['SVGUsedOnHtmlElementSrc'].count++; + break; + } + } + } + return results; + }); }(); -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; - } - } +// +// 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 b85920d..a61147c 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -966,11 +966,9 @@ void function() { try { // value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') // value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // if(false){ - // // Replace url(...) functions by dummies - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - // } + // // 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, " "); @@ -984,15 +982,15 @@ void function() { try { default: - // Replace strings by dummies - value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + // // 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() "); - } + // // Replace url(...) functions by dummies + // if (value.indexOf("(") != -1) { + // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + // } } @@ -1543,7 +1541,7 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); /* - RECIPE: SVGUsedOnImage + RECIPE: SVGInUrl ------------------------------------------------------------- Author: Description: @@ -1558,36 +1556,14 @@ void function() { 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 - //alert(value); - // if(value == "url()"){ - // alert("url found"); - - // value - // var patttemp = new RegExp("url\((.+)\)"); - // if(patttemp.test(value)){ - // alert(value) - var patt = new RegExp("url\(.+(\.svg).+\)"); - if(patt.test(value)){ - results['svginurl'] = results['svginurl'] || {count : 0} - results['svginurl'].count++; - break; - // alert("found a url that has svg in it!") - } - // } - // } + var patt = new RegExp("url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)"); + if(patt.test(value)){ + results['SVGInUrl'] = results['SVGInUrl'] || {count : 0} + results['SVGInUrl'].count++; + break; + } } - } - - // for(var n = 0; n < element.CSSUsage.length; n++) { - // if(element.CSSUsage[n].value) - // if(element.attributes[n].name == "url") { - // if(element.attributes[n].value.indexOf(".svg") != -1){ - // results['imgsrc'] = results['imgsrc'] || { count: 0 }; - // results['imgsrc'].count++; - // break; - // } - // } - // } + } return results; }); }(); @@ -1605,8 +1581,8 @@ void function() { void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function SVGSyntaxUsed( element, results) { if(element.nodeName == "svg") { - results['svgHTML'] = results['svgHTML'] || { count: 0 }; - results['svgHTML'].count++; + results['SVGSyntaxUsed'] = results['SVGSyntaxUsed'] || { count: 0 }; + results['SVGSyntaxUsed'].count++; } return results; @@ -1617,26 +1593,52 @@ void function() { /* - RECIPE: SVGUsedOnImage + RECIPE: SVGUsedOnHtmlElementData ------------------------------------------------------------- Author: Description: */ void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnImage( element, results) { - if(element.nodeName == "IMG") { - for(var n = 0; n < element.attributes.length; n++) { - if(element.attributes[n].name == "src") { - if(element.attributes[n].value.indexOf(".svg") != -1){ - results['imgsrc'] = results['imgsrc'] || { count: 0 }; - results['imgsrc'].count++; - break; - } + 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; + }); +}(); + + + + +/* + RECIPE: SVGUsedOnHtmlElementSrc + ------------------------------------------------------------- + Author: + Description: +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnHtmlElementSrc( element, results) { + for(var n = 0; n < element.attributes.length; n++) { + if(element.attributes[n].name == "src") { + if(element.attributes[n].value.indexOf(".svg") != -1){ + results['SVGUsedOnHtmlElementSrc'] = results['SVGUsedOnHtmlElementSrc'] || { count: 0 }; + results['SVGUsedOnHtmlElementSrc'].count++; + break; + } + } + } return results; }); }(); diff --git a/src/cssUsage.js b/src/cssUsage.js index 8c544da..fc6a146 100644 --- a/src/cssUsage.js +++ b/src/cssUsage.js @@ -469,11 +469,9 @@ void function() { try { // value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') // value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // if(false){ - // // Replace url(...) functions by dummies - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - // } + // // 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, " "); @@ -487,15 +485,15 @@ void function() { try { default: - // Replace strings by dummies - value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + // // 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() "); - } + // // Replace url(...) functions by dummies + // if (value.indexOf("(") != -1) { + // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1() "); + // } } diff --git a/src/recipes/SVGInUrl.js b/src/recipes/SVGInUrl.js index c734e22..f621a0b 100644 --- a/src/recipes/SVGInUrl.js +++ b/src/recipes/SVGInUrl.js @@ -1,5 +1,5 @@ /* - RECIPE: SVGUsedOnImage + RECIPE: SVGInUrl ------------------------------------------------------------- Author: Description: @@ -14,36 +14,14 @@ void function() { 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 - //alert(value); - // if(value == "url()"){ - // alert("url found"); - - // value - // var patttemp = new RegExp("url\((.+)\)"); - // if(patttemp.test(value)){ - // alert(value) - var patt = new RegExp("url\(.+(\.svg).+\)"); - if(patt.test(value)){ - results['svginurl'] = results['svginurl'] || {count : 0} - results['svginurl'].count++; - break; - // alert("found a url that has svg in it!") - } - // } - // } + var patt = new RegExp("url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)"); + if(patt.test(value)){ + results['SVGInUrl'] = results['SVGInUrl'] || {count : 0} + results['SVGInUrl'].count++; + break; + } } - } - - // for(var n = 0; n < element.CSSUsage.length; n++) { - // if(element.CSSUsage[n].value) - // if(element.attributes[n].name == "url") { - // if(element.attributes[n].value.indexOf(".svg") != -1){ - // results['imgsrc'] = results['imgsrc'] || { count: 0 }; - // results['imgsrc'].count++; - // break; - // } - // } - // } + } return results; }); }(); diff --git a/src/recipes/SVGSyntaxUsed.js b/src/recipes/SVGSyntaxUsed.js index 4894d17..6f10a0f 100644 --- a/src/recipes/SVGSyntaxUsed.js +++ b/src/recipes/SVGSyntaxUsed.js @@ -8,8 +8,8 @@ void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function SVGSyntaxUsed( element, results) { if(element.nodeName == "svg") { - results['svgHTML'] = results['svgHTML'] || { count: 0 }; - results['svgHTML'].count++; + results['SVGSyntaxUsed'] = results['SVGSyntaxUsed'] || { count: 0 }; + results['SVGSyntaxUsed'].count++; } return results; diff --git a/src/recipes/SVGUsedOnHtmlElementData.js b/src/recipes/SVGUsedOnHtmlElementData.js new file mode 100644 index 0000000..908d11e --- /dev/null +++ b/src/recipes/SVGUsedOnHtmlElementData.js @@ -0,0 +1,28 @@ +/* + RECIPE: SVGUsedOnHtmlElementData + ------------------------------------------------------------- + Author: + Description: +*/ + +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/SVGUsedOnHtmlElementSrc.js b/src/recipes/SVGUsedOnHtmlElementSrc.js new file mode 100644 index 0000000..139be77 --- /dev/null +++ b/src/recipes/SVGUsedOnHtmlElementSrc.js @@ -0,0 +1,24 @@ +/* + RECIPE: SVGUsedOnHtmlElementSrc + ------------------------------------------------------------- + Author: + Description: +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnHtmlElementSrc( element, results) { + for(var n = 0; n < element.attributes.length; n++) { + if(element.attributes[n].name == "src") { + if(element.attributes[n].value.indexOf(".svg") != -1){ + results['SVGUsedOnHtmlElementSrc'] = results['SVGUsedOnHtmlElementSrc'] || { count: 0 }; + results['SVGUsedOnHtmlElementSrc'].count++; + break; + } + } + } + return results; + }); +}(); + + + diff --git a/src/recipes/SVGUsedOnImage.js b/src/recipes/SVGUsedOnImage.js deleted file mode 100644 index 001d1f4..0000000 --- a/src/recipes/SVGUsedOnImage.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - RECIPE: SVGUsedOnImage - ------------------------------------------------------------- - Author: - Description: -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnImage( element, results) { - if(element.nodeName == "IMG") { - for(var n = 0; n < element.attributes.length; n++) { - if(element.attributes[n].name == "src") { - if(element.attributes[n].value.indexOf(".svg") != -1){ - results['imgsrc'] = results['imgsrc'] || { count: 0 }; - results['imgsrc'].count++; - break; - } - } - } - } - - return results; - }); -}(); - - - diff --git a/tests/recipes/svginvestigation.html b/tests/recipes/svginvestigation.html index 90efa52..fe303c7 100644 --- a/tests/recipes/svginvestigation.html +++ b/tests/recipes/svginvestigation.html @@ -13,7 +13,7 @@ padding-bottom: 40px; } - /* file size: 8.2ko | optimized file size: 7.2ko | base64 size: 9.6ko */ + /* file size: 8.2ko | optimized file size: 7.2ko | base64 size: 9.6ko (thanks b64.io!)*/ #svgimg { background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTE3cHgiIGhlaWdodD0iNTRweCIgdmlld0JveD0iLTM4MSAzMzQgMTE3IDU0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IC0zODEgMzM0IDExNyA1NCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PGcgaWQ9Imd1aWRlcyI+PC9nPjxnIGlkPSJMYXllcl8yIj48Zz48Zz48Zz48cG9seWdvbiBmaWxsPSIjMjUwRTBCIiBwb2ludHM9Ii0zNzAuNiwzNjIuNCAtMzU3LjksMzQ0LjcgLTM0OS43LDM2MSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzY2MTMwQyIgcG9pbnRzPSItMzQ5LjMsMzY2IC0zNzAuNiwzNjIuNCAtMzQ5LjcsMzYxICIvPjwvZz48Zz48cG9seWxpbmUgZmlsbD0iIzMzMTIwRSIgcG9pbnRzPSItMzM4LjcsMzcyLjUgLTM0OS4zLDM2NiAtMzQ5LjcsMzYxICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjOEQxODFCIiBwb2ludHM9Ii0zMzguNywzNzIuNSAtMzUyLjYsMzg3LjIgLTM0OS4zLDM2NiAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzcwMEYxMiIgcG9pbnRzPSItMzMzLjYsMzgwLjYgLTM1Mi42LDM4Ny4yIC0zMzguNywzNzIuNSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzNDMTYwQiIgcG9pbnRzPSItMzMzLjYsMzgwLjYgLTMzOC43LDM3Mi41IC0zMjMuNiwzNzMuMSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzg3MTcxOSIgcG9pbnRzPSItMzIzLDM4OCAtMzMzLjYsMzgwLjYgLTMyMy42LDM3My4xICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjNDkxNDBGIiBwb2ludHM9Ii0zMDIuNSwzODggLTMyMywzODggLTMyMy42LDM3My4xICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjMjUwRDBCIiBwb2ludHM9Ii0zMDIuNSwzODggLTMyMy42LDM3My4xIC0zMTIuOCwzNjcuMSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzdGMTkxNyIgcG9pbnRzPSItMzAyLjUsMzg4IC0zMTIuOCwzNjcuMSAtMzAzLjksMzYxICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjOUUxQzIwIiBwb2ludHM9Ii0yNzguMiwzNTQuNSAtMjg3LjksMzUxLjYgLTI2NCwzNTEuNiAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzk5MUUxRiIgcG9pbnRzPSItMzc3LDM2MiAtMzcwLjYsMzYyLjQgLTM3NS4zLDM1Ni41ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjMjUxMzBBIiBwb2ludHM9Ii0zMTIuOCwzNjcuMSAtMzExLjksMzUxLjYgLTMwMy45LDM2MSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzI1MEQwQiIgcG9pbnRzPSItMzcwLjYsMzYyLjQgLTM3NywzNjIgLTM3Mi40LDM2Ny43ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjNTMxMjBDIiBwb2ludHM9Ii0zMjIuMiwzNjAgLTMxMS45LDM1MS42IC0zMTIuOCwzNjcuMSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzgzMTYxOCIgcG9pbnRzPSItMzIzLjYsMzczLjEgLTMyMi4yLDM2MCAtMzEyLjgsMzY3LjEgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM1RDE0MEIiIHBvaW50cz0iLTMzOC43LDM3Mi41IC0zMjIuMiwzNjAgLTMyMy42LDM3My4xICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjOTkxRTFGIiBwb2ludHM9Ii0zNDkuNywzNjEgLTMyMi4yLDM2MCAtMzM4LjcsMzcyLjUgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM5OTFFMUYiIHBvaW50cz0iLTM1Ny45LDM0NC43IC0zNDUuNiwzNDYuNiAtMzQ5LjcsMzYxICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjMzAxNzBEIiBwb2ludHM9Ii0zNDUuNiwzNDYuNiAtMzQ2LjMsMzU4IC0zNDkuNywzNjEgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM0QTE3MEQiIHBvaW50cz0iLTMyOCwzNDIuMiAtMzIyLjIsMzYwIC0zNDkuNywzNjEgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM3NDExMTIiIHBvaW50cz0iLTMyOCwzNDIuMiAtMzIxLjYsMzQxLjggLTMyMi4yLDM2MCAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzlFMUMyMCIgcG9pbnRzPSItMzIxLjYsMzQxLjggLTMxMS45LDM1MS42IC0zMjIuMiwzNjAgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM2QjBEMEUiIHBvaW50cz0iLTMyMS42LDM0MS44IC0zMTMuMSwzMzQuOCAtMzExLjksMzUxLjYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiMyODBGMEQiIHBvaW50cz0iLTMxMy4xLDMzNC44IC0zMDEuMiwzMzYuNiAtMzExLjksMzUxLjYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM1MzEyMEMiIHBvaW50cz0iLTMwMS4yLDMzNi42IC0yOTguMiwzNDYgLTMxMS45LDM1MS42ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjOTYxQjFFIiBwb2ludHM9Ii0yOTguMiwzNDYgLTMwMy45LDM2MSAtMzExLjksMzUxLjYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiNBQzFFMjMiIHBvaW50cz0iLTI5OC4yLDM0NiAtMjg5LjQsMzYzLjEgLTMwMy45LDM2MSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzU0MTMwQiIgcG9pbnRzPSItMjg3LjksMzUxLjYgLTI4OS40LDM2My4xIC0yOTguMiwzNDYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiMyODBGMEQiIHBvaW50cz0iLTI3OC4yLDM1NC41IC0yODkuNCwzNjMuMSAtMjg3LjksMzUxLjYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiMzQjE0MEUiIHBvaW50cz0iLTMwMy45LDM2MSAtMjg5LjQsMzYzLjEgLTMwMi41LDM4OCAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzIxMEQwQyIgcG9pbnRzPSItMjg5LjQsMzYzLjEgLTI3OSwzNjkuNSAtMzAyLjUsMzg4ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjNkIxNjBGIiBwb2ludHM9Ii0yNzguMiwzNTQuNSAtMjc5LDM2OS41IC0yODkuNCwzNjMuMSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iI0IwMUYyNCIgcG9pbnRzPSItMjc4LjIsMzU0LjUgLTI2NCwzNTEuNiAtMjc5LDM2OS41ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjMjEwRDBCIiBwb2ludHM9Ii0zMjgsMzQyLjIgLTM0Ni4zLDM1OCAtMzQ1LjYsMzQ2LjYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiNBMjIwMjEiIHBvaW50cz0iLTMyOCwzNDIuMiAtMzQ1LjYsMzQ2LjYgLTMzOS4xLDMzNCAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzMzMTIwRSIgcG9pbnRzPSItMzU0LjIsMzY4LjEgLTM1MSwzNzYuNiAtMzQ5LjMsMzY2ICIvPjwvZz48Zz48cG9seWxpbmUgZmlsbD0iIzczMTkxQiIgcG9pbnRzPSItMzYxLjIsMzcxLjIgLTM3NS42LDM3Ny44IC0zNzAuNiwzNjIuNCAtMzYxLjIsMzcxLjIgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM0MjEyMTEiIHBvaW50cz0iLTM2MS4yLDM3MS4yIC0zNzAuNiwzNjIuNCAtMzQ5LjMsMzY2ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjNzMxOTFCIiBwb2ludHM9Ii0zNTcuOSwzNDQuNyAtMzcwLjYsMzYyLjQgLTM4MSwzNDkuMSAiLz48L2c+PC9nPjxnPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMzY5LjIsMzU3LjhjLTEuNSwwLTIuMiwwLjUtMi4yLDEuNmMwLDAuNSwwLjIsMC44LDAuNSwxYzAuMywwLjIsMS4xLDAuNCwyLjIsMC42YzEuMiwwLjIsMiwwLjUsMi40LDAuOGMwLjUsMC4zLDAuNywxLDAuNywyYzAsMS0wLjMsMS43LTAuOSwyLjFjLTAuNiwwLjQtMS41LDAuNy0yLjcsMC43Yy0wLjcsMC0xLjYtMC4xLTIuNy0wLjNsLTAuNS0wLjFsMC4xLTFjMS40LDAuMiwyLjUsMC4zLDMuMywwLjNjMC44LDAsMS4zLTAuMSwxLjgtMC40YzAuNC0wLjMsMC42LTAuNywwLjYtMS4zYzAtMC42LTAuMi0xLTAuNS0xLjNjLTAuMy0wLjItMS4xLTAuNC0yLjItMC42Yy0xLjEtMC4yLTEuOS0wLjQtMi40LTAuOGMtMC41LTAuMy0wLjctMC45LTAuNy0xLjljMC0wLjksMC4zLTEuNiwxLTJjMC42LTAuNCwxLjQtMC42LDIuNC0wLjZjMC44LDAsMS43LDAuMSwyLjgsMC4ybDAuNSwwLjFsMCwxQy0zNjcuMywzNTcuOS0zNjguNCwzNTcuOC0zNjkuMiwzNTcuOHoiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNLTM1OC41LDM1Ny45aC0zLjJ2NC43YzAsMS4yLDAuMSwyLDAuMywyLjRjMC4yLDAuNCwwLjYsMC42LDEuMiwwLjZsMS43LTAuMWwwLjEsMWMtMC44LDAuMS0xLjUsMC4yLTEuOSwwLjJjLTEsMC0xLjYtMC4yLTItMC43Yy0wLjQtMC41LTAuNi0xLjQtMC42LTIuN3YtNS4yaC0xLjR2LTFoMS40di0zaDEuMXYzaDMuMlYzNTcuOXoiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNLTM1MC4zLDM1OS43djUuMWMwLDAuNSwwLjUsMC43LDEuMiwwLjhsLTAuMSwwLjljLTEsMC0xLjctMC4zLTIuMS0wLjhjLTEuMiwwLjUtMi40LDAuOC0zLjYsMC44Yy0wLjgsMC0xLjUtMC4yLTEuOS0wLjdjLTAuNC0wLjUtMC43LTEuMi0wLjctMi4xYzAtMC45LDAuMi0xLjYsMC43LTJjMC40LTAuNCwxLjEtMC43LDIuMS0wLjhsMy4yLTAuM3YtMC45YzAtMC43LTAuMi0xLjItMC41LTEuNWMtMC4zLTAuMy0wLjctMC41LTEuMi0wLjVjLTAuOCwwLTEuOSwwLjEtMy4xLDAuMmwtMC42LDAuMWwtMC4xLTAuOWMxLjQtMC4zLDIuNi0wLjQsMy42LTAuNGMxLDAsMS44LDAuMiwyLjMsMC43Qy0zNTAuNSwzNTgtMzUwLjMsMzU4LjctMzUwLjMsMzU5Ljd6IE0tMzU2LjIsMzYzLjdjMCwxLjMsMC41LDEuOSwxLjYsMS45YzAuNSwwLDEtMC4xLDEuNS0wLjJjMC41LTAuMSwxLTAuMiwxLjMtMC4zbDAuNS0wLjJ2LTMuNGwtMy4xLDAuM2MtMC42LDAuMS0xLjEsMC4yLTEuMywwLjVDLTM1Ni4xLDM2Mi43LTM1Ni4yLDM2My4xLTM1Ni4yLDM2My43eiIvPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMzQ3LjMsMzY2LjR2LTkuNGgxLjF2MS40YzAuNS0wLjMsMS0wLjYsMS43LTAuOWMwLjctMC4zLDEuMy0wLjUsMS45LTAuNnYxLjFjLTAuNSwwLjEtMS4xLDAuMy0xLjcsMC41Yy0wLjYsMC4yLTEuMSwwLjQtMS40LDAuNmwtMC41LDAuM3Y3LjFDLTM0Ni4yLDM2Ni40LTM0Ny4zLDM2Ni40LTM0Ny4zLDM2Ni40eiIvPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMzM2LjEsMzU3LjloLTMuMnY0LjdjMCwxLjIsMC4xLDIsMC4zLDIuNGMwLjIsMC40LDAuNiwwLjYsMS4yLDAuNmwxLjctMC4xbDAuMSwxYy0wLjgsMC4xLTEuNSwwLjItMS45LDAuMmMtMSwwLTEuNi0wLjItMi0wLjdjLTAuNC0wLjUtMC42LTEuNC0wLjYtMi43di01LjJoLTEuNHYtMWgxLjR2LTNoMS4xdjNoMy4yVjM1Ny45eiIvPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMzI4LjQsMzU2LjloMS4xdjkuNGgtMS4xdi0wLjdjLTEsMC42LTEuOSwwLjktMi45LDAuOWMtMS4zLDAtMi4xLTAuMy0yLjUtMWMtMC40LTAuNy0wLjYtMS45LTAuNi0zLjd2LTQuOWgxLjF2NC45YzAsMS41LDAuMSwyLjQsMC40LDIuOWMwLjMsMC41LDAuOSwwLjgsMS44LDAuOGMwLjQsMCwwLjktMC4xLDEuNC0wLjJjMC41LTAuMSwwLjgtMC4zLDEuMS0wLjRsMC40LTAuMkMtMzI4LjQsMzY0LjgtMzI4LjQsMzU2LjktMzI4LjQsMzU2Ljl6Ii8+PHBhdGggZmlsbD0iI0ZGRkZGRiIgZD0iTS0zMjQuNCwzNzAuNnYtMTMuN2gxLjF2MC43YzEtMC42LDItMC45LDMuMS0wLjljMS4xLDAsMS45LDAuNCwyLjQsMS4yYzAuNSwwLjgsMC44LDIsMC44LDMuOGMwLDEuNy0wLjMsMy0wLjksMy44Yy0wLjYsMC44LTEuNywxLjItMy4xLDEuMmMtMC44LDAtMS41LTAuMS0yLjMtMC4ydjQuM0wtMzI0LjQsMzcwLjZMLTMyNC40LDM3MC42eiBNLTMyMC41LDM1Ny44Yy0wLjQsMC0wLjksMC4xLTEuMywwLjJjLTAuNSwwLjEtMC45LDAuMy0xLjEsMC40bC0wLjQsMC4ydjYuN2MwLjksMC4yLDEuNiwwLjIsMi4yLDAuMmMxLjEsMCwxLjgtMC4zLDIuMy0wLjljMC40LTAuNiwwLjctMS42LDAuNy0zYzAtMS40LTAuMi0yLjQtMC42LTNDLTMxOS4xLDM1OC4xLTMxOS43LDM1Ny44LTMyMC41LDM1Ny44eiIvPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMzA3LjUsMzU3LjhjLTEuNSwwLTIuMiwwLjUtMi4yLDEuNmMwLDAuNSwwLjIsMC44LDAuNSwxYzAuMywwLjIsMS4xLDAuNCwyLjIsMC42YzEuMiwwLjIsMiwwLjUsMi40LDAuOGMwLjUsMC4zLDAuNywxLDAuNywyYzAsMS0wLjMsMS43LTAuOSwyLjFjLTAuNiwwLjQtMS41LDAuNy0yLjcsMC43Yy0wLjcsMC0xLjYtMC4xLTIuNy0wLjNsLTAuNS0wLjFsMC4xLTFjMS40LDAuMiwyLjUsMC4zLDMuMywwLjNzMS4zLTAuMSwxLjgtMC40YzAuNC0wLjMsMC42LTAuNywwLjYtMS4zYzAtMC42LTAuMi0xLTAuNS0xLjNjLTAuMy0wLjItMS4xLTAuNC0yLjItMC42Yy0xLjEtMC4yLTEuOS0wLjQtMi40LTAuOGMtMC41LTAuMy0wLjctMC45LTAuNy0xLjljMC0wLjksMC4zLTEuNiwxLTJjMC42LTAuNCwxLjQtMC42LDIuNC0wLjZjMC44LDAsMS43LDAuMSwyLjgsMC4ybDAuNSwwLjFsMCwxQy0zMDUuNiwzNTcuOS0zMDYuNywzNTcuOC0zMDcuNSwzNTcuOHoiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNLTMwMC41LDM2Ni40aC0xLjF2LTEzLjZoMS4xdjQuN2MxLjEtMC41LDIuMS0wLjcsMy4xLTAuN2MxLjMsMCwyLjEsMC4zLDIuNSwxYzAuNCwwLjcsMC42LDEuOSwwLjYsMy43djVoLTEuMXYtNC45YzAtMS40LTAuMS0yLjQtMC40LTIuOWMtMC4zLTAuNS0wLjktMC44LTEuOC0wLjhjLTAuNCwwLTAuOSwwLjEtMS40LDAuMmMtMC41LDAuMS0wLjksMC4yLTEuMSwwLjNsLTAuNCwwLjJDLTMwMC41LDM1OC40LTMwMC41LDM2Ni40LTMwMC41LDM2Ni40eiIvPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMjg1LjMsMzY1LjRsMC42LTAuMWwwLDAuOWMtMS40LDAuMi0yLjYsMC4zLTMuNiwwLjNjLTEuNCwwLTIuMy0wLjQtMi45LTEuMmMtMC41LTAuOC0wLjgtMi0wLjgtMy43YzAtMy4zLDEuMy01LDMuOS01YzEuMiwwLDIuMiwwLjQsMi44LDEuMWMwLjYsMC43LDAuOSwxLjksMC45LDMuNGwwLDAuOWgtNi40YzAsMS4yLDAuMiwyLDAuNiwyLjZjMC40LDAuNiwxLjEsMC44LDIsMC44Qy0yODcuMiwzNjUuNS0yODYuMywzNjUuNS0yODUuMywzNjUuNHogTS0yOTAuOCwzNjEuMmg1LjNjMC0xLjItMC4yLTIuMS0wLjYtMi43Yy0wLjQtMC41LTEuMS0wLjgtMi0wLjhjLTAuOSwwLTEuNiwwLjMtMiwwLjhDLTI5MC42LDM1OS4xLTI5MC44LDM2MC0yOTAuOCwzNjEuMnoiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNLTI4MS45LDM2Ni40di0xMy42aDEuMXYxMy42SC0yODEuOXoiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNLTI3Ny43LDM2Ni40di0xMy42aDEuMXYxMy42SC0yNzcuN3oiLz48L2c+PC9nPjwvZz48L3N2Zz4=); padding-bottom: 40px; @@ -22,20 +22,40 @@ +

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 + +

  - \ No newline at end of file + + + From 0318c9538d077e21e964f91adeb7e7c83012dfee Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Wed, 5 Apr 2017 15:26:37 -0700 Subject: [PATCH 05/13] 5/6 recipes created --- Recipe.min.js | 7 ++++++- cssUsage.src.js | 7 ++++++- src/recipes/SVGInUrl.js | 2 +- src/recipes/SVGUsedOnHtmlElementSrc.js | 5 +++++ tests/recipes/svginvestigation.html | 22 +++++++++++----------- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/Recipe.min.js b/Recipe.min.js index 38975a6..6be4afa 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -1556,7 +1556,7 @@ void function() { 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 - var patt = new RegExp("url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)"); + var patt = new RegExp(/url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)/); if(patt.test(value)){ results['SVGInUrl'] = results['SVGInUrl'] || {count : 0} results['SVGInUrl'].count++; @@ -1630,12 +1630,17 @@ void function() { void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnHtmlElementSrc( element, results) { + var patt = new RegExp(/data\:image\/svg\+xml.+/); for(var n = 0; n < element.attributes.length; n++) { if(element.attributes[n].name == "src") { if(element.attributes[n].value.indexOf(".svg") != -1){ results['SVGUsedOnHtmlElementSrc'] = results['SVGUsedOnHtmlElementSrc'] || { count: 0 }; results['SVGUsedOnHtmlElementSrc'].count++; break; + } else if (patt.test(element.attributes[n].value)){ + results['SVGUsedOnHtmlElementSrcExplicit'] = results['SVGUsedOnHtmlElementSrcExplicit'] || {count : 0} + results['SVGUsedOnHtmlElementSrcExplicit'].count++; + break; } } } diff --git a/cssUsage.src.js b/cssUsage.src.js index a61147c..04170f2 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -1556,7 +1556,7 @@ void function() { 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 - var patt = new RegExp("url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)"); + var patt = new RegExp(/url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)/); if(patt.test(value)){ results['SVGInUrl'] = results['SVGInUrl'] || {count : 0} results['SVGInUrl'].count++; @@ -1630,12 +1630,17 @@ void function() { void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnHtmlElementSrc( element, results) { + var patt = new RegExp(/data\:image\/svg\+xml.+/); for(var n = 0; n < element.attributes.length; n++) { if(element.attributes[n].name == "src") { if(element.attributes[n].value.indexOf(".svg") != -1){ results['SVGUsedOnHtmlElementSrc'] = results['SVGUsedOnHtmlElementSrc'] || { count: 0 }; results['SVGUsedOnHtmlElementSrc'].count++; break; + } else if (patt.test(element.attributes[n].value)){ + results['SVGUsedOnHtmlElementSrcExplicit'] = results['SVGUsedOnHtmlElementSrcExplicit'] || {count : 0} + results['SVGUsedOnHtmlElementSrcExplicit'].count++; + break; } } } diff --git a/src/recipes/SVGInUrl.js b/src/recipes/SVGInUrl.js index f621a0b..4cf73c9 100644 --- a/src/recipes/SVGInUrl.js +++ b/src/recipes/SVGInUrl.js @@ -14,7 +14,7 @@ void function() { 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 - var patt = new RegExp("url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)"); + var patt = new RegExp(/url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)/); if(patt.test(value)){ results['SVGInUrl'] = results['SVGInUrl'] || {count : 0} results['SVGInUrl'].count++; diff --git a/src/recipes/SVGUsedOnHtmlElementSrc.js b/src/recipes/SVGUsedOnHtmlElementSrc.js index 139be77..d51b546 100644 --- a/src/recipes/SVGUsedOnHtmlElementSrc.js +++ b/src/recipes/SVGUsedOnHtmlElementSrc.js @@ -7,12 +7,17 @@ void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnHtmlElementSrc( element, results) { + var patt = new RegExp(/data\:image\/svg\+xml.+/); for(var n = 0; n < element.attributes.length; n++) { if(element.attributes[n].name == "src") { if(element.attributes[n].value.indexOf(".svg") != -1){ results['SVGUsedOnHtmlElementSrc'] = results['SVGUsedOnHtmlElementSrc'] || { count: 0 }; results['SVGUsedOnHtmlElementSrc'].count++; break; + } else if (patt.test(element.attributes[n].value)){ + results['SVGUsedOnHtmlElementSrcExplicit'] = results['SVGUsedOnHtmlElementSrcExplicit'] || {count : 0} + results['SVGUsedOnHtmlElementSrcExplicit'].count++; + break; } } } diff --git a/tests/recipes/svginvestigation.html b/tests/recipes/svginvestigation.html index fe303c7..ab14c2e 100644 --- a/tests/recipes/svginvestigation.html +++ b/tests/recipes/svginvestigation.html @@ -22,7 +22,7 @@ - +

This is text with a SVG border image

@@ -33,28 +33,28 @@

-

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 + - + From 9224c806a9e015e380e1780f3d0e53ff4a1e7e4c Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Fri, 7 Apr 2017 10:27:44 -0700 Subject: [PATCH 06/13] 7/7 recipes implemented --- Recipe.min.js | 70 ++++++++++++++++++----------- cssUsage.src.js | 70 ++++++++++++++++++----------- src/cssUsage.js | 62 +++++++++++++++---------- src/recipes/SVGInUrl.js | 8 +++- tests/recipes/svginvestigation.html | 22 ++++----- 5 files changed, 146 insertions(+), 86 deletions(-) diff --git a/Recipe.min.js b/Recipe.min.js index 6be4afa..cfc7529 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -936,7 +936,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName) { + function createValueArray(value, propertyName, wewantinsidesofurls) { // Trim value on the edges value = value.trim(); @@ -958,17 +958,19 @@ void function() { try { // 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 - // value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - // value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + // Replace strings by dummies + value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') + value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // // Replace url(...) functions by dummies - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); + // 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, " "); @@ -977,28 +979,39 @@ void function() { try { value = value.replace(/[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]*)[}])*[}])*[}])*[}])*[}]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); - + + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/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(!wewantinsidesofurls){ + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/g); + + // 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); + + // 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. + // That ruins everything because when we do .length in the for loop after this, it returns the length of the string, not the array. Ugh. + if( typeof value === 'string' ) { + value = [ value ]; + } return value; } @@ -1182,7 +1195,8 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); + var wewantinsidesofurls = true; + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, wewantinsidesofurls); var values = new Array(); for(var j=specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); @@ -1233,6 +1247,8 @@ void function() { try { // these on the element so we don't have to recompute them knownValues.valuesArray = knownValues.valuesArray || (knownValues.valuesArray = []); + + //TODO: Why is this ruining everything? for(var sv = 0; sv < specifiedValuesArray.length; sv++) { var currentSV = specifiedValuesArray[sv]; if(knownValues.valuesArray.indexOf(currentSV) == -1) { @@ -1556,11 +1572,15 @@ void function() { 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 - var patt = new RegExp(/url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)/); - if(patt.test(value)){ + 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; } } } diff --git a/cssUsage.src.js b/cssUsage.src.js index 04170f2..0e254e9 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -936,7 +936,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName) { + function createValueArray(value, propertyName, wewantinsidesofurls) { // Trim value on the edges value = value.trim(); @@ -958,17 +958,19 @@ void function() { try { // 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 - // value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - // value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + // Replace strings by dummies + value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') + value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // // Replace url(...) functions by dummies - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); + // 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, " "); @@ -977,28 +979,39 @@ void function() { try { value = value.replace(/[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]*)[}])*[}])*[}])*[}])*[}]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); - + + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/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(!wewantinsidesofurls){ + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/g); + + // 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); + + // 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. + // That ruins everything because when we do .length in the for loop after this, it returns the length of the string, not the array. Ugh. + if( typeof value === 'string' ) { + value = [ value ]; + } return value; } @@ -1182,7 +1195,8 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); + var wewantinsidesofurls = true; + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, wewantinsidesofurls); var values = new Array(); for(var j=specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); @@ -1233,6 +1247,8 @@ void function() { try { // these on the element so we don't have to recompute them knownValues.valuesArray = knownValues.valuesArray || (knownValues.valuesArray = []); + + //TODO: Why is this ruining everything? for(var sv = 0; sv < specifiedValuesArray.length; sv++) { var currentSV = specifiedValuesArray[sv]; if(knownValues.valuesArray.indexOf(currentSV) == -1) { @@ -1556,11 +1572,15 @@ void function() { 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 - var patt = new RegExp(/url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)/); - if(patt.test(value)){ + 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; } } } diff --git a/src/cssUsage.js b/src/cssUsage.js index fc6a146..8970bfd 100644 --- a/src/cssUsage.js +++ b/src/cssUsage.js @@ -439,7 +439,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName) { + function createValueArray(value, propertyName, wewantinsidesofurls) { // Trim value on the edges value = value.trim(); @@ -461,17 +461,19 @@ void function() { try { // 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 - // value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') - // value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); + // Replace strings by dummies + value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') + value = value.replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); - // // Replace url(...) functions by dummies - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); - // value = value.replace(/([a-z]?)[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, "$1()"); + // 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, " "); @@ -480,28 +482,39 @@ void function() { try { value = value.replace(/[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]*)[}])*[}])*[}])*[}])*[}]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); - + + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/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(!wewantinsidesofurls){ + // Divide at commas and spaces to separate different values + value = value.split(/\s*(?:,|[/])\s*|\s+/g); + + // 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); + + // 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. + // That ruins everything because when we do .length in the for loop after this, it returns the length of the string, not the array. Ugh. + if( typeof value === 'string' ) { + value = [ value ]; + } return value; } @@ -685,7 +698,8 @@ void function() { try { } // divide the value into simplified components - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey); + var wewantinsidesofurls = true; + var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, wewantinsidesofurls); var values = new Array(); for(var j=specifiedValuesArray.length; j--;) { values.push(CSSUsage.CSSValues.parseValues(specifiedValuesArray[j],normalizedKey)); @@ -736,6 +750,8 @@ void function() { try { // these on the element so we don't have to recompute them knownValues.valuesArray = knownValues.valuesArray || (knownValues.valuesArray = []); + + //TODO: Why is this ruining everything? for(var sv = 0; sv < specifiedValuesArray.length; sv++) { var currentSV = specifiedValuesArray[sv]; if(knownValues.valuesArray.indexOf(currentSV) == -1) { diff --git a/src/recipes/SVGInUrl.js b/src/recipes/SVGInUrl.js index 4cf73c9..2a7e0fd 100644 --- a/src/recipes/SVGInUrl.js +++ b/src/recipes/SVGInUrl.js @@ -14,11 +14,15 @@ void function() { 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 - var patt = new RegExp(/url\((data\:image\/svg\+xml.+)|(.+\.svg.?)\)/); - if(patt.test(value)){ + 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; } } } diff --git a/tests/recipes/svginvestigation.html b/tests/recipes/svginvestigation.html index ab14c2e..7fb41d2 100644 --- a/tests/recipes/svginvestigation.html +++ b/tests/recipes/svginvestigation.html @@ -16,7 +16,6 @@ /* file size: 8.2ko | optimized file size: 7.2ko | base64 size: 9.6ko (thanks b64.io!)*/ #svgimg { background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTE3cHgiIGhlaWdodD0iNTRweCIgdmlld0JveD0iLTM4MSAzMzQgMTE3IDU0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IC0zODEgMzM0IDExNyA1NCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PGcgaWQ9Imd1aWRlcyI+PC9nPjxnIGlkPSJMYXllcl8yIj48Zz48Zz48Zz48cG9seWdvbiBmaWxsPSIjMjUwRTBCIiBwb2ludHM9Ii0zNzAuNiwzNjIuNCAtMzU3LjksMzQ0LjcgLTM0OS43LDM2MSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzY2MTMwQyIgcG9pbnRzPSItMzQ5LjMsMzY2IC0zNzAuNiwzNjIuNCAtMzQ5LjcsMzYxICIvPjwvZz48Zz48cG9seWxpbmUgZmlsbD0iIzMzMTIwRSIgcG9pbnRzPSItMzM4LjcsMzcyLjUgLTM0OS4zLDM2NiAtMzQ5LjcsMzYxICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjOEQxODFCIiBwb2ludHM9Ii0zMzguNywzNzIuNSAtMzUyLjYsMzg3LjIgLTM0OS4zLDM2NiAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzcwMEYxMiIgcG9pbnRzPSItMzMzLjYsMzgwLjYgLTM1Mi42LDM4Ny4yIC0zMzguNywzNzIuNSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzNDMTYwQiIgcG9pbnRzPSItMzMzLjYsMzgwLjYgLTMzOC43LDM3Mi41IC0zMjMuNiwzNzMuMSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzg3MTcxOSIgcG9pbnRzPSItMzIzLDM4OCAtMzMzLjYsMzgwLjYgLTMyMy42LDM3My4xICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjNDkxNDBGIiBwb2ludHM9Ii0zMDIuNSwzODggLTMyMywzODggLTMyMy42LDM3My4xICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjMjUwRDBCIiBwb2ludHM9Ii0zMDIuNSwzODggLTMyMy42LDM3My4xIC0zMTIuOCwzNjcuMSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzdGMTkxNyIgcG9pbnRzPSItMzAyLjUsMzg4IC0zMTIuOCwzNjcuMSAtMzAzLjksMzYxICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjOUUxQzIwIiBwb2ludHM9Ii0yNzguMiwzNTQuNSAtMjg3LjksMzUxLjYgLTI2NCwzNTEuNiAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzk5MUUxRiIgcG9pbnRzPSItMzc3LDM2MiAtMzcwLjYsMzYyLjQgLTM3NS4zLDM1Ni41ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjMjUxMzBBIiBwb2ludHM9Ii0zMTIuOCwzNjcuMSAtMzExLjksMzUxLjYgLTMwMy45LDM2MSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzI1MEQwQiIgcG9pbnRzPSItMzcwLjYsMzYyLjQgLTM3NywzNjIgLTM3Mi40LDM2Ny43ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjNTMxMjBDIiBwb2ludHM9Ii0zMjIuMiwzNjAgLTMxMS45LDM1MS42IC0zMTIuOCwzNjcuMSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzgzMTYxOCIgcG9pbnRzPSItMzIzLjYsMzczLjEgLTMyMi4yLDM2MCAtMzEyLjgsMzY3LjEgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM1RDE0MEIiIHBvaW50cz0iLTMzOC43LDM3Mi41IC0zMjIuMiwzNjAgLTMyMy42LDM3My4xICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjOTkxRTFGIiBwb2ludHM9Ii0zNDkuNywzNjEgLTMyMi4yLDM2MCAtMzM4LjcsMzcyLjUgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM5OTFFMUYiIHBvaW50cz0iLTM1Ny45LDM0NC43IC0zNDUuNiwzNDYuNiAtMzQ5LjcsMzYxICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjMzAxNzBEIiBwb2ludHM9Ii0zNDUuNiwzNDYuNiAtMzQ2LjMsMzU4IC0zNDkuNywzNjEgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM0QTE3MEQiIHBvaW50cz0iLTMyOCwzNDIuMiAtMzIyLjIsMzYwIC0zNDkuNywzNjEgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM3NDExMTIiIHBvaW50cz0iLTMyOCwzNDIuMiAtMzIxLjYsMzQxLjggLTMyMi4yLDM2MCAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzlFMUMyMCIgcG9pbnRzPSItMzIxLjYsMzQxLjggLTMxMS45LDM1MS42IC0zMjIuMiwzNjAgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM2QjBEMEUiIHBvaW50cz0iLTMyMS42LDM0MS44IC0zMTMuMSwzMzQuOCAtMzExLjksMzUxLjYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiMyODBGMEQiIHBvaW50cz0iLTMxMy4xLDMzNC44IC0zMDEuMiwzMzYuNiAtMzExLjksMzUxLjYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM1MzEyMEMiIHBvaW50cz0iLTMwMS4yLDMzNi42IC0yOTguMiwzNDYgLTMxMS45LDM1MS42ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjOTYxQjFFIiBwb2ludHM9Ii0yOTguMiwzNDYgLTMwMy45LDM2MSAtMzExLjksMzUxLjYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiNBQzFFMjMiIHBvaW50cz0iLTI5OC4yLDM0NiAtMjg5LjQsMzYzLjEgLTMwMy45LDM2MSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzU0MTMwQiIgcG9pbnRzPSItMjg3LjksMzUxLjYgLTI4OS40LDM2My4xIC0yOTguMiwzNDYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiMyODBGMEQiIHBvaW50cz0iLTI3OC4yLDM1NC41IC0yODkuNCwzNjMuMSAtMjg3LjksMzUxLjYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiMzQjE0MEUiIHBvaW50cz0iLTMwMy45LDM2MSAtMjg5LjQsMzYzLjEgLTMwMi41LDM4OCAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzIxMEQwQyIgcG9pbnRzPSItMjg5LjQsMzYzLjEgLTI3OSwzNjkuNSAtMzAyLjUsMzg4ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjNkIxNjBGIiBwb2ludHM9Ii0yNzguMiwzNTQuNSAtMjc5LDM2OS41IC0yODkuNCwzNjMuMSAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iI0IwMUYyNCIgcG9pbnRzPSItMjc4LjIsMzU0LjUgLTI2NCwzNTEuNiAtMjc5LDM2OS41ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjMjEwRDBCIiBwb2ludHM9Ii0zMjgsMzQyLjIgLTM0Ni4zLDM1OCAtMzQ1LjYsMzQ2LjYgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiNBMjIwMjEiIHBvaW50cz0iLTMyOCwzNDIuMiAtMzQ1LjYsMzQ2LjYgLTMzOS4xLDMzNCAiLz48L2c+PGc+PHBvbHlnb24gZmlsbD0iIzMzMTIwRSIgcG9pbnRzPSItMzU0LjIsMzY4LjEgLTM1MSwzNzYuNiAtMzQ5LjMsMzY2ICIvPjwvZz48Zz48cG9seWxpbmUgZmlsbD0iIzczMTkxQiIgcG9pbnRzPSItMzYxLjIsMzcxLjIgLTM3NS42LDM3Ny44IC0zNzAuNiwzNjIuNCAtMzYxLjIsMzcxLjIgIi8+PC9nPjxnPjxwb2x5Z29uIGZpbGw9IiM0MjEyMTEiIHBvaW50cz0iLTM2MS4yLDM3MS4yIC0zNzAuNiwzNjIuNCAtMzQ5LjMsMzY2ICIvPjwvZz48Zz48cG9seWdvbiBmaWxsPSIjNzMxOTFCIiBwb2ludHM9Ii0zNTcuOSwzNDQuNyAtMzcwLjYsMzYyLjQgLTM4MSwzNDkuMSAiLz48L2c+PC9nPjxnPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMzY5LjIsMzU3LjhjLTEuNSwwLTIuMiwwLjUtMi4yLDEuNmMwLDAuNSwwLjIsMC44LDAuNSwxYzAuMywwLjIsMS4xLDAuNCwyLjIsMC42YzEuMiwwLjIsMiwwLjUsMi40LDAuOGMwLjUsMC4zLDAuNywxLDAuNywyYzAsMS0wLjMsMS43LTAuOSwyLjFjLTAuNiwwLjQtMS41LDAuNy0yLjcsMC43Yy0wLjcsMC0xLjYtMC4xLTIuNy0wLjNsLTAuNS0wLjFsMC4xLTFjMS40LDAuMiwyLjUsMC4zLDMuMywwLjNjMC44LDAsMS4zLTAuMSwxLjgtMC40YzAuNC0wLjMsMC42LTAuNywwLjYtMS4zYzAtMC42LTAuMi0xLTAuNS0xLjNjLTAuMy0wLjItMS4xLTAuNC0yLjItMC42Yy0xLjEtMC4yLTEuOS0wLjQtMi40LTAuOGMtMC41LTAuMy0wLjctMC45LTAuNy0xLjljMC0wLjksMC4zLTEuNiwxLTJjMC42LTAuNCwxLjQtMC42LDIuNC0wLjZjMC44LDAsMS43LDAuMSwyLjgsMC4ybDAuNSwwLjFsMCwxQy0zNjcuMywzNTcuOS0zNjguNCwzNTcuOC0zNjkuMiwzNTcuOHoiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNLTM1OC41LDM1Ny45aC0zLjJ2NC43YzAsMS4yLDAuMSwyLDAuMywyLjRjMC4yLDAuNCwwLjYsMC42LDEuMiwwLjZsMS43LTAuMWwwLjEsMWMtMC44LDAuMS0xLjUsMC4yLTEuOSwwLjJjLTEsMC0xLjYtMC4yLTItMC43Yy0wLjQtMC41LTAuNi0xLjQtMC42LTIuN3YtNS4yaC0xLjR2LTFoMS40di0zaDEuMXYzaDMuMlYzNTcuOXoiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNLTM1MC4zLDM1OS43djUuMWMwLDAuNSwwLjUsMC43LDEuMiwwLjhsLTAuMSwwLjljLTEsMC0xLjctMC4zLTIuMS0wLjhjLTEuMiwwLjUtMi40LDAuOC0zLjYsMC44Yy0wLjgsMC0xLjUtMC4yLTEuOS0wLjdjLTAuNC0wLjUtMC43LTEuMi0wLjctMi4xYzAtMC45LDAuMi0xLjYsMC43LTJjMC40LTAuNCwxLjEtMC43LDIuMS0wLjhsMy4yLTAuM3YtMC45YzAtMC43LTAuMi0xLjItMC41LTEuNWMtMC4zLTAuMy0wLjctMC41LTEuMi0wLjVjLTAuOCwwLTEuOSwwLjEtMy4xLDAuMmwtMC42LDAuMWwtMC4xLTAuOWMxLjQtMC4zLDIuNi0wLjQsMy42LTAuNGMxLDAsMS44LDAuMiwyLjMsMC43Qy0zNTAuNSwzNTgtMzUwLjMsMzU4LjctMzUwLjMsMzU5Ljd6IE0tMzU2LjIsMzYzLjdjMCwxLjMsMC41LDEuOSwxLjYsMS45YzAuNSwwLDEtMC4xLDEuNS0wLjJjMC41LTAuMSwxLTAuMiwxLjMtMC4zbDAuNS0wLjJ2LTMuNGwtMy4xLDAuM2MtMC42LDAuMS0xLjEsMC4yLTEuMywwLjVDLTM1Ni4xLDM2Mi43LTM1Ni4yLDM2My4xLTM1Ni4yLDM2My43eiIvPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMzQ3LjMsMzY2LjR2LTkuNGgxLjF2MS40YzAuNS0wLjMsMS0wLjYsMS43LTAuOWMwLjctMC4zLDEuMy0wLjUsMS45LTAuNnYxLjFjLTAuNSwwLjEtMS4xLDAuMy0xLjcsMC41Yy0wLjYsMC4yLTEuMSwwLjQtMS40LDAuNmwtMC41LDAuM3Y3LjFDLTM0Ni4yLDM2Ni40LTM0Ny4zLDM2Ni40LTM0Ny4zLDM2Ni40eiIvPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMzM2LjEsMzU3LjloLTMuMnY0LjdjMCwxLjIsMC4xLDIsMC4zLDIuNGMwLjIsMC40LDAuNiwwLjYsMS4yLDAuNmwxLjctMC4xbDAuMSwxYy0wLjgsMC4xLTEuNSwwLjItMS45LDAuMmMtMSwwLTEuNi0wLjItMi0wLjdjLTAuNC0wLjUtMC42LTEuNC0wLjYtMi43di01LjJoLTEuNHYtMWgxLjR2LTNoMS4xdjNoMy4yVjM1Ny45eiIvPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMzI4LjQsMzU2LjloMS4xdjkuNGgtMS4xdi0wLjdjLTEsMC42LTEuOSwwLjktMi45LDAuOWMtMS4zLDAtMi4xLTAuMy0yLjUtMWMtMC40LTAuNy0wLjYtMS45LTAuNi0zLjd2LTQuOWgxLjF2NC45YzAsMS41LDAuMSwyLjQsMC40LDIuOWMwLjMsMC41LDAuOSwwLjgsMS44LDAuOGMwLjQsMCwwLjktMC4xLDEuNC0wLjJjMC41LTAuMSwwLjgtMC4zLDEuMS0wLjRsMC40LTAuMkMtMzI4LjQsMzY0LjgtMzI4LjQsMzU2LjktMzI4LjQsMzU2Ljl6Ii8+PHBhdGggZmlsbD0iI0ZGRkZGRiIgZD0iTS0zMjQuNCwzNzAuNnYtMTMuN2gxLjF2MC43YzEtMC42LDItMC45LDMuMS0wLjljMS4xLDAsMS45LDAuNCwyLjQsMS4yYzAuNSwwLjgsMC44LDIsMC44LDMuOGMwLDEuNy0wLjMsMy0wLjksMy44Yy0wLjYsMC44LTEuNywxLjItMy4xLDEuMmMtMC44LDAtMS41LTAuMS0yLjMtMC4ydjQuM0wtMzI0LjQsMzcwLjZMLTMyNC40LDM3MC42eiBNLTMyMC41LDM1Ny44Yy0wLjQsMC0wLjksMC4xLTEuMywwLjJjLTAuNSwwLjEtMC45LDAuMy0xLjEsMC40bC0wLjQsMC4ydjYuN2MwLjksMC4yLDEuNiwwLjIsMi4yLDAuMmMxLjEsMCwxLjgtMC4zLDIuMy0wLjljMC40LTAuNiwwLjctMS42LDAuNy0zYzAtMS40LTAuMi0yLjQtMC42LTNDLTMxOS4xLDM1OC4xLTMxOS43LDM1Ny44LTMyMC41LDM1Ny44eiIvPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMzA3LjUsMzU3LjhjLTEuNSwwLTIuMiwwLjUtMi4yLDEuNmMwLDAuNSwwLjIsMC44LDAuNSwxYzAuMywwLjIsMS4xLDAuNCwyLjIsMC42YzEuMiwwLjIsMiwwLjUsMi40LDAuOGMwLjUsMC4zLDAuNywxLDAuNywyYzAsMS0wLjMsMS43LTAuOSwyLjFjLTAuNiwwLjQtMS41LDAuNy0yLjcsMC43Yy0wLjcsMC0xLjYtMC4xLTIuNy0wLjNsLTAuNS0wLjFsMC4xLTFjMS40LDAuMiwyLjUsMC4zLDMuMywwLjNzMS4zLTAuMSwxLjgtMC40YzAuNC0wLjMsMC42LTAuNywwLjYtMS4zYzAtMC42LTAuMi0xLTAuNS0xLjNjLTAuMy0wLjItMS4xLTAuNC0yLjItMC42Yy0xLjEtMC4yLTEuOS0wLjQtMi40LTAuOGMtMC41LTAuMy0wLjctMC45LTAuNy0xLjljMC0wLjksMC4zLTEuNiwxLTJjMC42LTAuNCwxLjQtMC42LDIuNC0wLjZjMC44LDAsMS43LDAuMSwyLjgsMC4ybDAuNSwwLjFsMCwxQy0zMDUuNiwzNTcuOS0zMDYuNywzNTcuOC0zMDcuNSwzNTcuOHoiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNLTMwMC41LDM2Ni40aC0xLjF2LTEzLjZoMS4xdjQuN2MxLjEtMC41LDIuMS0wLjcsMy4xLTAuN2MxLjMsMCwyLjEsMC4zLDIuNSwxYzAuNCwwLjcsMC42LDEuOSwwLjYsMy43djVoLTEuMXYtNC45YzAtMS40LTAuMS0yLjQtMC40LTIuOWMtMC4zLTAuNS0wLjktMC44LTEuOC0wLjhjLTAuNCwwLTAuOSwwLjEtMS40LDAuMmMtMC41LDAuMS0wLjksMC4yLTEuMSwwLjNsLTAuNCwwLjJDLTMwMC41LDM1OC40LTMwMC41LDM2Ni40LTMwMC41LDM2Ni40eiIvPjxwYXRoIGZpbGw9IiNGRkZGRkYiIGQ9Ik0tMjg1LjMsMzY1LjRsMC42LTAuMWwwLDAuOWMtMS40LDAuMi0yLjYsMC4zLTMuNiwwLjNjLTEuNCwwLTIuMy0wLjQtMi45LTEuMmMtMC41LTAuOC0wLjgtMi0wLjgtMy43YzAtMy4zLDEuMy01LDMuOS01YzEuMiwwLDIuMiwwLjQsMi44LDEuMWMwLjYsMC43LDAuOSwxLjksMC45LDMuNGwwLDAuOWgtNi40YzAsMS4yLDAuMiwyLDAuNiwyLjZjMC40LDAuNiwxLjEsMC44LDIsMC44Qy0yODcuMiwzNjUuNS0yODYuMywzNjUuNS0yODUuMywzNjUuNHogTS0yOTAuOCwzNjEuMmg1LjNjMC0xLjItMC4yLTIuMS0wLjYtMi43Yy0wLjQtMC41LTEuMS0wLjgtMi0wLjhjLTAuOSwwLTEuNiwwLjMtMiwwLjhDLTI5MC42LDM1OS4xLTI5MC44LDM2MC0yOTAuOCwzNjEuMnoiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNLTI4MS45LDM2Ni40di0xMy42aDEuMXYxMy42SC0yODEuOXoiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNLTI3Ny43LDM2Ni40di0xMy42aDEuMXYxMy42SC0yNzcuN3oiLz48L2c+PC9nPjwvZz48L3N2Zz4=); - padding-bottom: 40px; } @@ -33,28 +32,29 @@

- +

- +

- +

- +

+ - + From 96154f2f7ae366b0926bd572e8776d8ff7916a91 Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Fri, 7 Apr 2017 10:52:19 -0700 Subject: [PATCH 07/13] Cleaning things up --- src/cssUsage.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cssUsage.js b/src/cssUsage.js index 8970bfd..e370639 100644 --- a/src/cssUsage.js +++ b/src/cssUsage.js @@ -750,8 +750,6 @@ void function() { try { // these on the element so we don't have to recompute them knownValues.valuesArray = knownValues.valuesArray || (knownValues.valuesArray = []); - - //TODO: Why is this ruining everything? for(var sv = 0; sv < specifiedValuesArray.length; sv++) { var currentSV = specifiedValuesArray[sv]; if(knownValues.valuesArray.indexOf(currentSV) == -1) { From 77ec7085dc884ef9faf69a493f47197e065e1d1d Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Fri, 7 Apr 2017 10:56:59 -0700 Subject: [PATCH 08/13] Moving the recipe-template back out of archive --- src/recipes/{archive => }/recipe-template.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/recipes/{archive => }/recipe-template.js (100%) diff --git a/src/recipes/archive/recipe-template.js b/src/recipes/recipe-template.js similarity index 100% rename from src/recipes/archive/recipe-template.js rename to src/recipes/recipe-template.js From 2940822e2d216ac725bddfe36d9eddcdd4dfb622 Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Fri, 7 Apr 2017 11:26:06 -0700 Subject: [PATCH 09/13] More clean up --- src/cssUsage.js | 18 +++++++++++++----- tests/recipes/svginvestigation.html | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/cssUsage.js b/src/cssUsage.js index e370639..d6ca0b2 100644 --- a/src/cssUsage.js +++ b/src/cssUsage.js @@ -459,6 +459,9 @@ 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); @@ -483,6 +486,9 @@ void function() { try { value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/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); break; @@ -492,9 +498,6 @@ void function() { try { // Don't divide commas and spaces if we want the inside of Url values if(!wewantinsidesofurls){ - // Divide at commas and spaces to separate different values - value = value.split(/\s*(?:,|[/])\s*|\s+/g); - // Replace strings by dummies value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); @@ -504,10 +507,15 @@ void function() { try { 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, " "); + // 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. diff --git a/tests/recipes/svginvestigation.html b/tests/recipes/svginvestigation.html index 7fb41d2..ddf2413 100644 --- a/tests/recipes/svginvestigation.html +++ b/tests/recipes/svginvestigation.html @@ -2,7 +2,7 @@ - Max Width on Replaced Elements using % + SVG Investigation From 9dfab18155a5b9da6e9272efd32fce347f5b94d0 Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Fri, 7 Apr 2017 11:43:58 -0700 Subject: [PATCH 10/13] uploading new recipe file --- Recipe.min.js | 33 ++++++++++++++++++++++++++------- cssUsage.src.js | 33 ++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/Recipe.min.js b/Recipe.min.js index cfc7529..f8bf403 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -956,6 +956,9 @@ 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); @@ -980,6 +983,9 @@ void function() { try { value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/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); break; @@ -989,9 +995,6 @@ void function() { try { // Don't divide commas and spaces if we want the inside of Url values if(!wewantinsidesofurls){ - // Divide at commas and spaces to separate different values - value = value.split(/\s*(?:,|[/])\s*|\s+/g); - // Replace strings by dummies value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); @@ -1001,10 +1004,15 @@ void function() { try { 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, " "); + // 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. @@ -1247,8 +1255,6 @@ void function() { try { // these on the element so we don't have to recompute them knownValues.valuesArray = knownValues.valuesArray || (knownValues.valuesArray = []); - - //TODO: Why is this ruining everything? for(var sv = 0; sv < specifiedValuesArray.length; sv++) { var currentSV = specifiedValuesArray[sv]; if(knownValues.valuesArray.indexOf(currentSV) == -1) { @@ -1556,6 +1562,19 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); +/* + RECIPE: + ------------------------------------------------------------- + Author: + Description: + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function ( element, results) { + return results; + }); +}(); + +*/ /* RECIPE: SVGInUrl ------------------------------------------------------------- diff --git a/cssUsage.src.js b/cssUsage.src.js index 0e254e9..a9d1e6c 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -956,6 +956,9 @@ 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); @@ -980,6 +983,9 @@ void function() { try { value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/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); break; @@ -989,9 +995,6 @@ void function() { try { // Don't divide commas and spaces if we want the inside of Url values if(!wewantinsidesofurls){ - // Divide at commas and spaces to separate different values - value = value.split(/\s*(?:,|[/])\s*|\s+/g); - // Replace strings by dummies value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); @@ -1001,10 +1004,15 @@ void function() { try { 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, " "); + // 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. @@ -1247,8 +1255,6 @@ void function() { try { // these on the element so we don't have to recompute them knownValues.valuesArray = knownValues.valuesArray || (knownValues.valuesArray = []); - - //TODO: Why is this ruining everything? for(var sv = 0; sv < specifiedValuesArray.length; sv++) { var currentSV = specifiedValuesArray[sv]; if(knownValues.valuesArray.indexOf(currentSV) == -1) { @@ -1556,6 +1562,19 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); +/* + RECIPE: + ------------------------------------------------------------- + Author: + Description: + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function ( element, results) { + return results; + }); +}(); + +*/ /* RECIPE: SVGInUrl ------------------------------------------------------------- From 9d70a310da777b76522da13d54b7188898c36fdc Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Thu, 19 Oct 2017 16:58:47 -0700 Subject: [PATCH 11/13] cleaning up code before PR --- Recipe.min.js | 17 +++++------------ cssUsage.src.js | 17 +++++------------ src/cssUsage.js | 17 +++++------------ 3 files changed, 15 insertions(+), 36 deletions(-) diff --git a/Recipe.min.js b/Recipe.min.js index afca7ef..d238fc4 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -1099,7 +1099,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName, wewantinsidesofurls) { + function createValueArray(value, propertyName, stripUrlValue) { // Trim value on the edges value = value.trim(); @@ -1145,19 +1145,12 @@ void function() { try { value = value.replace(/[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]*)[}])*[}])*[}])*[}])*[}]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/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); break; default: - // Don't divide commas and spaces if we want the inside of Url values - if(!wewantinsidesofurls){ + if (stripUrlValue){ // Replace strings by dummies value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); @@ -1179,7 +1172,7 @@ void function() { try { // 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. - // That ruins everything because when we do .length in the for loop after this, it returns the length of the string, not the array. Ugh. + // 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 ]; } @@ -1367,8 +1360,8 @@ void function() { try { } // divide the value into simplified components - var wewantinsidesofurls = true; - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, wewantinsidesofurls); + var stripUrlValue = false; + 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/cssUsage.src.js b/cssUsage.src.js index ded3d1a..1f4d973 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -1099,7 +1099,7 @@ void function() { try { /** * This will transform a value into an array of value identifiers */ - function createValueArray(value, propertyName, wewantinsidesofurls) { + function createValueArray(value, propertyName, stripUrlValue) { // Trim value on the edges value = value.trim(); @@ -1145,19 +1145,12 @@ void function() { try { value = value.replace(/[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]*)[}])*[}])*[}])*[}])*[}]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/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); break; default: - // Don't divide commas and spaces if we want the inside of Url values - if(!wewantinsidesofurls){ + if (stripUrlValue){ // Replace strings by dummies value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); @@ -1179,7 +1172,7 @@ void function() { try { // 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. - // That ruins everything because when we do .length in the for loop after this, it returns the length of the string, not the array. Ugh. + // 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 ]; } @@ -1367,8 +1360,8 @@ void function() { try { } // divide the value into simplified components - var wewantinsidesofurls = true; - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, wewantinsidesofurls); + var stripUrlValue = false; + 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/cssUsage.js b/src/cssUsage.js index 7c5b6bd..00127e7 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, wewantinsidesofurls) { + function createValueArray(value, propertyName, stripUrlValue) { // Trim value on the edges value = value.trim(); @@ -648,19 +648,12 @@ void function() { try { value = value.replace(/[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]+|[{](?:[^{}]*)[}])*[}])*[}])*[}])*[}]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/g, " "); value = value.replace(/[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]+|[\[](?:[^\[\]]*)[\]])*[\]])*[\]])*[\]])*[\]]/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); break; default: - // Don't divide commas and spaces if we want the inside of Url values - if(!wewantinsidesofurls){ + if (stripUrlValue){ // Replace strings by dummies value = value.replace(/"([^"\\]|\\[^"\\]|\\\\|\\")*"/g,' ') .replace(/'([^'\\]|\\[^'\\]|\\\\|\\')*'/g,' '); @@ -682,7 +675,7 @@ void function() { try { // 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. - // That ruins everything because when we do .length in the for loop after this, it returns the length of the string, not the array. Ugh. + // 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 ]; } @@ -870,8 +863,8 @@ void function() { try { } // divide the value into simplified components - var wewantinsidesofurls = true; - var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue,normalizedKey, wewantinsidesofurls); + var stripUrlValue = false; + 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)); From d3d1b41418b7e6d2fcfe62f90cb982f7508dfbe8 Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Thu, 19 Oct 2017 17:04:10 -0700 Subject: [PATCH 12/13] minor fixes --- tests/recipes/microsoftedge.svg | 1 + tests/recipes/startupshell.svg | 172 ---------------------------- tests/recipes/svginvestigation.html | 12 +- 3 files changed, 7 insertions(+), 178 deletions(-) create mode 100644 tests/recipes/microsoftedge.svg delete mode 100644 tests/recipes/startupshell.svg 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/startupshell.svg b/tests/recipes/startupshell.svg deleted file mode 100644 index 35d7769..0000000 --- a/tests/recipes/startupshell.svg +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/recipes/svginvestigation.html b/tests/recipes/svginvestigation.html index ddf2413..ab650b1 100644 --- a/tests/recipes/svginvestigation.html +++ b/tests/recipes/svginvestigation.html @@ -9,13 +9,13 @@ @@ -33,22 +33,22 @@

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 - +

From 5e9d1c7917dc8369b2c994d9944477a83ddd2270 Mon Sep 17 00:00:00 2001 From: Joshua Berenhaus Date: Thu, 19 Oct 2017 17:13:14 -0700 Subject: [PATCH 13/13] archiving recipes and cleaning up comments for PR --- Recipe.min.js | 117 +----------------- cssUsage.src.js | 117 +----------------- src/cssUsage.js | 2 +- src/recipes/{ => archive}/SVGInUrl.js | 4 +- src/recipes/{ => archive}/SVGSyntaxUsed.js | 6 +- .../{ => archive}/SVGUsedOnHtmlElementData.js | 4 +- .../{ => archive}/SVGUsedOnHtmlElementSrc.js | 4 +- 7 files changed, 12 insertions(+), 242 deletions(-) rename src/recipes/{ => archive}/SVGInUrl.js (88%) rename src/recipes/{ => archive}/SVGSyntaxUsed.js (76%) rename src/recipes/{ => archive}/SVGUsedOnHtmlElementData.js (87%) rename src/recipes/{ => archive}/SVGUsedOnHtmlElementSrc.js (90%) diff --git a/Recipe.min.js b/Recipe.min.js index d238fc4..ba37864 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -1360,7 +1360,7 @@ void function() { try { } // divide the value into simplified components - var stripUrlValue = false; + var stripUrlValue = true; var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue, normalizedKey, stripUrlValue); var values = new Array(); for(var j = specifiedValuesArray.length; j--;) { @@ -1793,121 +1793,6 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* - RECIPE: SVGInUrl - ------------------------------------------------------------- - Author: - Description: -*/ - -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; - }); -}(); - - - - -/* - RECIPE: - ------------------------------------------------------------- - Author: - Description: -*/ - -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; - }); -}(); - - - - -/* - RECIPE: SVGUsedOnHtmlElementData - ------------------------------------------------------------- - Author: - Description: -*/ - -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; - }); -}(); - - - - -/* - RECIPE: SVGUsedOnHtmlElementSrc - ------------------------------------------------------------- - Author: - Description: -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnHtmlElementSrc( element, results) { - var patt = new RegExp(/data\:image\/svg\+xml.+/); - for(var n = 0; n < element.attributes.length; n++) { - if(element.attributes[n].name == "src") { - if(element.attributes[n].value.indexOf(".svg") != -1){ - results['SVGUsedOnHtmlElementSrc'] = results['SVGUsedOnHtmlElementSrc'] || { count: 0 }; - results['SVGUsedOnHtmlElementSrc'].count++; - break; - } else if (patt.test(element.attributes[n].value)){ - results['SVGUsedOnHtmlElementSrcExplicit'] = results['SVGUsedOnHtmlElementSrcExplicit'] || {count : 0} - results['SVGUsedOnHtmlElementSrcExplicit'].count++; - break; - } - } - } - return results; - }); -}(); - - - - /* RECIPE: z-index on static flex items ------------------------------------------------------------- diff --git a/cssUsage.src.js b/cssUsage.src.js index 1f4d973..64f89ff 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -1360,7 +1360,7 @@ void function() { try { } // divide the value into simplified components - var stripUrlValue = false; + var stripUrlValue = true; var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue, normalizedKey, stripUrlValue); var values = new Array(); for(var j = specifiedValuesArray.length; j--;) { @@ -1793,121 +1793,6 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* - RECIPE: SVGInUrl - ------------------------------------------------------------- - Author: - Description: -*/ - -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; - }); -}(); - - - - -/* - RECIPE: - ------------------------------------------------------------- - Author: - Description: -*/ - -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; - }); -}(); - - - - -/* - RECIPE: SVGUsedOnHtmlElementData - ------------------------------------------------------------- - Author: - Description: -*/ - -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; - }); -}(); - - - - -/* - RECIPE: SVGUsedOnHtmlElementSrc - ------------------------------------------------------------- - Author: - Description: -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function SVGUsedOnHtmlElementSrc( element, results) { - var patt = new RegExp(/data\:image\/svg\+xml.+/); - for(var n = 0; n < element.attributes.length; n++) { - if(element.attributes[n].name == "src") { - if(element.attributes[n].value.indexOf(".svg") != -1){ - results['SVGUsedOnHtmlElementSrc'] = results['SVGUsedOnHtmlElementSrc'] || { count: 0 }; - results['SVGUsedOnHtmlElementSrc'].count++; - break; - } else if (patt.test(element.attributes[n].value)){ - results['SVGUsedOnHtmlElementSrcExplicit'] = results['SVGUsedOnHtmlElementSrcExplicit'] || {count : 0} - results['SVGUsedOnHtmlElementSrcExplicit'].count++; - break; - } - } - } - return results; - }); -}(); - - - - /* RECIPE: z-index on static flex items ------------------------------------------------------------- diff --git a/src/cssUsage.js b/src/cssUsage.js index 00127e7..f05b52d 100644 --- a/src/cssUsage.js +++ b/src/cssUsage.js @@ -863,7 +863,7 @@ void function() { try { } // divide the value into simplified components - var stripUrlValue = false; + var stripUrlValue = true; var specifiedValuesArray = CSSUsage.CSSValues.createValueArray(styleValue, normalizedKey, stripUrlValue); var values = new Array(); for(var j = specifiedValuesArray.length; j--;) { diff --git a/src/recipes/SVGInUrl.js b/src/recipes/archive/SVGInUrl.js similarity index 88% rename from src/recipes/SVGInUrl.js rename to src/recipes/archive/SVGInUrl.js index 2a7e0fd..d3720c0 100644 --- a/src/recipes/SVGInUrl.js +++ b/src/recipes/archive/SVGInUrl.js @@ -1,8 +1,8 @@ /* RECIPE: SVGInUrl ------------------------------------------------------------- - Author: - Description: + Author: Joshua Berenhaus + Description: Find CSS Properties with url("___.svg") or url(data:image/svg+xml___) */ void function() { diff --git a/src/recipes/SVGSyntaxUsed.js b/src/recipes/archive/SVGSyntaxUsed.js similarity index 76% rename from src/recipes/SVGSyntaxUsed.js rename to src/recipes/archive/SVGSyntaxUsed.js index 6f10a0f..6d83c88 100644 --- a/src/recipes/SVGSyntaxUsed.js +++ b/src/recipes/archive/SVGSyntaxUsed.js @@ -1,8 +1,8 @@ /* - RECIPE: + RECIPE: SVGSyntaxUsed ------------------------------------------------------------- - Author: - Description: + Author: Joshua Berenhaus + Description: tag found */ void function() { diff --git a/src/recipes/SVGUsedOnHtmlElementData.js b/src/recipes/archive/SVGUsedOnHtmlElementData.js similarity index 87% rename from src/recipes/SVGUsedOnHtmlElementData.js rename to src/recipes/archive/SVGUsedOnHtmlElementData.js index 908d11e..41205c9 100644 --- a/src/recipes/SVGUsedOnHtmlElementData.js +++ b/src/recipes/archive/SVGUsedOnHtmlElementData.js @@ -1,8 +1,8 @@ /* RECIPE: SVGUsedOnHtmlElementData ------------------------------------------------------------- - Author: - Description: + Author: Joshua Berenhaus + Description: Find instances that match <___ data="___.svg"> or <___ type="image/svg+xml" data="___.svg"> */ void function() { diff --git a/src/recipes/SVGUsedOnHtmlElementSrc.js b/src/recipes/archive/SVGUsedOnHtmlElementSrc.js similarity index 90% rename from src/recipes/SVGUsedOnHtmlElementSrc.js rename to src/recipes/archive/SVGUsedOnHtmlElementSrc.js index d51b546..679e381 100644 --- a/src/recipes/SVGUsedOnHtmlElementSrc.js +++ b/src/recipes/archive/SVGUsedOnHtmlElementSrc.js @@ -1,8 +1,8 @@ /* RECIPE: SVGUsedOnHtmlElementSrc ------------------------------------------------------------- - Author: - Description: + Author: Joshua Berenhaus + Description: Find instances of