diff --git a/dist/showdown.js b/dist/showdown.js index af4d5e3..cde214f 100644 Binary files a/dist/showdown.js and b/dist/showdown.js differ diff --git a/dist/showdown.js.map b/dist/showdown.js.map index bbfc3eb..20aefab 100644 Binary files a/dist/showdown.js.map and b/dist/showdown.js.map differ diff --git a/dist/showdown.min.js b/dist/showdown.min.js index 0f229ce..c3e4173 100644 Binary files a/dist/showdown.min.js and b/dist/showdown.min.js differ diff --git a/dist/showdown.min.js.map b/dist/showdown.min.js.map index 84fbe2a..de43de2 100644 Binary files a/dist/showdown.min.js.map and b/dist/showdown.min.js.map differ diff --git a/src/helpers.js b/src/helpers.js index d572df4..e3758ff 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -12,7 +12,7 @@ if (!showdown.hasOwnProperty('helper')) { * @param {string} a * @returns {boolean} */ -showdown.helper.isString = function isString(a) { +showdown.helper.isString = function (a) { 'use strict'; return (typeof a === 'string' || a instanceof String); }; @@ -20,39 +20,22 @@ showdown.helper.isString = function isString(a) { /** * Check if var is a function * @static - * @param {string} a + * @param {*} a * @returns {boolean} */ -showdown.helper.isFunction = function isFunction(a) { +showdown.helper.isFunction = function (a) { 'use strict'; var getType = {}; return a && getType.toString.call(a) === '[object Function]'; }; -/** - * ForEach helper function - * @static - * @param {*} obj - * @param {function} callback - */ -showdown.helper.forEach = function forEach(obj, callback) { - 'use strict'; - if (typeof obj.forEach === 'function') { - obj.forEach(callback); - } else { - for (var i = 0; i < obj.length; i++) { - callback(obj[i], i, obj); - } - } -}; - /** * isArray helper function * @static * @param {*} a * @returns {boolean} */ -showdown.helper.isArray = function isArray(a) { +showdown.helper.isArray = function (a) { 'use strict'; return a.constructor === Array; }; @@ -63,11 +46,50 @@ showdown.helper.isArray = function isArray(a) { * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. */ -showdown.helper.isUndefined = function isUndefined(value) { +showdown.helper.isUndefined = function (value) { 'use strict'; return typeof value === 'undefined'; }; +/** + * ForEach helper function + * Iterates over Arrays and Objects (own properties only) + * @static + * @param {*} obj + * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object + */ +showdown.helper.forEach = function (obj, callback) { + 'use strict'; + // check if obj is defined + if (showdown.helper.isUndefined(obj)) { + throw new Error('obj param is required'); + } + + if (showdown.helper.isUndefined(callback)) { + throw new Error('callback param is required'); + } + + if (!showdown.helper.isFunction(callback)) { + throw new Error('callback param must be a function/closure'); + } + + if (typeof obj.forEach === 'function') { + obj.forEach(callback); + } else if (showdown.helper.isArray(obj)) { + for (var i = 0; i < obj.length; i++) { + callback(obj[i], i, obj); + } + } else if (typeof (obj) === 'object') { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + callback(obj[prop], prop, obj); + } + } + } else { + throw new Error('obj does not seem to be an array or an iterable object'); + } +}; + /** * Standardidize extension name * @static @@ -76,7 +98,7 @@ showdown.helper.isUndefined = function isUndefined(value) { */ showdown.helper.stdExtName = function (s) { 'use strict'; - return s.replace(/[_-]||\s/g, '').toLowerCase(); + return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase(); }; function escapeCharactersCallback(wholeMatch, m1) { @@ -102,7 +124,7 @@ showdown.helper.escapeCharactersCallback = escapeCharactersCallback; * @param {boolean} afterBackslash * @returns {XML|string|void|*} */ -showdown.helper.escapeCharacters = function escapeCharacters(text, charsToEscape, afterBackslash) { +showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) { 'use strict'; // First we have to escape the escape characters so that // we can build a character class out of them diff --git a/test/node/showdown.helpers.js b/test/node/showdown.helpers.js index 2540dba..3563c23 100644 --- a/test/node/showdown.helpers.js +++ b/test/node/showdown.helpers.js @@ -1,6 +1,10 @@ /** * Created by Estevao on 27/01/2017. */ +/*jshint expr: true*/ +/*jshint -W053 */ +/*jshint -W010 */ +/*jshint -W009 */ var bootstrap = require('../bootstrap.js'), showdown = bootstrap.showdown; @@ -27,3 +31,205 @@ describe('encodeEmailAddress()', function () { decodedEmail.should.equal(email); }); }); + +describe('isString()', function () { + 'use strict'; + var isString = showdown.helper.isString; + + it('should return true for new String Object', function () { + isString(new String('some string')).should.be.true; + }); + + it('should return true for String Object', function () { + isString(String('some string')).should.be.true; + }); + + it('should return true for string literal', function () { + isString('some string').should.be.true; + }); + + it('should return false for integers', function () { + isString(5).should.be.false; + }); + + it('should return false for random objects', function () { + isString({foo: 'bar'}).should.be.false; + }); + + it('should return false for arrays', function () { + isString(['bar']).should.be.false; + }); +}); + +describe('isFunction()', function () { + 'use strict'; + var isFunction = showdown.helper.isFunction; + + it('should return true for closures', function () { + isFunction(function () {}).should.be.true; + }); + + it('should return true for defined functions', function () { + function foo () {} + isFunction(foo).should.be.true; + }); + + it('should return true for function variables', function () { + var bar = function () {}; + isFunction(bar).should.be.true; + }); + + it('should return false for hash objects', function () { + isFunction({}).should.be.false; + }); + + it('should return false for objects', function () { + isFunction(new Object ()).should.be.false; + }); + + it('should return false for string primitives', function () { + isFunction('foo').should.be.false; + }); +}); + +describe('isArray()', function () { + 'use strict'; + var isArray = showdown.helper.isArray; + + it('should return true for short syntax arrays', function () { + isArray([]).should.be.true; + }); + + it('should return true for array objects', function () { + var myArr = new Array(); + isArray(myArr).should.be.true; + }); + + it('should return false for functions', function () { + isArray(function () {}).should.be.false; + function baz () {} + isArray(baz).should.be.false; + }); + + it('should return false for objects', function () { + isArray({}).should.be.false; + isArray(new Object ()).should.be.false; + }); + + it('should return false for strings', function () { + isArray('foo').should.be.false; + isArray(new String('foo')).should.be.false; + }); +}); + +describe('isUndefined()', function () { + 'use strict'; + var isUndefined = showdown.helper.isUndefined; + + it('should return true if nothing is passed', function () { + isUndefined().should.be.true; + }); + + it('should return true if a variable is initialized but not defined', function () { + var myVar; + isUndefined(myVar).should.be.true; + }); + + it('should return false for null', function () { + isUndefined(null).should.be.false; + }); + + it('should return false for 0', function () { + isUndefined(0).should.be.false; + }); + + it('should return false for empty string', function () { + isUndefined('').should.be.false; + }); + + it('should return false for empty booleans false or true', function () { + isUndefined(false).should.be.false; + isUndefined(true).should.be.false; + }); + + it('should return false for anything not undefined', function () { + isUndefined('foo').should.be.false; + isUndefined(2).should.be.false; + isUndefined({}).should.be.false; + }); +}); + +describe('stdExtName()', function () { + 'use strict'; + var stdExtName = showdown.helper.stdExtName; + + it('should remove certain chars', function () { + var str = 'bla_- \nbla'; + //[_?*+\/\\.^-] + stdExtName(str).should.not.match(/[_?*+\/\\.^-]/g); + }); + it('should make everything lowercase', function () { + var str = 'BLABLA'; + //[_?*+\/\\.^-] + stdExtName(str).should.equal('blabla'); + }); +}); + +describe('forEach()', function () { + 'use strict'; + var forEach = showdown.helper.forEach; + + it('should throw an error if first parameter is undefined', function () { + (function () {forEach();}).should.throw('obj param is required'); + }); + + it('should throw an error if second parameter is undefined', function () { + (function () {forEach([]);}).should.throw('callback param is required'); + }); + + it('should throw an error if second parameter is not a function', function () { + (function () {forEach([], 'foo');}).should.throw('callback param must be a function/closure'); + }); + + it('should throw an error if first parameter is not an object or an array', function () { + (function () {forEach('foo', function () {});}).should.throw('obj does not seem to be an array or an iterable object'); + }); + + it('should not throw even if object is empty', function () { + (function () {forEach({}, function () {});}).should.not.throw(); + }); + + it('should iterate array items', function () { + var myArray = ['banana', 'orange', 'grape']; + forEach(myArray, function (val, key, obj) { + key.should.be.a('number'); + (key % 1).should.equal(0); + val.should.equal(myArray[key]); + obj.should.equal(myArray); + }); + }); + + it('should iterate over object properties', function () { + var myObj = {foo: 'banana', bar: 'orange', baz: 'grape'}; + forEach(myObj, function (val, key, obj) { + myObj.should.have.ownProperty(key); + val.should.equal(myObj[key]); + obj.should.equal(myObj); + }); + }); + + it('should iterate only over object own properties', function () { + var Obj1 = {foo: 'banana'}, + myObj = Object.create(Obj1); + myObj.bar = 'orange'; + myObj.baz = 'grape'; + + myObj.should.have.ownProperty('bar'); + myObj.should.have.ownProperty('baz'); + myObj.should.not.have.ownProperty('foo'); + + forEach(myObj, function (val, key) { + key.should.not.equal('foo'); + }); + }); +});