JAVASCRIPT   67

underscore.string.js

Guest on 9th September 2021 02:22:10 AM

  1. // Underscore.string
  2. // (c)  Esa-Matti Suuronen <esa-matti aet suuronen dot org>
  3. // Underscore.strings is freely distributable under the terms of the MIT license.
  4. // Documentation: https://github.com/epeli/underscore.string
  5. // Some code is borrowed from MooTools and Alexandru Marasteanu.
  6.  
  7. // Version 2.2.0rc
  8.  
  9. (function(root){
  10.   'use strict';
  11.  
  12.   // Defining helper functions.
  13.  
  14.   var nativeTrim = String.prototype.trim;
  15.   var nativeTrimRight = String.prototype.trimRight;
  16.   var nativeTrimLeft = String.prototype.trimLeft;
  17.  
  18.   var parseNumber = function(source) { return source * 1 || 0; };
  19.  
  20.   var strRepeat = function(str, qty, separator){
  21.     // ~~var ā€” is the fastest available way to convert anything to Integer in javascript.
  22. ipt.// We'll use it extensively in this lib.
  23. lib.
  24.     str += ''; qty = ~~qty;
  25.     for (var repeat = []; qty > 0; repeat[--qty] = str) {}
  26.     return repeat.join(separator == null ? '' : separator);
  27.   };
  28.  
  29.   var slice = function(a){
  30.     return Array.prototype.slice.call(a);
  31.   };
  32.  
  33.   var defaultToWhiteSpace = function(characters){
  34.     if (characters != null) {
  35.       return '[' + _s.escapeRegExp(''+characters) + ']';
  36.     }
  37.     return '\\s';
  38.   };
  39.  
  40.   var escapeChars = {
  41.     lt: '<',
  42.     gt: '>',
  43.     quot: '"',
  44.     apos: "'",
  45.     amp: '&'
  46.   };
  47.  
  48.   var reversedEscapeChars = {};
  49.   for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; // sprintf() for JavaScript 0.7-beta1
  50. et// http://www.diveintojavascript.com/projects/javascript-sprintf
  51. in//
  52.   // Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
  53. co// All rights reserved.
  54. ved.
  55.  
  56.   var sprintf = (function() {
  57.     function get_type(variable) {
  58.       return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
  59.     }
  60.  
  61.     var str_repeat = strRepeat;
  62.  
  63.     var str_format = function() {
  64.       if (!str_format.cache.hasOwnProperty(arguments[0])) {
  65.         str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
  66.       }
  67.       return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
  68.     };
  69.  
  70.     str_format.format = function(parse_tree, argv) {
  71.       var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
  72.       for (i = 0; i < tree_length; i++) {
  73.         node_type = get_type(parse_tree[i]);
  74.         if (node_type === 'string') {
  75.           output.push(parse_tree[i]);
  76.         }
  77.         else if (node_type === 'array') {
  78.           match = parse_tree// convenience purposes only
  79. only
  80.           if (match[2// keyword argument
  81. ment
  82.             arg = argv[cursor];
  83.             for (k = 0; k < match[2].length; k++) {
  84.               if (!arg.hasOwnProperty(match[2][k])) {
  85.                 throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
  86.               }
  87.               arg = arg[match[2][k]];
  88.             }
  89.           } else if (match[1// positional argument (explicit)
  90. cit)
  91.             arg = argv[match[1]];
  92.           }
  93.           el// positional argument (implicit)
  94. cit)
  95.             arg = argv[cursor++];
  96.           }
  97.  
  98.           if (/.test.test(match[8]) && (get_type(arg) != 'number')) {
  99.             throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
  100.           }
  101.           switch (match[8]) {
  102.             case 'b': arg = arg.toString(2); break;
  103.             case 'c': arg = String.fromCharCode(arg); break;
  104.             case 'd': arg = parseInt(arg, 10); break;
  105.             case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
  106.             case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
  107.             case 'o': arg = arg.toString(8); break;
  108.             case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
  109.             case 'u': arg = Math.abs(arg); break;
  110.             case 'x': arg = arg.toString(16); break;
  111.             case 'X': arg = arg.toString(16).toUpperCase(); break;
  112.           }
  113.           arg = (]/.test.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
  114.           pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
  115.           pad_length = match[6] - String(arg).length;
  116.           pad = match[6] ? str_repeat(pad_character, pad_length) : '';
  117.           output.push(match[5] ? arg + pad : pad + arg);
  118.         }
  119.       }
  120.       return output.join('');
  121.     };
  122.  
  123.     str_format.cache = {};
  124.  
  125.     str_format.parse = function(fmt) {
  126.       var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
  127.       while (_fmt) {
  128.         if ((match = x25]+/.exec.exec(_fmt)) !== null) {
  129.           parse_tree.push(match[0]);
  130.         }
  131.         else if ((match = 5{2}/.exec.exec(_fmt)) !== null) {
  132.           parse_tree.push('%');
  133.         }
  134.         else if ((match = 5(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec.exec(_fmt)) !== null) {
  135.           if (match[2]) {
  136.             arg_names |= 1;
  137.             var field_list = [], replacement_field = match[2], field_match = [];
  138.             if ((field_match = -z_][a-z_\d]*)/i.exec.exec(replacement_field)) !== null) {
  139.               field_list.push(field_match[1]);
  140.               while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
  141.                 if ((field_match = [a-z_][a-z_\d]*)/i.exec.exec(replacement_field)) !== null) {
  142.                   field_list.push(field_match[1]);
  143.                 }
  144.                 else if ((field_match = \d+)\]/.exec.exec(replacement_field)) !== null) {
  145.                   field_list.push(field_match[1]);
  146.                 }
  147.                 else {
  148.                   throw new Error('[_.sprintf] huh?');
  149.                 }
  150.               }
  151.             }
  152.             else {
  153.               throw new Error('[_.sprintf] huh?');
  154.             }
  155.             match[2] = field_list;
  156.           }
  157.           else {
  158.             arg_names |= 2;
  159.           }
  160.           if (arg_names === 3) {
  161.             throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
  162.           }
  163.           parse_tree.push(match);
  164.         }
  165.         else {
  166.           throw new Error('[_.sprintf] huh?');
  167.         }
  168.         _fmt = _fmt.substring(match[0].length);
  169.       }
  170.       return parse_tree;
  171.     };
  172.  
  173.     return str_format;
  174.   })();
  175. // Defining underscore.string
  176. ring
  177.  
  178.   var _s = {
  179.  
  180.     VERSION: '2.2.0rc',
  181.  
  182.     isBlank: function(str){
  183.       return ($/).tes).test(str);
  184.     },
  185.  
  186.     stripTags: function(str){
  187.       return (''+str).replace([^>]+>/g, ''), '');
  188.     },
  189.  
  190.     capitalize : function(str) {
  191.       str += '';
  192.       return str.charAt(0).toUpperCase() + str.substring(1);
  193.     },
  194.  
  195.     chop: function(str, step){
  196.       str = str+'';
  197.       step = ~~step || str.length;
  198.       var arr = [];
  199.       for (var i = 0; i < str.length; i += step)
  200.         arr.push(str.slice(i,i + step));
  201.       return arr;
  202.     },
  203.  
  204.     clean: function(str){
  205.       return _s.strip(str).replace(g, ' ', ' ');
  206.     },
  207.  
  208.     count: function(str, substr){
  209.       str += ''; substr += '';
  210.       return str.split(substr).length - 1;
  211.     },
  212.  
  213.     chars: function(str) {
  214.       return (''+str).split('');
  215.     },
  216.  
  217.     escapeHTML: function(str) {
  218.       return (''+str).replace("']/g, fun, function(match){ return '&' + reversedEscapeChars[match] + ';'; });
  219.     },
  220.  
  221.     unescapeHTML: function(str) {
  222.       return (''+str).replace(^;]+);/g, fun, function(entity, entityCode){
  223.         var match;
  224.        
  225.         if (entityCode in escapeChars) {
  226.           return escapeChars[entityCode];
  227.         } else if (match = entityCode.match([\da-fA-F]+)$/)) {
  228. )) {
  229.           return String.fromCharCode(parseInt(match[1], 16));
  230.         } else if (match = entityCode.match(d+)$/)) {
  231. )) {
  232.           return String.fromCharCode(~~match[1]);
  233.         } else {
  234.           return entity;
  235.         }
  236.       });
  237.     },
  238.  
  239.     escapeRegExp: function(str){
  240.  // From MooTools core 1.2.4
  241. .2.4
  242.       return str.replace(*+?^${}()|[\]\/\\])/g, '\\, ');
  243.    },
  244.  
  245.    insert: function(str, i, substr){
  246.      var arr = _s.chars(str);
  247.      arr.splice(~~i, 0, ' 0, ''+substr);
  248.       return arr.join('');
  249.     },
  250.  
  251.     include: function(str, needle){
  252.       return !!~(''+str).indexOf(needle);
  253.     },
  254.  
  255.     join: function() {
  256.       var args = slice(arguments);
  257.       return args.join(args.shift());
  258.     },
  259.  
  260.     lines: function(str) {
  261.       return (''+str).split("\n");
  262.     },
  263.  
  264.     reverse: function(str){
  265.       return _s.chars(str).reverse().join('');
  266.     },
  267.  
  268.     splice: function(str, i, howmany, substr){
  269.       var arr = _s.chars(str);
  270.       arr.splice(~~i, ~~howmany, substr);
  271.       return arr.join('');
  272.     },
  273.  
  274.     startsWith: function(str, starts){
  275.       str += ''; starts += '';
  276.       return str.length >= starts.length && str.substring(0, starts.length) === starts;
  277.     },
  278.  
  279.     endsWith: function(str, ends){
  280.       str += ''; ends += '';
  281.       return str.length >= ends.length && str.substring(str.length - ends.length) === ends;
  282.     },
  283.  
  284.     succ: function(str){
  285.       str += '';
  286.       var arr = _s.chars(str);
  287.       arr.splice(str.length-1, 1, String.fromCharCode(str.charCodeAt(str.length-1) + 1));
  288.       return arr.join('');
  289.     },
  290.  
  291.     titleize: function(str){
  292.       return (''+str).replace(g, fun, function(ch){ return ch.toUpperCase(); });
  293.     },
  294.  
  295.     camelize: function(str){
  296.       return _s.trim(str).replace(s]+(.)?/g, fun, function(match, chr){
  297.         return chr && chr.toUpperCase();
  298.       });
  299.     },
  300.  
  301.     underscored: function(str){
  302.       return _s.trim(str).replace(z\d])([A-Z]+)/g, '$1, '$1_$2').replace(]+/g, '_', '_').toLowerCase();
  303.     },
  304.  
  305.     dasherize: function(str){
  306.       return _s.trim(str).replace(]+/g, '-', '-').replace(Z])/g, '-$, '-$1').replace(, '-', '-').toLowerCase();
  307.     },
  308.  
  309.     classify: function(str){
  310.       str += '';
  311.       return _s.titleize(str.replace( ' ', ' ')).replace(, ''), '')
  312.     },
  313.  
  314.     humanize: function(str){
  315.       return _s.capitalize(this.underscored(str).replace(/,'').,'').replace( ' ', ' '));
  316.     },
  317.  
  318.     trim: function(str, characters){
  319.       str += '';
  320.       if (!characters && nativeTrim) { return nativeTrim.call(str); }
  321.       characters = defaultToWhiteSpace(characters);
  322.       return str.replace(new RegExp('\^' + characters + '+|' + characters + '+$'), '');
  323.    },
  324.  
  325.    ltrim: function(str, characters){
  326.      str+='tr+='';
  327.       if (!characters && nativeTrimLeft) {
  328.         return nativeTrimLeft.call(str);
  329.       }
  330.       characters = defaultToWhiteSpace(characters);
  331.       return str.replace(new RegExp('^' + characters + '+');
  332.    },
  333.  
  334.    rtrim: function(str, characters){
  335.      str+='tr+='';
  336.       if (!characters && nativeTrimRight) {
  337.         return nativeTrimRight.call(str);
  338.       }
  339.       characters = defaultToWhiteSpace(characters);
  340.       return str.replace(new RegExp(characters + '+$');
  341.    },
  342.  
  343.    truncate: function(str, length, truncateStr){
  344.      str += ' += ''; truncateStr = truncateStr || '...';
  345.       length = ~~length;
  346.       return str.length > length ? str.slice(0, length) + truncateStr : str;
  347.     },
  348. /**
  349.      * _s.prune: a more elegant version of truncate
  350.      * prune extra chars, never leaving a half-chopped word.
  351.      * @author github.com/sergiokas
  352.      */   */
  353.     prune: function(str, length, pruneStr){
  354.       str += ''; length = ~~length;
  355.       pruneStr = pruneStr != null ? ''+pruneStr : '...';
  356.      
  357.       var pruned, borderChar, template = str.replace(, fun, function(ch){
  358.         return (ch.toUpperCase() !== ch.toLowerCase()) ? 'A' : ' ';
  359.       });
  360.      
  361.       borderChar = template.charAt(length);
  362.      
  363.       pruned = template.slice(0, length);
  364.      
  365.  // Check if we're in the middle of a word
  366. word
  367.       if (borderChar && borderChar.match()
  368.   ))
  369.         pruned = pruned.replace(+$/, ''), '');
  370.        
  371.       pruned = _s.rtrim(pruned);
  372.      
  373.       return (pruned+pruneStr).length > str.length ? str : str.substring(0, pruned.length)+pruneStr;
  374.     },
  375.  
  376.     words: function(str, delimiter) {
  377.       return _s.trim(str, delimiter).split(delimiter || );
  378.   );
  379.     },
  380.  
  381.     pad: function(str, length, padStr, type) {
  382.       str += '';
  383.      
  384.       var padlen  = 0;
  385.  
  386.       length = ~~length;
  387.      
  388.       if (!padStr) {
  389.         padStr = ' ';
  390.       } else if (padStr.length > 1) {
  391.         padStr = padStr.charAt(0);
  392.       }
  393.      
  394.       switch(type) {
  395.         case 'right':
  396.           padlen = (length - str.length);
  397.           return str + strRepeat(padStr, padlen);
  398.         case ':
  399.          padlen = (length - str.length);
  400.          return strRepeat(padStr, Math.ceil(padlen/2)) +
  401.                 str +
  402.                 strRepeat(padStr, Math.floor(padlen/2));
  403.        default: // ' // '
  404.          padlen = (length - str.length);
  405.          return strRepeat(padStr, padlen) + str;
  406.        }
  407.    },
  408.  
  409.    lpad: function(str, length, padStr) {
  410.      return _s.pad(str, length, padStr);
  411.    },
  412.  
  413.    rpad: function(str, length, padStr) {
  414.      return _s.pad(str, length, padStr, 'tr, 'right');
  415.     },
  416.  
  417.     lrpad: function(str, length, padStr) {
  418.       return _s.pad(str, length, padStr, ');
  419.    },
  420.  
  421.    sprintf: sprintf,
  422.  
  423.    vsprintf: function(fmt, argv){
  424.      argv.unshift(fmt);
  425.      return sprintf.apply(null, argv);
  426.    },
  427.  
  428.    toNumber: function(str, decimals) {
  429.      str += ' += '';
  430.       var num = parseNumber(parseNumber(str).toFixed(~~decimals));
  431.       return num === 0 && !str.match(/) ? N) ? Number.NaN : num;
  432.     },
  433.  
  434.     strRight: function(str, sep){
  435.       str += ''; sep = sep != null ? ''+sep : sep;
  436.       var pos = !sep ? -1 : str.indexOf(sep);
  437.       return ~pos ? str.slice(pos+sep.length, str.length) : str;
  438.     },
  439.  
  440.     strRightBack: function(str, sep){
  441.       str += ''; sep = sep != null ? ''+sep : sep;
  442.       var pos = !sep ? -1 : str.lastIndexOf(sep);
  443.       return ~pos ? str.slice(pos+sep.length, str.length) : str;
  444.     },
  445.  
  446.     strLeft: function(str, sep){
  447.       str += ''; sep = sep != null ? ''+sep : sep;
  448.       var pos = !sep ? -1 : str.indexOf(sep);
  449.       return ~pos ? str.slice(0, pos) : str;
  450.     },
  451.  
  452.     strLeftBack: function(str, sep){
  453.       str += ''; sep = sep != null ? ''+sep : sep;
  454.       var pos = str.lastIndexOf(sep);
  455.       return ~pos ? str.slice(0, pos) : str;
  456.     },
  457.  
  458.     toSentence: function(array, separator, lastSeparator) {
  459.         separator || (separator = ', ');
  460.         lastSeparator || (lastSeparator = ' and ');
  461.         var length = array.length, str = '';
  462.  
  463.         for (var i = 0; i < length; i++) {
  464.             str += array[i];
  465.             if (i === (length - 2)) { str += lastSeparator; }
  466.             else if (i < (length - 1)) { str += separator; }
  467.         }
  468.  
  469.         return str;
  470.     },
  471.  
  472.     slugify: function(str) {
  473.       var from  = "Ä…Ć Ć�Ć¤Ć¢Ć£Ä‡Ä™ĆØĆ©Ć«ĆŖƬƭĆÆĆ®Å‚Å„Ć²Ć³Ć¶Ć´ĆµĆ¹ĆŗĆ¼Ć»Ć±Ć§Å¼Åŗ",
  474.           to    = "aaaaaaceeeeeiiiilnooooouuuunczz",
  475.           regex = new RegExp(defaultToWhiteSpace(from), 'g');
  476.  
  477.       str = (''+str).toLowerCase();
  478.  
  479.       str = str.replace(regex, function(ch){
  480.         var index = from.indexOf(ch);
  481.         return to.charAt(index) || '-';
  482.       });
  483.  
  484.       return _s.trim(str.replace(ction() {
  485.  , '').replace(t = {};
  486.  
  487. , '-'), '-');
  488.     },
  489.  
  490.     exports: function() {
  491.       var result = {};
  492.  
  493.       for (var prop in this) {
  494.         if (!this.hasOwnProperty(prop) || ~_s.words('include contains reverse').indexOf(prop)) continue;
  495.         result[prop] = this[prop];
  496. // Aliases
  497.     return result;
  498.     },
  499.    
  500.     repeat: strRepeat
  501.   };
  502.  
  503.   // Aliases
  504.  
  505.   _s.strip    = _s.trim;
  506.   _s.lstrip   = _s.ltrim;
  507.   _s.rstrip   = _s.rtrim;
  508.   _s.center   = _s.lrpad;
  509.   _s.rjus// CommonJS module is defined
  510. = _s.rpad;
  511.   _s.contains = _s.include;
  512.  
  513.   // CommonJS module is defined
  514.   if (typeof exports !== 'undefin// Export module
  515. peof module !== 'undefined' && module.exports) {
  516.       // Export module
  517.       module.exports = _s;
  518.     }
  519.     exports._// Register as a named module with AMD.
  520. 'function' && define.amd) {
  521.     // Register as a named module with AMD.
  522.     define('unders// Integrate with Underscore.js if defined
  523.  
  524.    // or create our own underscore object.
  525. th Underscore.js if defined
  526.     // or create our own underscore object.
  527.     root._ = roo

Raw Paste


Login or Register to edit or fork this paste. It's free.