Repository: bem/bh
Pull request #137 (2015-03-24 11:24:24)

Optimize attribute escaping

coveralls: 
[![Coverage Status](https://coveralls.io/builds/2180443/badge)](https://coveralls.io/builds/2180443)

Coverage remained the same at 100.0% when pulling **a2068edc1934bdf7521e2f6b0d29d1efcb0453ef on escape** into **57466ed5449121ab5bae976c1bffd4374c4c5ce9 on master**.


Patch:
diff --git a/lib/bh.js b/lib/bh.js
index f29c98a..9a61afc 100644
--- a/lib/bh.js
+++ b/lib/bh.js
@@ -975,11 +975,11 @@ BH.prototype = {
             }
 
             if (json.cls) {
-                cls = cls ? cls + ' ' + json.cls : json.cls;
+                cls = (cls ? cls + ' ' : '') + attrEscape(json.cls);
             }
 
             var content, tag = (json.tag || 'div');
-            res = '<' + tag + (cls ? ' class="' + attrEscape(cls) + '"' : '') + (attrs ? attrs : '');
+            res = '<' + tag + (cls ? ' class="' + cls + '"' : '') + (attrs ? attrs : '');
 
             if (selfCloseHtmlTags[tag]) {
                 res += '/>';
@@ -1030,10 +1030,10 @@ var xmlEscape = BH.prototype.xmlEscape = function(str) {
     return (str + '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
 };
 var attrEscape = BH.prototype.attrEscape = function(str) {
-    return (str + '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
+    return (str + '').replace(/&/g, '&amp;').replace(/"/g, '&quot;');
 };
 var jsAttrEscape = BH.prototype.jsAttrEscape = function(str) {
-    return (str + '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&#39;');
+    return (str + '').replace(/&/g, '&amp;').replace(/'/g, '&#39;');
 };
 
 var toBemCssClasses = function(json, base, parentBase, nobase) {


Test patch:
diff --git a/test/test.escape.js b/test/test.escape.js
index b9dac05..6b5a1d9 100644
--- a/test/test.escape.js
+++ b/test/test.escape.js
@@ -23,7 +23,7 @@ describe('bh.attrEscape()', function() {
 
     it('should escape xml attr string', function() {
         bh.match('button', function() {
-            bh.attrEscape('<b id="a">&</b>').should.equal('&lt;b id=&quot;a&quot;&gt;&amp;&lt;/b&gt;');
+            bh.attrEscape('<b id="a">&</b>').should.equal('<b id=&quot;a&quot;>&amp;</b>');
         });
         bh.apply({ block: 'button' });
     });
@@ -37,7 +37,7 @@ describe('bh.jsAttrEscape()', function() {
 
     it('should escape xml attr js string', function() {
         bh.match('button', function() {
-            bh.jsAttrEscape('<b id="a">\'&\'</b>').should.equal('&lt;b id="a"&gt;&#39;&amp;&#39;&lt;/b&gt;');
+            bh.jsAttrEscape('<b id="a">\'&\'</b>').should.equal('<b id="a">&#39;&amp;&#39;</b>');
         });
         bh.apply({ block: 'button' });
     });
diff --git a/test/test.toHtml.js b/test/test.toHtml.js
index 3ed3fb9..4bd27b2 100644
--- a/test/test.toHtml.js
+++ b/test/test.toHtml.js
@@ -124,8 +124,7 @@ describe('bh.toHtml()', function() {
                 attrs: { href: '<script type="javascript">window && alert(document.cookie)</script>' },
                 content: 'link'
             }).should.equal(
-                '<a href="&lt;script type=&quot;javascript&quot;&gt;window &amp;&amp; ' +
-                'alert(document.cookie)&lt;/script&gt;">link</a>');
+                '<a href="<script type=&quot;javascript&quot;>window &amp;&amp; alert(document.cookie)</script>">link</a>');
         });
     });