forked from mapbox/feature-filter
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
78 lines (71 loc) · 2.36 KB
/
index.js
File metadata and controls
78 lines (71 loc) · 2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
'use strict';
var VectorTileFeatureTypes = ['Unknown', 'Point', 'LineString', 'Polygon'];
function infix(operator) {
return function(_, key, value) {
if (key === '$type') {
return 't' + operator + VectorTileFeatureTypes.indexOf(value);
} else {
return 'p[' + JSON.stringify(key) + ']' + operator + JSON.stringify(value);
}
};
}
function strictInfix(operator) {
var nonstrictInfix = infix(operator);
return function(_, key, value) {
if (key === '$type') {
return nonstrictInfix(_, key, value);
} else {
return 'typeof(p[' + JSON.stringify(key) + ']) === typeof(' + JSON.stringify(value) + ') && ' +
nonstrictInfix(_, key, value);
}
};
}
var operators = {
'==': infix('==='),
'!=': infix('!=='),
'>': strictInfix('>'),
'<': strictInfix('<'),
'<=': strictInfix('<='),
'>=': strictInfix('>='),
'in': function(_, key) {
return '(function(){' + Array.prototype.slice.call(arguments, 2).map(function(value) {
return 'if (' + operators['=='](_, key, value) + ') return true;';
}).join('') + 'return false;})()';
},
'!in': function() {
return '!(' + operators.in.apply(this, arguments) + ')';
},
'any': function() {
return Array.prototype.slice.call(arguments, 1).map(function(filter) {
return '(' + compile(filter) + ')';
}).join('||') || 'false';
},
'all': function() {
return Array.prototype.slice.call(arguments, 1).map(function(filter) {
return '(' + compile(filter) + ')';
}).join('&&') || 'true';
},
'none': function() {
return '!(' + operators.any.apply(this, arguments) + ')';
}
};
function compile(filter) {
return operators[filter[0]].apply(filter, filter);
}
function truth() {
return true;
}
/**
* Given a filter expressed as nested arrays, return a new function
* that evaluates whether a given feature (with a .properties or .tags property)
* passes its test.
*
* @param {Array} filter mapbox gl filter
* @returns {Function} filter-evaluating function
*/
module.exports = function (filter) {
if (!filter) return truth;
var filterStr = 'var p = f.properties || f.tags || {}, t = f.type; return ' + compile(filter) + ';';
// jshint evil: true
return new Function('f', filterStr);
};