Plato on Github
Report Home
src/filter.js
Maintainability
86.18
Lines of code
228
Difficulty
13.00
Estimated Errors
0.51
Function weight
By Complexity
By SLOC
/** * @file Filtering helper * @since 0.1.9 */ /*#ifndef(UMD)*/ "use strict"; /*global _GPF_START*/ // 0 /*global _gpfFunc*/ // Create a new function using the source /*#endif*/ /** * Filtering function * * @callback gpf.typedef.filterFunc * * @param {*} data Data to filter * @return {Boolean} truthy / falsy value indicating if the data matches the filter * * @since 0.2.4 */ /** * Filter property read specification * * @typedef gpf.typedef.filterProperty * @property {String} property Property name to read * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter equal specification * * @typedef gpf.typedef.filterEq * @property {gpf.typedef.filterItem[]} eq List of items to compare, * returns true if all values are strictly equal * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter not equal specification * * @typedef gpf.typedef.filterNe * @property {gpf.typedef.filterItem[]} eq List of items to compare, * returns true if all values are strictly different * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter lower than specification * * @typedef gpf.typedef.filterLt * @property {gpf.typedef.filterItem[]} lt List of items to compare * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter lower than or equal specification * * @typedef gpf.typedef.filterLte * @property {gpf.typedef.filterItem[]} lte List of items to compare * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter greater than specification * * @typedef gpf.typedef.filterGt * @property {gpf.typedef.filterItem[]} gt List of items to compare * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter greater than or equal specification * * @typedef gpf.typedef.filterGte * @property {gpf.typedef.filterItem[]} gte List of items to compare * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter not specification * * @typedef gpf.typedef.filterNot * @property {gpf.typedef.filterItem} not Item to negate, * returns true if the item is falsy, false otherwise * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter like specification * * @typedef gpf.typedef.filterLike * @property {gpf.typedef.filterItem} like Item * @property {String} regexp Regular expression specification * @property {Number} [group] If the regular expression contains capturing group, this members can be used to return * the group by index (1-based) * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter OR specification * * @typedef gpf.typedef.filterOr * @property {gpf.typedef.filterItem[]} or List of items to or, * returns the first truthy value or the last falsy value * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter AND specification * * @typedef gpf.typedef.filterAnd * @property {gpf.typedef.filterItem[]} and List of items to and, * returns the first falsy value or the last truthy value * @see gpf.createFilterFunction * @since 0.1.9 */ /** * Filter specification * * @typedef { * gpf.typedef.filterProperty * | gpf.typedef.filterEq * | gpf.typedef.filterNe * | gpf.typedef.filterLt * | gpf.typedef.filterLte * | gpf.typedef.filterGt * | gpf.typedef.filterGte * | gpf.typedef.filterNot * | gpf.typedef.filterLike * | gpf.typedef.filterOr * | gpf.typedef.filterAnd * } gpf.typedef.filterItem * @see gpf.createFilterFunction * @since 0.1.9 */ // Avoid use before declaration var _gpfCreateFilterConvert; function _gpfCreateFilterArrayConverter (member, operator) { return function (specification) { return "(" + specification[member].map(_gpfCreateFilterConvert).join(operator) + ")"; }; } function _gpfCreateFilterLike (specification) { return "/" + specification.regexp + "/.exec(" + _gpfCreateFilterConvert(specification.like) + ")"; } var // List of converters _gpfCreateFilterConverters = { property: function (specification) { return "i." + specification.property; }, eq: _gpfCreateFilterArrayConverter("eq", "==="), ne: _gpfCreateFilterArrayConverter("ne", "!=="), lt: _gpfCreateFilterArrayConverter("lt", "<"), lte: _gpfCreateFilterArrayConverter("lte", "<="), gt: _gpfCreateFilterArrayConverter("gt", ">"), gte: _gpfCreateFilterArrayConverter("gte", ">="), not: function (specification) { return "!" + _gpfCreateFilterConvert(specification.not); }, like: function (specification) { var like = _gpfCreateFilterLike(specification); if (specification.group) { return "(" + like + "||[])[" + specification.group + "]"; } return like; }, or: _gpfCreateFilterArrayConverter("or", "||"), and: _gpfCreateFilterArrayConverter("and", "&&"), undefined: function (specification) { return JSON.stringify(specification); } }, _gpfCreateFilterTypes = Object.keys(_gpfCreateFilterConverters); function _gpfCreateFilterGetType (specification) { if (typeof specification === "object") { return Object.keys(specification).filter(function (property) { return _gpfCreateFilterTypes.includes(property); })[_GPF_START]; } } _gpfCreateFilterConvert = function (specification) { var type = _gpfCreateFilterGetType(specification), converter = _gpfCreateFilterConverters[type]; return converter(specification); }; function _gpfCreateFilterBody (specification) { return "return " + _gpfCreateFilterConvert(specification); } /** * Create a filtering function based on the given specification. * * @param {gpf.typedef.filterItem} specification Filter specification * @return {gpf.typedef.filterFunc} Function that takes an object and return a truthy / falsy value indicating if the * object matches the filter * @since 0.1.9 */ gpf.createFilterFunction = function (specification) { return _gpfFunc(["i"], _gpfCreateFilterBody(specification)); };