1 | /* jshint node: true */
|
---|
2 | 'use strict';
|
---|
3 |
|
---|
4 | var REGEXP_PARTS = /(\*|\?)/g;
|
---|
5 |
|
---|
6 | /**
|
---|
7 | # wildcard
|
---|
8 |
|
---|
9 | Very simple wildcard matching, which is designed to provide the same
|
---|
10 | functionality that is found in the
|
---|
11 | [eve](https://github.com/adobe-webplatform/eve) eventing library.
|
---|
12 |
|
---|
13 | ## Usage
|
---|
14 |
|
---|
15 | It works with strings:
|
---|
16 |
|
---|
17 | <<< examples/strings.js
|
---|
18 |
|
---|
19 | Arrays:
|
---|
20 |
|
---|
21 | <<< examples/arrays.js
|
---|
22 |
|
---|
23 | Objects (matching against keys):
|
---|
24 |
|
---|
25 | <<< examples/objects.js
|
---|
26 |
|
---|
27 | ## Alternative Implementations
|
---|
28 |
|
---|
29 | - <https://github.com/isaacs/node-glob>
|
---|
30 |
|
---|
31 | Great for full file-based wildcard matching.
|
---|
32 |
|
---|
33 | - <https://github.com/sindresorhus/matcher>
|
---|
34 |
|
---|
35 | A well cared for and loved JS wildcard matcher.
|
---|
36 | **/
|
---|
37 |
|
---|
38 | function WildcardMatcher(text, separator) {
|
---|
39 | this.text = text = text || '';
|
---|
40 | this.hasWild = text.indexOf('*') >= 0;
|
---|
41 | this.separator = separator;
|
---|
42 | this.parts = text.split(separator).map(this.classifyPart.bind(this));
|
---|
43 | }
|
---|
44 |
|
---|
45 | WildcardMatcher.prototype.match = function(input) {
|
---|
46 | var matches = true;
|
---|
47 | var parts = this.parts;
|
---|
48 | var ii;
|
---|
49 | var partsCount = parts.length;
|
---|
50 | var testParts;
|
---|
51 |
|
---|
52 | if (typeof input == 'string' || input instanceof String) {
|
---|
53 | if (!this.hasWild && this.text != input) {
|
---|
54 | matches = false;
|
---|
55 | } else {
|
---|
56 | testParts = (input || '').split(this.separator);
|
---|
57 | for (ii = 0; matches && ii < partsCount; ii++) {
|
---|
58 | if (parts[ii] === '*') {
|
---|
59 | continue;
|
---|
60 | } else if (ii < testParts.length) {
|
---|
61 | matches = parts[ii] instanceof RegExp
|
---|
62 | ? parts[ii].test(testParts[ii])
|
---|
63 | : parts[ii] === testParts[ii];
|
---|
64 | } else {
|
---|
65 | matches = false;
|
---|
66 | }
|
---|
67 | }
|
---|
68 |
|
---|
69 | // If matches, then return the component parts
|
---|
70 | matches = matches && testParts;
|
---|
71 | }
|
---|
72 | }
|
---|
73 | else if (typeof input.splice == 'function') {
|
---|
74 | matches = [];
|
---|
75 |
|
---|
76 | for (ii = input.length; ii--; ) {
|
---|
77 | if (this.match(input[ii])) {
|
---|
78 | matches[matches.length] = input[ii];
|
---|
79 | }
|
---|
80 | }
|
---|
81 | }
|
---|
82 | else if (typeof input == 'object') {
|
---|
83 | matches = {};
|
---|
84 |
|
---|
85 | for (var key in input) {
|
---|
86 | if (this.match(key)) {
|
---|
87 | matches[key] = input[key];
|
---|
88 | }
|
---|
89 | }
|
---|
90 | }
|
---|
91 |
|
---|
92 | return matches;
|
---|
93 | };
|
---|
94 |
|
---|
95 | WildcardMatcher.prototype.classifyPart = function(part) {
|
---|
96 | // in the event that we have been provided a part that is not just a wildcard
|
---|
97 | // then turn this into a regular expression for matching purposes
|
---|
98 | if (part === '*') {
|
---|
99 | return part;
|
---|
100 | } else if (part.indexOf('*') >= 0 || part.indexOf('?') >= 0) {
|
---|
101 | return new RegExp(part.replace(REGEXP_PARTS, '\.$1'));
|
---|
102 | }
|
---|
103 |
|
---|
104 | return part;
|
---|
105 | };
|
---|
106 |
|
---|
107 | module.exports = function(text, test, separator) {
|
---|
108 | var matcher = new WildcardMatcher(text, separator || /[\/\.]/);
|
---|
109 | if (typeof test != 'undefined') {
|
---|
110 | return matcher.match(test);
|
---|
111 | }
|
---|
112 |
|
---|
113 | return matcher;
|
---|
114 | };
|
---|