twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

utils.js (5554B)


      1 'use strict';
      2 
      3 var has = Object.prototype.hasOwnProperty;
      4 
      5 var hexTable = (function () {
      6     var array = [];
      7     for (var i = 0; i < 256; ++i) {
      8         array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
      9     }
     10 
     11     return array;
     12 }());
     13 
     14 var compactQueue = function compactQueue(queue) {
     15     var obj;
     16 
     17     while (queue.length) {
     18         var item = queue.pop();
     19         obj = item.obj[item.prop];
     20 
     21         if (Array.isArray(obj)) {
     22             var compacted = [];
     23 
     24             for (var j = 0; j < obj.length; ++j) {
     25                 if (typeof obj[j] !== 'undefined') {
     26                     compacted.push(obj[j]);
     27                 }
     28             }
     29 
     30             item.obj[item.prop] = compacted;
     31         }
     32     }
     33 
     34     return obj;
     35 };
     36 
     37 var arrayToObject = function arrayToObject(source, options) {
     38     var obj = options && options.plainObjects ? Object.create(null) : {};
     39     for (var i = 0; i < source.length; ++i) {
     40         if (typeof source[i] !== 'undefined') {
     41             obj[i] = source[i];
     42         }
     43     }
     44 
     45     return obj;
     46 };
     47 
     48 var merge = function merge(target, source, options) {
     49     if (!source) {
     50         return target;
     51     }
     52 
     53     if (typeof source !== 'object') {
     54         if (Array.isArray(target)) {
     55             target.push(source);
     56         } else if (typeof target === 'object') {
     57             if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
     58                 target[source] = true;
     59             }
     60         } else {
     61             return [target, source];
     62         }
     63 
     64         return target;
     65     }
     66 
     67     if (typeof target !== 'object') {
     68         return [target].concat(source);
     69     }
     70 
     71     var mergeTarget = target;
     72     if (Array.isArray(target) && !Array.isArray(source)) {
     73         mergeTarget = arrayToObject(target, options);
     74     }
     75 
     76     if (Array.isArray(target) && Array.isArray(source)) {
     77         source.forEach(function (item, i) {
     78             if (has.call(target, i)) {
     79                 if (target[i] && typeof target[i] === 'object') {
     80                     target[i] = merge(target[i], item, options);
     81                 } else {
     82                     target.push(item);
     83                 }
     84             } else {
     85                 target[i] = item;
     86             }
     87         });
     88         return target;
     89     }
     90 
     91     return Object.keys(source).reduce(function (acc, key) {
     92         var value = source[key];
     93 
     94         if (has.call(acc, key)) {
     95             acc[key] = merge(acc[key], value, options);
     96         } else {
     97             acc[key] = value;
     98         }
     99         return acc;
    100     }, mergeTarget);
    101 };
    102 
    103 var assign = function assignSingleSource(target, source) {
    104     return Object.keys(source).reduce(function (acc, key) {
    105         acc[key] = source[key];
    106         return acc;
    107     }, target);
    108 };
    109 
    110 var decode = function (str) {
    111     try {
    112         return decodeURIComponent(str.replace(/\+/g, ' '));
    113     } catch (e) {
    114         return str;
    115     }
    116 };
    117 
    118 var encode = function encode(str) {
    119     // This code was originally written by Brian White (mscdex) for the io.js core querystring library.
    120     // It has been adapted here for stricter adherence to RFC 3986
    121     if (str.length === 0) {
    122         return str;
    123     }
    124 
    125     var string = typeof str === 'string' ? str : String(str);
    126 
    127     var out = '';
    128     for (var i = 0; i < string.length; ++i) {
    129         var c = string.charCodeAt(i);
    130 
    131         if (
    132             c === 0x2D // -
    133             || c === 0x2E // .
    134             || c === 0x5F // _
    135             || c === 0x7E // ~
    136             || (c >= 0x30 && c <= 0x39) // 0-9
    137             || (c >= 0x41 && c <= 0x5A) // a-z
    138             || (c >= 0x61 && c <= 0x7A) // A-Z
    139         ) {
    140             out += string.charAt(i);
    141             continue;
    142         }
    143 
    144         if (c < 0x80) {
    145             out = out + hexTable[c];
    146             continue;
    147         }
    148 
    149         if (c < 0x800) {
    150             out = out + (hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]);
    151             continue;
    152         }
    153 
    154         if (c < 0xD800 || c >= 0xE000) {
    155             out = out + (hexTable[0xE0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]);
    156             continue;
    157         }
    158 
    159         i += 1;
    160         c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
    161         out += hexTable[0xF0 | (c >> 18)]
    162             + hexTable[0x80 | ((c >> 12) & 0x3F)]
    163             + hexTable[0x80 | ((c >> 6) & 0x3F)]
    164             + hexTable[0x80 | (c & 0x3F)];
    165     }
    166 
    167     return out;
    168 };
    169 
    170 var compact = function compact(value) {
    171     var queue = [{ obj: { o: value }, prop: 'o' }];
    172     var refs = [];
    173 
    174     for (var i = 0; i < queue.length; ++i) {
    175         var item = queue[i];
    176         var obj = item.obj[item.prop];
    177 
    178         var keys = Object.keys(obj);
    179         for (var j = 0; j < keys.length; ++j) {
    180             var key = keys[j];
    181             var val = obj[key];
    182             if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
    183                 queue.push({ obj: obj, prop: key });
    184                 refs.push(val);
    185             }
    186         }
    187     }
    188 
    189     return compactQueue(queue);
    190 };
    191 
    192 var isRegExp = function isRegExp(obj) {
    193     return Object.prototype.toString.call(obj) === '[object RegExp]';
    194 };
    195 
    196 var isBuffer = function isBuffer(obj) {
    197     if (obj === null || typeof obj === 'undefined') {
    198         return false;
    199     }
    200 
    201     return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
    202 };
    203 
    204 module.exports = {
    205     arrayToObject: arrayToObject,
    206     assign: assign,
    207     compact: compact,
    208     decode: decode,
    209     encode: encode,
    210     isBuffer: isBuffer,
    211     isRegExp: isRegExp,
    212     merge: merge
    213 };