Skip to content

Commit

Permalink
Utils: escaping function should’t render undefined/Null/NaN
Browse files Browse the repository at this point in the history
Motivation: for safety reasons I decided to change regular cast to string. In
frontend we need only useful values such as Strings and Numbers. All undefined,
NaN, Null and [Object object] values is useless and are a mistake in HTML.
  • Loading branch information
Yeti-or authored and miripiruni committed Dec 7, 2016
1 parent 99fa742 commit 1977ee8
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 0 deletions.
16 changes: 16 additions & 0 deletions lib/bemxjst/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ var singleQuot = ''';
var matchXmlRegExp = /[&<>]/;

exports.xmlEscape = function(string) {
if (typeof string === 'undefined' ||
string === null ||
(typeof string === 'number' && isNaN(string))
)
return '';

var str = '' + string;
var match = matchXmlRegExp.exec(str);

Expand Down Expand Up @@ -48,6 +54,11 @@ exports.xmlEscape = function(string) {
var matchAttrRegExp = /["&]/;

exports.attrEscape = function(string) {
if (typeof string === 'undefined' ||
string === null ||
(typeof string === 'number' && isNaN(string)))
return '';

var str = '' + string;
var match = matchAttrRegExp.exec(str);

Expand Down Expand Up @@ -86,6 +97,11 @@ exports.attrEscape = function(string) {
var matchJsAttrRegExp = /['&]/;

exports.jsAttrEscape = function(string) {
if (typeof string === 'undefined' ||
string === null ||
(typeof string === 'number' && isNaN(string)))
return '';

var str = '' + string;
var match = matchJsAttrRegExp.exec(str);

Expand Down
64 changes: 64 additions & 0 deletions test/bemcontext-attrescape-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var fixtures = require('./fixtures')('bemhtml');
var compile = fixtures.compile;
var test = fixtures.test;

describe('BEMContext this.attrEscape(str)', function() {
Expand All @@ -11,4 +12,67 @@ describe('BEMContext this.attrEscape(str)', function() {
{ block: 'button' },
'<b id=&quot;a&quot; class=&quot;bem&quot;>a&amp;b&amp;c</b>');
});

describe('Type of argument', function() {
var bemhtml;

before(function() {
bemhtml = compile(function() {
block('b').def()(function(n, ctx) {
return n.attrEscape(ctx.val);
});
});
});

it('should return \'\' for undefined', function() {
bemhtml.apply({ block: 'b', val: undefined }).should.equal('');
});

it('should return \'\' for null', function() {
bemhtml.apply({ block: 'b', val: null }).should.equal('');
});

it('should return String for zero', function() {
bemhtml.apply({ block: 'b', val: 0 }).should.equal('0');
});

it('should return String for Number', function() {
bemhtml.apply({ block: 'b', val: 42 }).should.equal('42');
});

it('should return \'\' for NaN', function() {
bemhtml.apply({ block: 'b', val: NaN }).should.equal('');
});

it('should return String for String', function() {
bemhtml.apply({ block: 'b', val: '' }).should.equal('');
});

it('should return String for String', function() {
bemhtml.apply({ block: 'b', val: 'test' }).should.equal('test');
});

it('should return String for Boolean', function() {
bemhtml.apply({ block: 'b', val: false }).should.equal('false');
});

it('should return String for Array', function() {
bemhtml.apply({ block: 'b', val: [] }).should.equal('');
});

it('should return String for Array', function() {
bemhtml.apply({ block: 'b', val: [ 'a', 'b' ] }).should.equal('a,b');
});

it('should return \'\' for Object', function() {
bemhtml.apply({ block: 'b', val: {
toString: function() { return ''; }
} }).should.equal('');
});

it('should return \'\' for Function', function() {
bemhtml.apply({ block: 'b', val: function() {} })
.should.equal('function () {}');
});
});
});
63 changes: 63 additions & 0 deletions test/bemcontext-jsattrescape-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,67 @@ describe('BEMContext this.jsAttrEscape(str)', function() {
.should.equal('<b foo="a">&#39;&amp;&#39;</b><b bar="b">&#39;&amp;' +
'&#39;</b>');
});

describe('Type of argument', function() {
var bemhtml;

before(function() {
bemhtml = compile(function() {
block('b').def()(function(n, ctx) {
return n.jsAttrEscape(ctx.val);
});
});
});

it('should return \'\' for undefined', function() {
bemhtml.apply({ block: 'b', val: undefined }).should.equal('');
});

it('should return \'\' for null', function() {
bemhtml.apply({ block: 'b', val: null }).should.equal('');
});

it('should return String for zero', function() {
bemhtml.apply({ block: 'b', val: 0 }).should.equal('0');
});

it('should return String for Number', function() {
bemhtml.apply({ block: 'b', val: 42 }).should.equal('42');
});

it('should return \'\' for NaN', function() {
bemhtml.apply({ block: 'b', val: NaN }).should.equal('');
});

it('should return String for String', function() {
bemhtml.apply({ block: 'b', val: '' }).should.equal('');
});

it('should return String for String', function() {
bemhtml.apply({ block: 'b', val: 'test' }).should.equal('test');
});

it('should return String for Boolean', function() {
bemhtml.apply({ block: 'b', val: false }).should.equal('false');
});

it('should return String for Array', function() {
bemhtml.apply({ block: 'b', val: [] }).should.equal('');
});

it('should return String for Array', function() {
bemhtml.apply({ block: 'b', val: [ 'a', 'b' ] }).should.equal('a,b');
});

it('should return \'\' for Object', function() {
bemhtml.apply({ block: 'b', val: {
toString: function() { return ''; }
} }).should.equal('');
});

it('should return \'\' for Function', function() {
bemhtml.apply({ block: 'b', val: function() {} })
.should.equal('function () {}');
});
});
});
64 changes: 64 additions & 0 deletions test/bemcontext-xmlescape-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var fixtures = require('./fixtures')('bemhtml');
var compile = fixtures.compile;
var test = fixtures.test;

describe('BEMContext this.xmlEscape()', function() {
Expand All @@ -11,4 +12,67 @@ describe('BEMContext this.xmlEscape()', function() {
{ block: 'button' },
'&lt;b&gt;&amp;&lt;/b&gt;');
});

describe('Type of argument', function() {
var bemhtml;

before(function() {
bemhtml = compile(function() {
block('b').def()(function(n, ctx) {
return n.xmlEscape(ctx.val);
});
});
});

it('should return \'\' for undefined', function() {
bemhtml.apply({ block: 'b', val: undefined }).should.equal('');
});

it('should return \'\' for null', function() {
bemhtml.apply({ block: 'b', val: null }).should.equal('');
});

it('should return String for zero', function() {
bemhtml.apply({ block: 'b', val: 0 }).should.equal('0');
});

it('should return String for Number', function() {
bemhtml.apply({ block: 'b', val: 42 }).should.equal('42');
});

it('should return \'\' for NaN', function() {
bemhtml.apply({ block: 'b', val: NaN }).should.equal('');
});

it('should return String for String', function() {
bemhtml.apply({ block: 'b', val: '' }).should.equal('');
});

it('should return String for String', function() {
bemhtml.apply({ block: 'b', val: 'test' }).should.equal('test');
});

it('should return String for Boolean', function() {
bemhtml.apply({ block: 'b', val: false }).should.equal('false');
});

it('should return String for Array', function() {
bemhtml.apply({ block: 'b', val: [] }).should.equal('');
});

it('should return String for Array', function() {
bemhtml.apply({ block: 'b', val: [ 'a', 'b' ] }).should.equal('a,b');
});

it('should return \'\' for Object', function() {
bemhtml.apply({ block: 'b', val: {
toString: function() { return ''; }
} }).should.equal('');
});

it('should return \'\' for Function', function() {
bemhtml.apply({ block: 'b', val: function() {} })
.should.equal('function () {}');
});
});
});

0 comments on commit 1977ee8

Please sign in to comment.