'use strict'; /* eslint-disable max-params */ /* Expose. */ module.exports = is; /* Assert if `test` passes for `node`. * When a `parent` node is known the `index` of node */ function is(test, node, index, parent, context) { var hasParent = parent !== null && parent !== undefined; var hasIndex = index !== null && index !== undefined; var check = convert(test); if ( hasIndex && (typeof index !== 'number' || index < 0 || index === Infinity) ) { throw new Error('Expected positive finite index or child node'); } if (hasParent && (!is(null, parent) || !parent.children)) { throw new Error('Expected parent node'); } if (!node || !node.type || typeof node.type !== 'string') { return false; } if (hasParent !== hasIndex) { throw new Error('Expected both parent and index'); } return Boolean(check.call(context, node, index, parent)); } function convert(test) { if (typeof test === 'string') { return typeFactory(test); } if (test === null || test === undefined) { return ok; } if (typeof test === 'object') { return ('length' in test ? anyFactory : matchesFactory)(test); } if (typeof test === 'function') { return test; } throw new Error('Expected function, string, or object as test'); } function convertAll(tests) { var results = []; var length = tests.length; var index = -1; while (++index < length) { results[index] = convert(tests[index]); } return results; } /* Utility assert each property in `test` is represented * in `node`, and each values are strictly equal. */ function matchesFactory(test) { return matches; function matches(node) { var key; for (key in test) { if (node[key] !== test[key]) { return false; } } return true; } } function anyFactory(tests) { var checks = convertAll(tests); var length = checks.length; return matches; function matches() { var index = -1; while (++index < length) { if (checks[index].apply(this, arguments)) { return true; } } return false; } } /* Utility to convert a string into a function which checks * a given node’s type for said string. */ function typeFactory(test) { return type; function type(node) { return Boolean(node && node.type === test); } } /* Utility to return true. */ function ok() { return true; }