json-q
Version:
Retrieves values from JSON objects (and JavaScript objects) by css-selector-like query (includes attribute filters and array flattening).
72 lines (62 loc) • 2.14 kB
JavaScript
const { operator } = require('./filter_operators');
//returns {left:<left_side>, right:<right_side>, delimiter:<delimiter>}
//for instance, "a\\=b=c" becomes {left:'a=b', right:'c', delimiter:'='}
const parse_filter = (str, opt) => {
if (typeof str === 'undefined') str='';
if (typeof str !== 'string') str=str+'';
let ret = {left:''};
for (let i=0; i < str.length; i++) {
let op = _is_operator(str, i, opt);
if (op) {
ret.delimiter = op;
ret.right = str.substring(i + 1);
ret.left = str.substring(0, i-op.length+1);
break;
}
}
if (!ret.right) ret.left = str;
ret.left = _replace_escaped_operators(ret.left, opt);
if (ret.right) ret.right = _replace_escaped_operators(ret.right, opt);
return ret;
}
const _replace_escaped_operators = (str, opt) => {
let ret = str.trim();
const operator_keys = _get_operator_keys(opt);
operator_keys.forEach(_itm => {
ret = ret.replace("\\"+_itm, _itm);
})
return ret;
}
const _is_operator = (str, str_index, opt) => {
let ret;
const operator_keys = _get_operator_keys(opt);
for (let i=0; i<operator_keys.length && !ret; i++){
let op = _is_operator_word(str, str_index, operator_keys[i]);
if (op) ret = operator_keys[i];
}
return ret;
}
const _get_operator_keys = (opt) => {
const localOperator = Object.assign({}, operator, (opt || {}).operator);
const operator_keys = Object.keys(localOperator);
operator_keys.sort((a,b)=>{return b.length - a.length}); // if "=" comes before "*=" then "=" will win while it is really "*=", not "="
return operator_keys;
}
const _is_operator_word = (str, str_index, word) => {
let ret = false;
if (str_index>=word.length-1) {
let word_index = 0;
while (word_index<word.length-1 && str[str_index-word_index] == word[word.length-1-word_index]) word_index++;
if (word_index == word.length-1 && str[str_index-word_index] == word[word.length-1-word_index]) {
if (str_index==word.length-1) {
ret = true;
} else {
if (str[str_index-1] != '\\' ) {
ret = true;
}
}
}
}
return ret;
}
module.exports = { parse_filter }