1'use strict';
2
3var SafeString = require('./runtime').SafeString;
4
5/**
6 * Returns `true` if the object is a function, otherwise `false`.
7 * @param { any } value
8 * @returns { boolean }
9 */
10function callable(value) {
11  return typeof value === 'function';
12}
13exports.callable = callable;
14
15/**
16 * Returns `true` if the object is strictly not `undefined`.
17 * @param { any } value
18 * @returns { boolean }
19 */
20function defined(value) {
21  return value !== undefined;
22}
23exports.defined = defined;
24
25/**
26 * Returns `true` if the operand (one) is divisble by the test's argument
27 * (two).
28 * @param { number } one
29 * @param { number } two
30 * @returns { boolean }
31 */
32function divisibleby(one, two) {
33  return one % two === 0;
34}
35exports.divisibleby = divisibleby;
36
37/**
38 * Returns true if the string has been escaped (i.e., is a SafeString).
39 * @param { any } value
40 * @returns { boolean }
41 */
42function escaped(value) {
43  return value instanceof SafeString;
44}
45exports.escaped = escaped;
46
47/**
48 * Returns `true` if the arguments are strictly equal.
49 * @param { any } one
50 * @param { any } two
51 */
52function equalto(one, two) {
53  return one === two;
54}
55exports.equalto = equalto;
56
57// Aliases
58exports.eq = exports.equalto;
59exports.sameas = exports.equalto;
60
61/**
62 * Returns `true` if the value is evenly divisible by 2.
63 * @param { number } value
64 * @returns { boolean }
65 */
66function even(value) {
67  return value % 2 === 0;
68}
69exports.even = even;
70
71/**
72 * Returns `true` if the value is falsy - if I recall correctly, '', 0, false,
73 * undefined, NaN or null. I don't know if we should stick to the default JS
74 * behavior or attempt to replicate what Python believes should be falsy (i.e.,
75 * empty arrays, empty dicts, not 0...).
76 * @param { any } value
77 * @returns { boolean }
78 */
79function falsy(value) {
80  return !value;
81}
82exports.falsy = falsy;
83
84/**
85 * Returns `true` if the operand (one) is greater or equal to the test's
86 * argument (two).
87 * @param { number } one
88 * @param { number } two
89 * @returns { boolean }
90 */
91function ge(one, two) {
92  return one >= two;
93}
94exports.ge = ge;
95
96/**
97 * Returns `true` if the operand (one) is greater than the test's argument
98 * (two).
99 * @param { number } one
100 * @param { number } two
101 * @returns { boolean }
102 */
103function greaterthan(one, two) {
104  return one > two;
105}
106exports.greaterthan = greaterthan;
107
108// alias
109exports.gt = exports.greaterthan;
110
111/**
112 * Returns `true` if the operand (one) is less than or equal to the test's
113 * argument (two).
114 * @param { number } one
115 * @param { number } two
116 * @returns { boolean }
117 */
118function le(one, two) {
119  return one <= two;
120}
121exports.le = le;
122
123/**
124 * Returns `true` if the operand (one) is less than the test's passed argument
125 * (two).
126 * @param { number } one
127 * @param { number } two
128 * @returns { boolean }
129 */
130function lessthan(one, two) {
131  return one < two;
132}
133exports.lessthan = lessthan;
134
135// alias
136exports.lt = exports.lessthan;
137
138/**
139 * Returns `true` if the string is lowercased.
140 * @param { string } value
141 * @returns { boolean }
142 */
143function lower(value) {
144  return value.toLowerCase() === value;
145}
146exports.lower = lower;
147
148/**
149 * Returns `true` if the operand (one) is less than or equal to the test's
150 * argument (two).
151 * @param { number } one
152 * @param { number } two
153 * @returns { boolean }
154 */
155function ne(one, two) {
156  return one !== two;
157}
158exports.ne = ne;
159
160/**
161 * Returns true if the value is strictly equal to `null`.
162 * @param { any }
163 * @returns { boolean }
164 */
165function nullTest(value) {
166  return value === null;
167}
168exports.null = nullTest;
169
170/**
171 * Returns true if value is a number.
172 * @param { any }
173 * @returns { boolean }
174 */
175function number(value) {
176  return typeof value === 'number';
177}
178exports.number = number;
179
180/**
181 * Returns `true` if the value is *not* evenly divisible by 2.
182 * @param { number } value
183 * @returns { boolean }
184 */
185function odd(value) {
186  return value % 2 === 1;
187}
188exports.odd = odd;
189
190/**
191 * Returns `true` if the value is a string, `false` if not.
192 * @param { any } value
193 * @returns { boolean }
194 */
195function string(value) {
196  return typeof value === 'string';
197}
198exports.string = string;
199
200/**
201 * Returns `true` if the value is not in the list of things considered falsy:
202 * '', null, undefined, 0, NaN and false.
203 * @param { any } value
204 * @returns { boolean }
205 */
206function truthy(value) {
207  return !!value;
208}
209exports.truthy = truthy;
210
211/**
212 * Returns `true` if the value is undefined.
213 * @param { any } value
214 * @returns { boolean }
215 */
216function undefinedTest(value) {
217  return value === undefined;
218}
219exports.undefined = undefinedTest;
220
221/**
222 * Returns `true` if the string is uppercased.
223 * @param { string } value
224 * @returns { boolean }
225 */
226function upper(value) {
227  return value.toUpperCase() === value;
228}
229exports.upper = upper;
230
231/**
232 * If ES6 features are available, returns `true` if the value implements the
233 * `Symbol.iterator` method. If not, it's a string or Array.
234 *
235 * Could potentially cause issues if a browser exists that has Set and Map but
236 * not Symbol.
237 *
238 * @param { any } value
239 * @returns { boolean }
240 */
241function iterable(value) {
242  if (typeof Symbol !== 'undefined') {
243    return !!value[Symbol.iterator];
244  } else {
245    return Array.isArray(value) || typeof value === 'string';
246  }
247}
248exports.iterable = iterable;
249
250/**
251 * If ES6 features are available, returns `true` if the value is an object hash
252 * or an ES6 Map. Otherwise just return if it's an object hash.
253 * @param { any } value
254 * @returns { boolean }
255 */
256function mapping(value) {
257  // only maps and object hashes
258  var bool = value !== null && value !== undefined && typeof value === 'object' && !Array.isArray(value);
259  if (Set) {
260    return bool && !(value instanceof Set);
261  } else {
262    return bool;
263  }
264}
265exports.mapping = mapping;