utils.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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')
  61. ? Array.isArray
  62. : function (obj) {
  63. return obj
  64. ? typeof obj === 'object' &&
  65. Object.prototype.toString.call(obj).indexOf() !== -1
  66. : false
  67. }
  68. /**
  69. * Test if an item in an enumerable matches your conditions.
  70. * @param {array|object} obj Enumerable object.
  71. * @param {Function} fn Executed for each item. Return true if your condition is met.
  72. * @return {boolean}
  73. */
  74. exports.some = function (obj, fn) {
  75. var i = 0
  76. var result
  77. var l
  78. if (isArray(obj)) {
  79. l = obj.length
  80. for (i; i < l; i += 1) {
  81. result = fn(obj[i], i, obj)
  82. if (result) {
  83. break
  84. }
  85. }
  86. } else {
  87. exports.each(obj, function (value, index) {
  88. result = fn(value, index, obj)
  89. return !result
  90. })
  91. }
  92. return !!result
  93. }
  94. /**
  95. * Return a new enumerable, mapped by a given iteration function.
  96. * @param {object} obj Enumerable object.
  97. * @param {Function} fn Executed for each item. Return the item to replace the original item with.
  98. * @return {object} New mapped object.
  99. */
  100. exports.map = function (obj, fn) {
  101. var i = 0
  102. var result = []
  103. var l
  104. if (isArray(obj)) {
  105. l = obj.length
  106. for (i; i < l; i += 1) {
  107. result[i] = fn(obj[i], i)
  108. }
  109. } else {
  110. for (i in obj) {
  111. if (obj.hasOwnProperty(i)) {
  112. result[i] = fn(obj[i], i)
  113. }
  114. }
  115. }
  116. return result
  117. }
  118. /**
  119. * 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.
  120. * @param {...object} arguments
  121. * @return {object}
  122. */
  123. exports.extend = function () {
  124. var args = arguments
  125. var target = args[0]
  126. var objs = args.length > 1 ? Array.prototype.slice.call(args, 1) : []
  127. var i = 0
  128. var l = objs.length
  129. var key
  130. var obj
  131. for (i; i < l; i += 1) {
  132. obj = objs[i] || {}
  133. for (key in obj) {
  134. if (obj.hasOwnProperty(key)) {
  135. target[key] = obj[key]
  136. }
  137. }
  138. }
  139. return target
  140. }
  141. /**
  142. * Get all of the keys on an object.
  143. * @param {object} obj
  144. * @return {array}
  145. */
  146. exports.keys = function (obj) {
  147. if (!obj) {
  148. return []
  149. }
  150. if (Object.keys) {
  151. return Object.keys(obj)
  152. }
  153. return exports.map(obj, function (v, k) {
  154. return k
  155. })
  156. }
  157. /**
  158. * Throw an error with possible line number and source file.
  159. * @param {string} message Error message
  160. * @param {number} [line] Line number in template.
  161. * @param {string} [file] Template file the error occured in.
  162. * @throws {Error} No seriously, the point is to throw an error.
  163. */
  164. exports.throwError = function (message, line, file) {
  165. if (line) {
  166. message += ' on line ' + line
  167. }
  168. if (file) {
  169. message += ' in file ' + file
  170. }
  171. throw new Error(message + '.')
  172. }