فهرست منبع

Offenders layout for DOM inserts

Gaël Métais 10 سال پیش
والد
کامیت
a4f22a8542
5فایلهای تغییر یافته به همراه204 افزوده شده و 16 حذف شده
  1. 50 3
      front/src/css/rule.css
  2. 67 9
      front/src/less/rule.less
  3. 10 3
      lib/metadata/policies.js
  4. 33 1
      lib/offendersHelpers.js
  5. 44 0
      test/core/offendersHelpersTest.js

+ 50 - 3
front/src/css/rule.css

@@ -82,17 +82,64 @@
   font-size: 3em;
   margin-bottom: 1em;
 }
+.offenders .eltButton {
+  display: inline-block;
+  position: relative;
+  background: #efe;
+  padding: 0 0.5em;
+  margin: 0.2em 0;
+  border-radius: 0.4em;
+  z-index: 1;
+}
+.offenders .eltButton.opens {
+  padding-right: 0.75em;
+}
+.offenders .eltButton.opens:after {
+  position: relative;
+  left: 0.5em;
+  content: '\25BC';
+  font-size: 0.8em;
+}
+.offenders .eltButton > div {
+  display: none;
+  position: absolute;
+  right: 0;
+  min-width: 100%;
+  background: inherit;
+  border-bottom-left-radius: 0.4em;
+  border-bottom-right-radius: 0.4em;
+  border-top: 1px solid #999;
+}
+.offenders .eltButton .domTree {
+  text-align: left;
+  white-space: nowrap;
+}
+.offenders .eltButton .domTree > div {
+  margin: 0.5em;
+}
+.offenders .eltButton .domTree > div div {
+  margin-left: 1em;
+}
+.offenders .eltButton:hover {
+  border-bottom-left-radius: 0;
+  border-bottom-right-radius: 0;
+  background: #ffe0cc;
+  z-index: 2;
+}
+.offenders .eltButton:hover > div {
+  display: block;
+}
 .offendersHtml {
   display: inline-block;
 }
