utils.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. var isArray;
  2. /**
  3. * Strip leading and trailing whitespace from a string.
  4. * @param {string} input
  5. * @return {string} Stripped input.
  6. */
  7. exports.strip = function (input) {
  8. return input.replace(/^\s+|\s+$/g, '');
  9. };
  10. /**
  11. * Test if a string starts with a given prefix.
  12. * @param {string} str String to test against.
  13. * @param {string} prefix Prefix to check for.
  14. * @return {boolean}
  15. */
  16. exports.startsWith = function (str, prefix) {
  17. return str.indexOf(prefix) === 0;
  18. };
  19. /**
  20. * Test if a string ends with a given suffix.
  21. * @param {string} str String to test against.
  22. * @param {string} suffix Suffix to check for.
  23. * @return {boolean}
  24. */
  25. exports.endsWith = function (str, suffix) {
  26. return str.indexOf(suffix, str.length - suffix.length) !== -1;
  27. };
  28. /**
  29. * Iterate over an array or object.
  30. * @param {array|object} obj Enumerable object.
  31. * @param {Function} fn Callback function executed for each item.
  32. * @return {array|object} The original input object.
  33. */
  34. exports.each = function (obj, fn) {
  35. var i, l;
  36. if (isArray(obj)) {
  37. i = 0;
  38. l = obj.length;
  39. for (i; i < l; i += 1) {
  40. if (fn(obj[i], i, obj) === false) {
  41. break;
  42. }
  43. }
  44. } else {
  45. for (i in obj) {
  46. if (obj.hasOwnProperty(i)) {
  47. if (fn(obj[i], i, obj) === false) {
  48. break;
  49. }
  50. }
  51. }
  52. }
  53. return obj;
  54. };
  55. /**
  56. * Test if an object is an Array.
  57. * @param {object} obj
  58. * @return {boolean}
  59. */
  60. exports.isArray = isArray = (Array.hasOwnProperty('isArray')) ? Array.isArray : function (obj) {
  61. return (obj) ? (typeof obj === 'object' && Object.prototype.toString.call(obj).indexOf() !== -1) : false;
  62. };
  63. /**
  64. * Test if an item in an enumerable matches your conditions.
  65. * @param {array|object} obj Enumerable object.
  66. * @param {Function} fn Executed for each item. Return true if your condition is met.
  67. * @return {boolean}
  68. */
  69. exports.some = function (obj, fn) {
  70. var i = 0,
  71. result,
  72. l;
  73. if (isArray(obj)) {
  74. l = obj.length;
  75. for (i; i < l; i += 1) {
  76. result = fn(obj[i], i, obj);
  77. if (result) {
  78. break;
  79. }
  80. }
  81. } else {
  82. exports.each(obj, function (value, index, collection) {
  83. result = fn(value, index, obj);
  84. return !(result);
  85. });
  86. }
  87. return !!result;
  88. };
  89. /**
  90. * Return a new enumerable, mapped by a given iteration function.
  91. * @param {object} obj Enumerable object.
  92. * @param {Function} fn Executed for each item. Return the item to replace the original item with.
  93. * @return {object} New mapped object.
  94. */
  95. exports.map = function (obj, fn) {
  96. var i = 0,
  97. result = [],
  98. l;
  99. if (isArray(obj)) {
  100. l = obj.length;
  101. for (i; i < l; i += 1) {
  102. result[i] = fn(obj[i], i);
  103. }
  104. } else {
  105. for (i in obj) {
  106. if (obj.hasOwnProperty(i)) {
  107. result[i] = fn(obj[i], i);
  108. }
  109. }
  110. }
  111. return result;
  112. };
  113. /**
  114. * Copy all of the properties in the source objects over to the destination object, and return the destination object. It's in-order, so the last source will override properties of the same name in previous arguments.
  115. * @param {...object} arguments
  116. * @return {object}
  117. */
  118. exports.extend = function () {
  119. var args = arguments,
  120. target = args[0],
  121. objs = (args.length > 1) ? Array.prototype.slice.call(args, 1) : [],
  122. i = 0,
  123. l = objs.length,
  124. key,
  125. obj;
  126. for (i; i < l; i += 1) {
  127. obj = objs[i] || {};
  128. for (key in obj) {
  129. if (obj.hasOwnProperty(key)) {
  130. target[key] = obj[key];
  131. }
  132. }
  133. }
  134. return target;
  135. };
  136. /**
  137. * Get all of the keys on an object.
  138. * @param {object} obj
  139. * @return {array}
  140. */
  141. exports.keys = function (obj) {
  142. if (Object.keys) {
  143. return Object.keys(obj);
  144. }
  145. return exports.map(obj, function (v, k) {
  146. return k;
  147. });
  148. };
  149. /**
  150. * Throw an error with possible line number and source file.
  151. * @param {string} message Error message
  152. * @param {number} [line] Line number in template.
  153. * @param {string} [file] Template file the error occured in.
  154. * @throws {Error} No seriously, the point is to throw an error.
  155. */
  156. exports.throwError = function (message, line, file) {
  157. if (line) {
  158. message += ' on line ' + line;
  159. }
  160. if (file) {
  161. message += ' in file ' + file;
  162. }
  163. throw new Error(message + '.');
  164. };