Code coverage report for lib/utils.js

Statements: 71.08% (59 / 83)      Branches: 53.49% (23 / 43)      Functions: 89.47% (17 / 19)      Lines: 73.75% (59 / 80)      Ignored: none     

All files » lib/ » utils.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 1821 1 1 1 1   1 6 6     1                                         1918     1918               1929       2021 2021 2021         2021                     1749       5425 5425 5490 14488     5425               1758       1114 1135       1114 10   1114               2099 2099   2099     2099 2099 47500       2099 2099 35056       2099 45401 717309 62598   654711             2099       1137 1137                       1137       7946 7946 50351 7946             440 440 54   440       585 585 1679 1292     585      
var shim = require('./shim');
var forEach = shim.forEach;
var filter = shim.filter;
var reduce = shim.reduce;
var getKeys = shim.getKeys;
 
var errorMethodBlacklist = reduce(['message', 'line', 'sourceId', 'sourceURL', 'stack', 'stackArray'], function (result, prop) {
    result[prop] = true;
    return result;
}, {});
 
module.exports = {
    // https://gist.github.com/1044128/
    getOuterHTML: function (element) {
        // jshint browser:true
        if ('outerHTML' in element) return element.outerHTML;
        var ns = "http://www.w3.org/1999/xhtml";
        var container = document.createElementNS(ns, '_');
        var xmlSerializer = new XMLSerializer();
        var html;
        if (document.xmlVersion) {
            return xmlSerializer.serializeToString(element);
        } else {
            container.appendChild(element.cloneNode(false));
            html = container.innerHTML.replace('><', '>' + element.innerHTML + '<');
            container.innerHTML = '';
            return html;
        }
    },
 
    // Returns true if object is a DOM element.
    isDOMElement: function (object) {
        Iif (typeof HTMLElement === 'object') {
            return object instanceof HTMLElement;
        } else {
            return object &&
                typeof object === 'object' &&
                object.nodeType === 1 &&
                typeof object.nodeName === 'string';
        }
    },
 
    isArray: function (ar) {
        return Object.prototype.toString.call(ar) === '[object Array]';
    },
 
    isRegExp: function (re) {
        var s;
        try {
            s = '' + re;
        } catch (e) {
            return false;
        }
 
        return re instanceof RegExp || // easy case
        // duck-type for context-switching evalcx case
        typeof(re) === 'function' &&
            re.constructor.name === 'RegExp' &&
            re.compile &&
            re.test &&
            re.exec &&
            s.match(/^\/.*\/[gim]{0,3}$/);
    },
 
    isError: function (err) {
        return typeof err === 'object' && Object.prototype.toString.call(err) === '[object Error]';
    },
 
    extend: function (target) {
        var sources = Array.prototype.slice.call(arguments, 1);
        forEach(sources, function (source) {
            forEach(getKeys(source), function (key) {
                target[key] = source[key];
            });
        });
        return target;
    },
 
    isUndefinedOrNull: function (value) {
        return value === null || value === undefined;
    },
 
    isArguments: function (object) {
        return Object.prototype.toString.call(object) === '[object Arguments]';
    },
 
    getKeysOfDefinedProperties: function (object) {
        var keys = filter(getKeys(object), function (key) {
            return typeof object[key] !== 'undefined';
        });
        // The 'message' property of Error instances is enumerable for some reason, but we want
        // to include it in the set when comparing:
        if (Object.prototype.toString.call(object) === '[object Error]') {
            keys.push('message');
        }
        return keys;
    },
 
    /**
     * Levenshtein distance algorithm from wikipedia
     * http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
     */
    levenshteinDistance: function (a, b) {
        Iif (a.length === 0) return b.length;
        Iif (b.length === 0) return a.length;
 
        var matrix = [];
 
        // increment along the first column of each row
        var i;
        for (i = 0; i <= b.length; i += 1) {
            matrix[i] = [i];
        }
 
        // increment each column in the first row
        var j;
        for (j = 0; j <= a.length; j += 1) {
            matrix[0][j] = j;
        }
 
        // Fill in the rest of the matrix
        for (i = 1; i <= b.length; i += 1) {
            for (j = 1; j <= a.length; j += 1) {
                if (b.charAt(i - 1) === a.charAt(j - 1)) {
                    matrix[i][j] = matrix[i - 1][j - 1];
                } else {
                    matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
                                            Math.min(matrix[i][j - 1] + 1, // insertion
                                                     matrix[i - 1][j] + 1)); // deletion
                }
            }
        }
 
        return matrix[b.length][a.length];
    },
 
    truncateStack: function (err, fn) {
        Eif (Error.captureStackTrace) {
            Error.captureStackTrace(err, fn);
        } else if ('stack' in err) {
            // Excludes IE<10, and fn cannot be anonymous for this backup plan to work:
            var stackEntries = err.stack.split(/\r\n?|\n\r?/),
            needle = 'at ' + fn.name + ' ';
            for (var i = 0 ; i < stackEntries.length ; i += 1) {
                if (stackEntries[i].indexOf(needle) !== -1) {
                    stackEntries.splice(1, i);
                    err.stack = stackEntries.join("\n");
                }
            }
        }
        return err;
    },
 
    findFirst: function (arr, predicate, thisObj) {
        var scope = thisObj || null;
        for (var i = 0 ; i < arr.length ; i += 1) {
            if (predicate.call(scope, arr[i], i, arr)) {
                return arr[i];
            }
        }
        return null;
    },
 
    leftPad: function (str, width, ch) {
        ch = ch || ' ';
        while (str.length < width) {
            str = ch + str;
        }
        return str;
    },
 
    cloneError: function (e) {
        var newError = new Error();
        forEach(getKeys(e), function (key) {
            if (!errorMethodBlacklist[key]) {
                newError[key] = e[key];
            }
        });
        return newError;
    }
};