From 63019aa78468f34954ab46e32951647bdd22dba3 Mon Sep 17 00:00:00 2001 From: "Thomas Moore (CHAKRA)" Date: Mon, 26 Mar 2018 13:00:53 -0700 Subject: [PATCH 1/6] Adds scriptElemStats to CSSUsage.StyleWalker This recipe allows for statistics to be capture for all script elements on a page, specifically - whether the script is inline or internal - if it has the async or defer attribute - it's parent element (typically, head or body) --- Recipe.min.js | 23 ++ cssUsage.src.js | 545 ++++++++++++++++-------------- src/recipes/scriptelem.js | 22 ++ tests/recipes/scriptElemTest.html | 27 ++ 4 files changed, 362 insertions(+), 255 deletions(-) create mode 100644 src/recipes/scriptelem.js create mode 100644 tests/recipes/scriptElemTest.html diff --git a/Recipe.min.js b/Recipe.min.js index f1937f0..53f118b 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -1820,6 +1820,29 @@ void function() { }); }(); +/* + RECIPE: scriptElemStats + ------------------------------------------------------------- + Author: thomasmo + Description: Collect stats for script elements +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { + if(element.nodeName.toLowerCase() == "script") { + results["data"] = results["data"] || []; + results["data"].push({ + async : element.hasAttribute("async"), + defer : element.hasAttribute("defer"), + external : element.hasAttribute("src"), + parentElem : element.parentNode.nodeName.toLowerCase() + }); + } + + return results; + }); +}(); + // // This file is only here to create the TSV // necessary to collect the data from the crawler diff --git a/cssUsage.src.js b/cssUsage.src.js index 43d4d45..0768b10 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 { @@ -1782,216 +1782,251 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); /* - RECIPE: z-index on static flex items + RECIPE: Edit controls on the web ------------------------------------------------------------- - Author: Francois Remy - Description: Get count of flex items who should create a stacking context but do not really + Author: Grisha Lyukshin + Description: Counts pages that have either input, textarea, or content editable elements */ void function() { - - window.CSSUsage.StyleWalker.recipesToRun.push( function zstaticflex(/*HTML DOM Element*/ element, results) { - if(!element.parentElement) return; - - // the problem happens if the element is a flex item with static position and non-auto z-index - if(getComputedStyle(element.parentElement).display != 'flex') return results; - if(getComputedStyle(element).position != 'static') return results; - if(getComputedStyle(element).zIndex != 'auto') { - results.likely = 1; + window.CSSUsage.StyleWalker.recipesToRun.push( function editControls(/*HTML DOM Element*/ element, results) { + + // we only care about special kind of inputs + if(element.nodeName.toLowerCase() === "input" && + (element.getAttribute("type").toLowerCase() === "email" || + element.getAttribute("type").toLowerCase() === "number" || + element.getAttribute("type").toLowerCase() === "search" || + element.getAttribute("type").toLowerCase() === "tel" || + element.getAttribute("type").toLowerCase() === "url" || + element.getAttribute("type").toLowerCase() === "text")) + { + results["input"] = results["input"] || { count: 0 }; + results["input"].count++; } - - // the problem might happen if z-index could ever be non-auto - if(element.CSSUsage["z-index"] && element.CSSUsage["z-index"].valuesArray.length > 0) { - results.possible = 1; + else if (element.nodeName.toLowerCase() === "textarea") + { + results["textarea"] = results["textarea"] || { count: 0 }; + results["textarea"].count++; } - + else if (element.nodeName.toLowerCase() === "div" || element.nodeName.toLowerCase() === "p" || element.nodeName.toLowerCase() === "table") + { + if(element.getAttribute("contenteditable").toLowerCase() === "true" || element.getAttribute("contenteditable").toLowerCase() === "plain-text") + { + results["contenteditable"] = results["contenteditable"] || { count: 0 }; + results["contenteditable"].count++; + } + } + 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(); +/* + RECIPE: scriptElemStats + ------------------------------------------------------------- + Author: thomasmo + Description: Collect stats for script elements +*/ - currentRowTemplate.push('html'); - convertToTSV(INSTRUMENTATION_RESULTS['html']); - currentRowTemplate.pop(); +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { + if(element.nodeName.toLowerCase() == "script") { + results["data"] = results["data"] || []; + results["data"].push({ + async : element.hasAttribute("async"), + defer : element.hasAttribute("defer"), + external : element.hasAttribute("src"), + parentElem : element.parentNode.nodeName.toLowerCase() + }); + } - 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; - } + 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; + } + + } }; // // Execution scheduler: diff --git a/src/recipes/scriptelem.js b/src/recipes/scriptelem.js new file mode 100644 index 0000000..dd86579 --- /dev/null +++ b/src/recipes/scriptelem.js @@ -0,0 +1,22 @@ +/* + RECIPE: scriptElemStats + ------------------------------------------------------------- + Author: thomasmo + Description: Collect stats for script elements +*/ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { + if(element.nodeName.toLowerCase() == "script") { + results["data"] = results["data"] || []; + results["data"].push({ + async : element.hasAttribute("async"), + defer : element.hasAttribute("defer"), + external : element.hasAttribute("src"), + parentElem : element.parentNode.nodeName.toLowerCase() + }); + } + + return results; + }); +}(); diff --git a/tests/recipes/scriptElemTest.html b/tests/recipes/scriptElemTest.html new file mode 100644 index 0000000..aa4334a --- /dev/null +++ b/tests/recipes/scriptElemTest.html @@ -0,0 +1,27 @@ + + + + + + + + + + +Tests scriptElemStats + +To see results in F12 easily, paste + window.RecipeResults.scriptElemStats.data) + + + + + + \ No newline at end of file From 633620eb194b9ea4cb4f21389290d34ae69d4f62 Mon Sep 17 00:00:00 2001 From: "Thomas Moore (CHAKRA)" Date: Mon, 26 Mar 2018 13:16:34 -0700 Subject: [PATCH 2/6] Update scriptElemStats result object to follow conventions --- Recipe.min.js | 12 ++++++++---- cssUsage.src.js | 12 ++++++++---- src/recipes/scriptelem.js | 12 ++++++++---- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Recipe.min.js b/Recipe.min.js index 53f118b..d2fdf58 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -1831,11 +1831,15 @@ void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { if(element.nodeName.toLowerCase() == "script") { results["data"] = results["data"] || []; + parentElemName = element.parentNode.nodeName.toLowerCase(); results["data"].push({ - async : element.hasAttribute("async"), - defer : element.hasAttribute("defer"), - external : element.hasAttribute("src"), - parentElem : element.parentNode.nodeName.toLowerCase() + async : element.hasAttribute("async") ? 1 : 0, + defer : element.hasAttribute("defer") ? 1 : 0, + external : element.hasAttribute("src") ? 1 : 0, + parentElem : { + head : (parentElemName === "head") ? 1 : 0, + body : (parentElemName === "body") ? 1 : 0 + } }); } diff --git a/cssUsage.src.js b/cssUsage.src.js index 0768b10..43878e7 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -1831,11 +1831,15 @@ void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { if(element.nodeName.toLowerCase() == "script") { results["data"] = results["data"] || []; + parentElemName = element.parentNode.nodeName.toLowerCase(); results["data"].push({ - async : element.hasAttribute("async"), - defer : element.hasAttribute("defer"), - external : element.hasAttribute("src"), - parentElem : element.parentNode.nodeName.toLowerCase() + async : element.hasAttribute("async") ? 1 : 0, + defer : element.hasAttribute("defer") ? 1 : 0, + external : element.hasAttribute("src") ? 1 : 0, + parentElem : { + head : (parentElemName === "head") ? 1 : 0, + body : (parentElemName === "body") ? 1 : 0 + } }); } diff --git a/src/recipes/scriptelem.js b/src/recipes/scriptelem.js index dd86579..02a1cda 100644 --- a/src/recipes/scriptelem.js +++ b/src/recipes/scriptelem.js @@ -9,11 +9,15 @@ void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { if(element.nodeName.toLowerCase() == "script") { results["data"] = results["data"] || []; + parentElemName = element.parentNode.nodeName.toLowerCase(); results["data"].push({ - async : element.hasAttribute("async"), - defer : element.hasAttribute("defer"), - external : element.hasAttribute("src"), - parentElem : element.parentNode.nodeName.toLowerCase() + async : element.hasAttribute("async") ? 1 : 0, + defer : element.hasAttribute("defer") ? 1 : 0, + external : element.hasAttribute("src") ? 1 : 0, + parentElem : { + head : (parentElemName === "head") ? 1 : 0, + body : (parentElemName === "body") ? 1 : 0 + } }); } From a9a09f14e0ff76bbce6f566ec3bb302e9df9b2d5 Mon Sep 17 00:00:00 2001 From: "Thomas Moore (CHAKRA)" Date: Mon, 26 Mar 2018 13:54:17 -0700 Subject: [PATCH 3/6] Remove recipe not needed for script stats --- Recipe.min.js | 39 ----------------------- cssUsage.src.js | 39 ----------------------- src/recipes/{ => archive}/editControls.js | 0 3 files changed, 78 deletions(-) rename src/recipes/{ => archive}/editControls.js (100%) diff --git a/Recipe.min.js b/Recipe.min.js index d2fdf58..6a7516d 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -1781,45 +1781,6 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* - RECIPE: Edit controls on the web - ------------------------------------------------------------- - Author: Grisha Lyukshin - Description: Counts pages that have either input, textarea, or content editable elements -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function editControls(/*HTML DOM Element*/ element, results) { - - // we only care about special kind of inputs - if(element.nodeName.toLowerCase() === "input" && - (element.getAttribute("type").toLowerCase() === "email" || - element.getAttribute("type").toLowerCase() === "number" || - element.getAttribute("type").toLowerCase() === "search" || - element.getAttribute("type").toLowerCase() === "tel" || - element.getAttribute("type").toLowerCase() === "url" || - element.getAttribute("type").toLowerCase() === "text")) - { - results["input"] = results["input"] || { count: 0 }; - results["input"].count++; - } - else if (element.nodeName.toLowerCase() === "textarea") - { - results["textarea"] = results["textarea"] || { count: 0 }; - results["textarea"].count++; - } - else if (element.nodeName.toLowerCase() === "div" || element.nodeName.toLowerCase() === "p" || element.nodeName.toLowerCase() === "table") - { - if(element.getAttribute("contenteditable").toLowerCase() === "true" || element.getAttribute("contenteditable").toLowerCase() === "plain-text") - { - results["contenteditable"] = results["contenteditable"] || { count: 0 }; - results["contenteditable"].count++; - } - } - return results; - }); -}(); - /* RECIPE: scriptElemStats ------------------------------------------------------------- diff --git a/cssUsage.src.js b/cssUsage.src.js index 43878e7..ce8900e 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -1781,45 +1781,6 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* - RECIPE: Edit controls on the web - ------------------------------------------------------------- - Author: Grisha Lyukshin - Description: Counts pages that have either input, textarea, or content editable elements -*/ - -void function() { - window.CSSUsage.StyleWalker.recipesToRun.push( function editControls(/*HTML DOM Element*/ element, results) { - - // we only care about special kind of inputs - if(element.nodeName.toLowerCase() === "input" && - (element.getAttribute("type").toLowerCase() === "email" || - element.getAttribute("type").toLowerCase() === "number" || - element.getAttribute("type").toLowerCase() === "search" || - element.getAttribute("type").toLowerCase() === "tel" || - element.getAttribute("type").toLowerCase() === "url" || - element.getAttribute("type").toLowerCase() === "text")) - { - results["input"] = results["input"] || { count: 0 }; - results["input"].count++; - } - else if (element.nodeName.toLowerCase() === "textarea") - { - results["textarea"] = results["textarea"] || { count: 0 }; - results["textarea"].count++; - } - else if (element.nodeName.toLowerCase() === "div" || element.nodeName.toLowerCase() === "p" || element.nodeName.toLowerCase() === "table") - { - if(element.getAttribute("contenteditable").toLowerCase() === "true" || element.getAttribute("contenteditable").toLowerCase() === "plain-text") - { - results["contenteditable"] = results["contenteditable"] || { count: 0 }; - results["contenteditable"].count++; - } - } - return results; - }); -}(); - /* RECIPE: scriptElemStats ------------------------------------------------------------- diff --git a/src/recipes/editControls.js b/src/recipes/archive/editControls.js similarity index 100% rename from src/recipes/editControls.js rename to src/recipes/archive/editControls.js From 8522f68afe1bfec2c6d763db4f64bd2ded2473b3 Mon Sep 17 00:00:00 2001 From: "Thomas Moore (CHAKRA)" Date: Mon, 26 Mar 2018 14:05:40 -0700 Subject: [PATCH 4/6] Simplify data collection for better scaling --- Recipe.min.js | 42 +++++++++++++++++++++++++++++---------- cssUsage.src.js | 42 +++++++++++++++++++++++++++++---------- src/recipes/scriptelem.js | 42 +++++++++++++++++++++++++++++---------- 3 files changed, 93 insertions(+), 33 deletions(-) diff --git a/Recipe.min.js b/Recipe.min.js index 6a7516d..e646cbf 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -1781,7 +1781,7 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* +/* RECIPE: scriptElemStats ------------------------------------------------------------- Author: thomasmo @@ -1791,17 +1791,37 @@ void function() { try { void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { if(element.nodeName.toLowerCase() == "script") { - results["data"] = results["data"] || []; + results["data"] = results["data"] || { + total : 0, + async : 0, + defer : 0, + externalSrc : 0, + parentElemHead : 0, + parentElemBody : 0, + parentElemOther : 0 + }; + + var result = results["data"]; + result.total++; + + if (element.hasAttribute("async")) { + result.async++; + } + if (element.hasAttribute("defer")) { + result.defer++; + } + if (element.hasAttribute("src")) { + result.externalSrc++; + } + parentElemName = element.parentNode.nodeName.toLowerCase(); - results["data"].push({ - async : element.hasAttribute("async") ? 1 : 0, - defer : element.hasAttribute("defer") ? 1 : 0, - external : element.hasAttribute("src") ? 1 : 0, - parentElem : { - head : (parentElemName === "head") ? 1 : 0, - body : (parentElemName === "body") ? 1 : 0 - } - }); + if (parentElemName === "head") { + result.parentElemHead++; + } else if (parentElemName === "body") { + result.parentElemBody++; + } else { + result.parentElemOther++; + } } return results; diff --git a/cssUsage.src.js b/cssUsage.src.js index ce8900e..1853a52 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -1781,7 +1781,7 @@ void function() { try { } catch (ex) { /* do something maybe */ throw ex; } }(); -/* +/* RECIPE: scriptElemStats ------------------------------------------------------------- Author: thomasmo @@ -1791,17 +1791,37 @@ void function() { try { void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { if(element.nodeName.toLowerCase() == "script") { - results["data"] = results["data"] || []; + results["data"] = results["data"] || { + total : 0, + async : 0, + defer : 0, + externalSrc : 0, + parentElemHead : 0, + parentElemBody : 0, + parentElemOther : 0 + }; + + var result = results["data"]; + result.total++; + + if (element.hasAttribute("async")) { + result.async++; + } + if (element.hasAttribute("defer")) { + result.defer++; + } + if (element.hasAttribute("src")) { + result.externalSrc++; + } + parentElemName = element.parentNode.nodeName.toLowerCase(); - results["data"].push({ - async : element.hasAttribute("async") ? 1 : 0, - defer : element.hasAttribute("defer") ? 1 : 0, - external : element.hasAttribute("src") ? 1 : 0, - parentElem : { - head : (parentElemName === "head") ? 1 : 0, - body : (parentElemName === "body") ? 1 : 0 - } - }); + if (parentElemName === "head") { + result.parentElemHead++; + } else if (parentElemName === "body") { + result.parentElemBody++; + } else { + result.parentElemOther++; + } } return results; diff --git a/src/recipes/scriptelem.js b/src/recipes/scriptelem.js index 02a1cda..6b3430e 100644 --- a/src/recipes/scriptelem.js +++ b/src/recipes/scriptelem.js @@ -1,4 +1,4 @@ -/* +/* RECIPE: scriptElemStats ------------------------------------------------------------- Author: thomasmo @@ -8,17 +8,37 @@ void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { if(element.nodeName.toLowerCase() == "script") { - results["data"] = results["data"] || []; + results["data"] = results["data"] || { + total : 0, + async : 0, + defer : 0, + externalSrc : 0, + parentElemHead : 0, + parentElemBody : 0, + parentElemOther : 0 + }; + + var result = results["data"]; + result.total++; + + if (element.hasAttribute("async")) { + result.async++; + } + if (element.hasAttribute("defer")) { + result.defer++; + } + if (element.hasAttribute("src")) { + result.externalSrc++; + } + parentElemName = element.parentNode.nodeName.toLowerCase(); - results["data"].push({ - async : element.hasAttribute("async") ? 1 : 0, - defer : element.hasAttribute("defer") ? 1 : 0, - external : element.hasAttribute("src") ? 1 : 0, - parentElem : { - head : (parentElemName === "head") ? 1 : 0, - body : (parentElemName === "body") ? 1 : 0 - } - }); + if (parentElemName === "head") { + result.parentElemHead++; + } else if (parentElemName === "body") { + result.parentElemBody++; + } else { + result.parentElemOther++; + } } return results; From 80a293131096cd388d656f434b7b4b7cda5abe9e Mon Sep 17 00:00:00 2001 From: "Thomas Moore (CHAKRA)" Date: Fri, 30 Mar 2018 09:41:33 -0700 Subject: [PATCH 5/6] Collect data-per-element --- Recipe.min.js | 26 +++++++++++++++++++++++++- cssUsage.src.js | 26 +++++++++++++++++++++++++- src/recipes/scriptelem.js | 25 +++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/Recipe.min.js b/Recipe.min.js index e646cbf..7bd9c9f 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -1788,6 +1788,30 @@ void function() { try { Description: Collect stats for script elements */ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { + window._elementCount = window._elementCount || 0; + window._elementCount++; + if(element.nodeName.toLowerCase() == "script") { + results["data"] = results["data"] || []; + + var elemData = { + index : window._elementCount, + async : element.hasAttribute("async"), + defer : element.hasAttribute("defer"), + externalSrc : element.hasAttribute("src"), + parentElem : element.parentNode.nodeName.toLowerCase() + }; + + results["data"].push(elemData); + } + + return results; + }); +}(); + +/* void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { if(element.nodeName.toLowerCase() == "script") { @@ -1827,7 +1851,7 @@ void function() { return results; }); }(); - +*/ // // This file is only here to create the TSV // necessary to collect the data from the crawler diff --git a/cssUsage.src.js b/cssUsage.src.js index 1853a52..d51c4f3 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -1788,6 +1788,30 @@ void function() { try { Description: Collect stats for script elements */ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { + window._elementCount = window._elementCount || 0; + window._elementCount++; + if(element.nodeName.toLowerCase() == "script") { + results["data"] = results["data"] || []; + + var elemData = { + index : window._elementCount, + async : element.hasAttribute("async"), + defer : element.hasAttribute("defer"), + externalSrc : element.hasAttribute("src"), + parentElem : element.parentNode.nodeName.toLowerCase() + }; + + results["data"].push(elemData); + } + + return results; + }); +}(); + +/* void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { if(element.nodeName.toLowerCase() == "script") { @@ -1827,7 +1851,7 @@ void function() { return results; }); }(); - +*/ // // This file is only here to create the TSV // necessary to collect the data from the crawler diff --git a/src/recipes/scriptelem.js b/src/recipes/scriptelem.js index 6b3430e..cf9a605 100644 --- a/src/recipes/scriptelem.js +++ b/src/recipes/scriptelem.js @@ -5,6 +5,30 @@ Description: Collect stats for script elements */ + +void function() { + window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { + window._elementCount = window._elementCount || 0; + window._elementCount++; + if(element.nodeName.toLowerCase() == "script") { + results["data"] = results["data"] || []; + + var elemData = { + index : window._elementCount, + async : element.hasAttribute("async"), + defer : element.hasAttribute("defer"), + externalSrc : element.hasAttribute("src"), + parentElem : element.parentNode.nodeName.toLowerCase() + }; + + results["data"].push(elemData); + } + + return results; + }); +}(); + +/* void function() { window.CSSUsage.StyleWalker.recipesToRun.push( function scriptElemStats( element, results) { if(element.nodeName.toLowerCase() == "script") { @@ -44,3 +68,4 @@ void function() { return results; }); }(); +*/ \ No newline at end of file From a73a8a98d38aa3e17ce43f34ad569df8b708f51b Mon Sep 17 00:00:00 2001 From: "Thomas Moore (CHAKRA)" Date: Fri, 30 Mar 2018 14:51:21 -0700 Subject: [PATCH 6/6] Remove usage of booleans --- Recipe.min.js | 10 +++++----- cssUsage.src.js | 10 +++++----- src/recipes/scriptelem.js | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Recipe.min.js b/Recipe.min.js index 7bd9c9f..f797fe0 100644 --- a/Recipe.min.js +++ b/Recipe.min.js @@ -1797,11 +1797,11 @@ void function() { results["data"] = results["data"] || []; var elemData = { - index : window._elementCount, - async : element.hasAttribute("async"), - defer : element.hasAttribute("defer"), - externalSrc : element.hasAttribute("src"), - parentElem : element.parentNode.nodeName.toLowerCase() + index : window._elementCount, + async : element.hasAttribute("async") ? 1 : 0, + defer : element.hasAttribute("defer") ? 1 : 0, + externalSrc : element.hasAttribute("src") ? 1 : 0, + parentElem : element.parentNode.nodeName.toLowerCase() }; results["data"].push(elemData); diff --git a/cssUsage.src.js b/cssUsage.src.js index d51c4f3..8c96c4f 100644 --- a/cssUsage.src.js +++ b/cssUsage.src.js @@ -1797,11 +1797,11 @@ void function() { results["data"] = results["data"] || []; var elemData = { - index : window._elementCount, - async : element.hasAttribute("async"), - defer : element.hasAttribute("defer"), - externalSrc : element.hasAttribute("src"), - parentElem : element.parentNode.nodeName.toLowerCase() + index : window._elementCount, + async : element.hasAttribute("async") ? 1 : 0, + defer : element.hasAttribute("defer") ? 1 : 0, + externalSrc : element.hasAttribute("src") ? 1 : 0, + parentElem : element.parentNode.nodeName.toLowerCase() }; results["data"].push(elemData); diff --git a/src/recipes/scriptelem.js b/src/recipes/scriptelem.js index cf9a605..e71fef9 100644 --- a/src/recipes/scriptelem.js +++ b/src/recipes/scriptelem.js @@ -14,11 +14,11 @@ void function() { results["data"] = results["data"] || []; var elemData = { - index : window._elementCount, - async : element.hasAttribute("async"), - defer : element.hasAttribute("defer"), - externalSrc : element.hasAttribute("src"), - parentElem : element.parentNode.nodeName.toLowerCase() + index : window._elementCount, + async : element.hasAttribute("async") ? 1 : 0, + defer : element.hasAttribute("defer") ? 1 : 0, + externalSrc : element.hasAttribute("src") ? 1 : 0, + parentElem : element.parentNode.nodeName.toLowerCase() }; results["data"].push(elemData);