-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.vue
81 lines (70 loc) · 2.64 KB
/
search.vue
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
79
80
81
<script lang="js" frontend>
import stringSplitBy from 'string-split-by';
/**
* Various utility functions for handling string queries
*/
app.service('$search', function() {
var $search = {};
/**
* Attempt to loosely parse search tags from an input string
* NOTE: This does not perform any validation on tags - only parses them into a key=value object
* @param {string} query The input string to process
* @returns {Object} An object of key=value parses with the meta `$fuzzy` key for left over string values
*
* @example Parse a string query
* vm.$search.parseTags('is:draft between:jan john smith') //= {is: 'draft', between: 'jan-dec', $fuzzy: 'john smith'}
*/
$search.parseTags = function(query = '') {
var fuzzyQuery = []; // Extracted fuzzy query parts, extracted from all queryHash parts that don't look like tags
var terms = stringSplitBy(query, /\s+/, {
ignore: ['"', "'", '()'], // Preserve compound terms with speachmarks + brackets
escape: true, // Allow escaping of terms
});
terms.forEach(v => {
if (!/:/.test(v)) fuzzyQuery.push(v); // Not a tag - add to fuzzy query part
});
return _.chain(terms).filter(v => (/:/.test(v)))
.map(v => v.split(/:/, 2))
.fromPairs()
.set('$fuzzy', fuzzyQuery.join(' '))
.value();
};
/**
* Take an object and return it as a sequence of tags
* This is the opposite of $search.parseTags()
* @param {Object} obj The query object to stringify, this can also contain the `$fuzzy` meta key
* @returns {string} The stringified object
*/
$search.stringify = function(obj) {
return _.chain(obj)
.map((v, k) => {
// Only wrap in quotes if not already wrapped...
const hasWhitespaceWithoutQuotes = /^[^\"]+.*\s.*[^\"]$/;
// Fuzzy search with or without spaces
if (k == '$fuzzy' && hasWhitespaceWithoutQuotes.test(v)) {
return `"${v}"`;
} else if (k == '$fuzzy') {
return v;
// Individual values within a tag may also contain spaces
} else {
return `${k}:${v.split(',')
.map(s => (hasWhitespaceWithoutQuotes.test(s)) ? `"${s}"`:s)}`;
}
})
.join(' ')
.value();
};
/**
* Take an existing search query, merge options and return the result
* This is really just a combination of various other functions together as a convenience function
* @param {string} query The existing query string to merge with
* @param {Object} obj The new object to merge with the input query using _.merge()
* @returns {string} The modified query with the object merged
*/
$search.merge = function(query = '', obj) {
var existingQuery = $search.parseTags(query);
return $search.stringify(_.merge(existingQuery, obj));
};
return $search;
});
</script>