186 lines
4.1 KiB
JavaScript
186 lines
4.1 KiB
JavaScript
/*
|
|
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
* This file is part of utilities which is released under MIT.
|
|
* See file 'LICENSE' for full license details.
|
|
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
/**
|
|
* truncates a floating point number
|
|
*
|
|
* @param {number} num number to truncate
|
|
* @param {number} len length to truncate to
|
|
* @returns {number} truncated number
|
|
*/
|
|
function truncate_decimal (num, len) {
|
|
return Math.round (num * (10 ** len)) / (10 ** len);
|
|
}
|
|
|
|
/**
|
|
* parse json and catch invalid strings
|
|
*
|
|
* @param {string} text input
|
|
* @returns {any} parsed
|
|
*/
|
|
function try_parse_json (text) {
|
|
try {
|
|
return JSON.parse (text);
|
|
}
|
|
catch (e) {
|
|
// noop
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
/**
|
|
* copy an object to prevent modification to the original
|
|
*
|
|
* @param {object} obj object to copy
|
|
* @returns {object} copy
|
|
*/
|
|
function copy_object (obj) {
|
|
return JSON.parse (JSON.stringify (obj));
|
|
}
|
|
|
|
/**
|
|
* run a regular expression and callback for every result
|
|
*
|
|
* @param {any} regex regular expression
|
|
* @param {any} data data to run on
|
|
* @param {any} func function to execute
|
|
*/
|
|
function run_regex (regex, data, func) {
|
|
if (!regex.global) {
|
|
const result = regex.exec (data);
|
|
if (result)
|
|
func (result);
|
|
return;
|
|
}
|
|
let res = regex.exec (data);
|
|
while (res) {
|
|
func (res);
|
|
res = regex.exec (data);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* check if an object is either undefined, null or NaN
|
|
*
|
|
* @param {any} obj object to check
|
|
* @returns {boolean} true if nil
|
|
*/
|
|
function is_nil (obj) {
|
|
return typeof obj === 'undefined'
|
|
|| obj === null
|
|
|| (typeof obj === 'number' && isNaN (obj));
|
|
}
|
|
|
|
function get_element_field (element, carried_data, field) {
|
|
if (typeof carried_data[field] !== 'undefined')
|
|
return carried_data[field];
|
|
return element[field];
|
|
}
|
|
|
|
function check_filter (filter, e, carried_data) {
|
|
const search_str = Array.isArray (filter.field)
|
|
? filter.field.map ((f) => get_element_field (e, carried_data, f))
|
|
.filter ((v) => typeof v !== 'undefined')
|
|
.join (' ')
|
|
: get_element_field (e, carried_data, filter.field);
|
|
|
|
return filter.filter.test (search_str);
|
|
}
|
|
|
|
function check_filters (filters, e, carried_data, or = false) {
|
|
for (const filter of filters) {
|
|
let res = false;
|
|
if (Array.isArray (filter.or))
|
|
res = check_filters (filter.or, e, carried_data, true);
|
|
else
|
|
res = check_filter (filter, e, carried_data);
|
|
|
|
if (or && res)
|
|
return true;
|
|
if (!res && !or)
|
|
return false;
|
|
}
|
|
return !or;
|
|
}
|
|
|
|
/**
|
|
* @typedef Filter
|
|
* @type {object}
|
|
* @property {string|string[]} field - fields to apply filter on
|
|
* @property {RegExp} filter - filter
|
|
*/
|
|
|
|
/**
|
|
* @typedef FilterOrGroup
|
|
* @type {object}
|
|
* @property {(Filter|FilterOrGroup)[]} or - create an OR group of filters
|
|
*/
|
|
|
|
/**
|
|
* filter nested objects
|
|
*
|
|
* @param {Array<object>} input object to filter
|
|
* @param {(Filter|FilterOrGroup)[]} filters filters
|
|
* @param {string[]} carry carry data to children to match
|
|
* @param {object} carried_data internal: carried data
|
|
* @returns {Array<object>} filtered data
|
|
*/
|
|
function recursive_filter (
|
|
input,
|
|
filters,
|
|
children_key = 'children',
|
|
carry = [],
|
|
carried_data = {}
|
|
) {
|
|
const data = [ ...input ];
|
|
const filtered = [];
|
|
|
|
for (const c of carry) {
|
|
if (typeof carried_data[c] !== 'string')
|
|
carried_data[c] = '';
|
|
}
|
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
const e = { ...data[i] };
|
|
data[i] = e;
|
|
const sub_carry = { ...carried_data };
|
|
for (const c of carry) {
|
|
if (typeof e[c] !== 'undefined')
|
|
sub_carry[c] += `${sub_carry[c].length > 0 ? ' ' : ''}${e[c]}`;
|
|
}
|
|
if (check_filters (filters, e, sub_carry)) {
|
|
filtered.push (e);
|
|
}
|
|
else {
|
|
if (typeof e[children_key] === 'undefined')
|
|
continue;
|
|
e[children_key] = recursive_filter (
|
|
e[children_key],
|
|
filters,
|
|
children_key,
|
|
carry,
|
|
sub_carry
|
|
);
|
|
if (e[children_key].length > 0)
|
|
filtered.push (e);
|
|
}
|
|
}
|
|
return filtered;
|
|
}
|
|
|
|
module.exports = {
|
|
truncate_decimal,
|
|
try_parse_json,
|
|
copy_object,
|
|
run_regex,
|
|
is_nil,
|
|
recursive_filter
|
|
};
|