-.offendersHtml .domTree div {
+.domTree div {
   text-align: left;
   margin-left: 1em;
 }
-.offendersHtml .domTree div span:only-child {
+.domTree div span:only-child {
   font-weight: bold;
 }
-.offendersHtml .domTree div span:only-child span {
+.domTree div span:only-child span {
   font-style: italic;
   font-weight: normal;
 }

+ 67 - 9
front/src/less/rule.less

@@ -90,19 +90,77 @@
     }
 }
 
+.offenders {
+    .eltButton {
+        display: inline-block;
+        position: relative;
+        background: #efe;
+        padding: 0 0.5em;
+        margin: 0.2em 0;
+        border-radius: 0.4em;
+        z-index: 1;
+
+        &.opens {
+            padding-right: 0.75em;
+
+            &:after {
+                position: relative;
+                left: 0.5em;
+                content: '\25BC';
+                font-size: 0.8em;
+            }
+        }
+
+        > div {
+            display: none;
+            position: absolute;
+            right: 0;
+            min-width: 100%;
+            background: inherit;
+            border-bottom-left-radius: 0.4em;
+            border-bottom-right-radius: 0.4em;
+            border-top: 1px solid #999;
+        }
+
+        .domTree {
+            text-align: left;
+            white-space: nowrap;
+
+            > div {
+                margin: 0.5em;
+
+                div {
+                    margin-left: 1em;
+                }
+            }
+        }
+
+        &:hover {
+            border-bottom-left-radius: 0;
+            border-bottom-right-radius: 0;
+            background: #ffe0cc;
+            z-index: 2;
+
+            & > div {
+                display: block;
+            }
+        }
+    }
+}
+
 .offendersHtml {
     display: inline-block;
+}
 
-    .domTree div {
-        text-align: left;
-        margin-left: 1em;
+.domTree div {
+    text-align: left;
+    margin-left: 1em;
 
-        span:only-child {
-            font-weight: bold;
-            span {
-                font-style: italic;
-                font-weight: normal;
-            }
+    span:only-child {
+        font-weight: bold;
+        span {
+            font-style: italic;
+            font-weight: normal;
         }
     }
 }

+ 10 - 3
lib/metadata/policies.js

@@ -38,8 +38,8 @@ var policies = {
         "isAbnormalThreshold": 10,
         "offendersTransformFn": function(offenders) {
             return offenders.map(function(offender) {
-                var results = /^(.*): (\d) occurrences$/.exec(offender);
-                return '<b>#' + results[1] + '</b>: ' + results[2] + ' occurrences';
+                var parts = /^(.*): (\d) occurrences$/.exec(offender);
+                return '<b>#' + parts[1] + '</b>: ' + parts[2] + ' occurrences';
             });
         }
     },
@@ -49,7 +49,14 @@ var policies = {
         "message": "<p>Working with the DOM in JavaScript triggers layout calculations and slows down the page.</p><p>Try, as much as possible, to have an HTML page fully generated by the server instead of making changes with JS.</p>",
         "isOkThreshold": 10,
         "isBadThreshold": 400,
-        "isAbnormalThreshold": 1000
+        "isAbnormalThreshold": 1000,
+        "offendersTransformFn": function(offenders) {
+            return offenders.map(function(offender) {
+                var parts = /^"(.*)" appended to "(.*)"$/.exec(offender);
+
+                return offendersHelpers.domPathToButton(parts[1]) + ' appended to ' + offendersHelpers.domPathToButton(parts[2]);
+            });
+        }
     },
     "DOMqueries": {
         "tool": "phantomas",

+ 33 - 1
lib/offendersHelpers.js

@@ -1,7 +1,6 @@
 
 
 var OffendersHelpers = function() {
-
     
     this.domPathToArray = function(str) {
         return str.split(/\s?>\s?/);
@@ -60,6 +59,39 @@ var OffendersHelpers = function() {
         return this.domTreeToHTML(domTree);
     };
 
+    this.domPathToButton = function(domPath) {
+        var domArray = this.domPathToArray(domPath);
+        var domTree = this.listOfDomPathsToHTML([domPath]);
+
+        if (domArray[0] === 'html') {
+            return '<div class="eltButton htmlButton"><b>html</b></div>';
+        }
+        if (domArray[0] === 'body') {
+            if (domArray.length === 1) {
+                return '<div class="eltButton bodyButton"><b>body</b></div>';
+            } else {
+                return '<div class="eltButton domButton opens">DOM element <b>' + domArray[domArray.length - 1] + '</b>' + domTree + '</div>';
+            }
+        }
+        if (domArray[0] === 'head') {
+            return '<div class="eltButton headButton"><b>head</b></div>';
+        }
+        if (domArray[0] === 'DocumentFragment') {
+            if (domArray.length === 1) {
+                return '<div class="eltButton fragButton">Fragment</div>';
+            } else {
+                return '<div class="eltButton fragEltButton opens">Fragment element <b>' + domArray[domArray.length - 1] + '</b>' + domTree + '</div>';
+            }
+        }
+        
+        // Not attached element, such as just created with document.createElement()
+        if (domArray.length === 1) {
+            return '<div class="eltButton aloneButton">Created element <b>' + domPath + '</b></div>';
+        } else {
+            return '<div class="eltButton aloneEltButton opens">Created element <b>' + domArray[domArray.length - 1] + '</b>' + domTree + '</div>';
+        }
+    };
+
 };
 
 module.exports = new OffendersHelpers();

+ 44 - 0
test/core/offendersHelpersTest.js

@@ -80,4 +80,48 @@ describe('offendersHelpers', function() {
 
     });
 
+    describe('domPathToButton', function() {
+
+        it('should transform html', function() {
+            var result = offendersHelpers.domPathToButton('html');
+            result.should.equal('<div class="eltButton htmlButton"><b>html</b></div>');
+        });
+
+        it('should transform body', function() {
+            var result = offendersHelpers.domPathToButton('body');
+            result.should.equal('<div class="eltButton bodyButton"><b>body</b></div>');
+        });
+
+        it('should transform head', function() {
+            var result = offendersHelpers.domPathToButton('head');
+            result.should.equal('<div class="eltButton headButton"><b>head</b></div>');
+        });
+
+        it('should transform a standard in-body element', function() {
+            var result = offendersHelpers.domPathToButton('body > div#colorbox > div#cboxContent');
+            result.should.equal('<div class="eltButton domButton opens">DOM element <b>div#cboxContent</b><div class="domTree"><div><span>body</span><div><span>div#colorbox</span><div><span>div#cboxContent</span></div></div></div></div></div>');
+        });
+
+        it('should transform a domFragment element', function() {
+            var result = offendersHelpers.domPathToButton('DocumentFragment');
+            result.should.equal('<div class="eltButton fragButton">Fragment</div>');
+        });
+
+        it('should transform a domFragment element', function() {
+            var result = offendersHelpers.domPathToButton('DocumentFragment > div#colorbox > div#cboxContent');
+            result.should.equal('<div class="eltButton fragEltButton opens">Fragment element <b>div#cboxContent</b><div class="domTree"><div><span>DocumentFragment</span><div><span>div#colorbox</span><div><span>div#cboxContent</span></div></div></div></div></div>');
+        });
+
+        it('should transform an not-attached element', function() {
+            var result = offendersHelpers.domPathToButton('div#sizcache');
+            result.should.equal('<div class="eltButton aloneButton">Created element <b>div#sizcache</b></div>');
+        });
+
+        it('should transform an not-attached element path', function() {
+            var result = offendersHelpers.domPathToButton('div > div#sizcache');
+            result.should.equal('<div class="eltButton aloneEltButton opens">Created element <b>div#sizcache</b><div class="domTree"><div><span>div</span><div><span>div#sizcache</span></div></div></div></div>');
+        });
+
+    });
+
 });