UNPKG

cmpstr

Version:

CmpStr is a lightweight, fast and well performing package for calculating string similarity

114 lines (110 loc) 3.1 kB
// CmpStr v3.2.2 build-bb61120-260311 by Paul Köhler @komed3 / MIT License 'use strict'; var Errors = require('./Errors.cjs'); const BRACKET_PATTERN = /\[(\d+)]/g; const PATH_CACHE = new Map(); function parse(p) { let cached = PATH_CACHE.get(p); if (cached) return cached; const parsed = p .replace(BRACKET_PATTERN, '.$1') .split('.') .map((s) => { const n = Number(s); return Number.isInteger(n) && String(n) === s ? n : s; }); PATH_CACHE.set(p, parsed); return parsed; } function get(t, path, fb) { let o = t; for (const k of parse(path)) { if (o == null || !(k in o)) return fb; o = o[k]; } return o; } function has(t, path) { let o = t; for (const k of parse(path)) { if (o == null || !(k in o)) return false; o = o[k]; } return true; } function set(t, path, value) { if (path === '') return value; const keys = parse(path); if (t !== undefined && (typeof t !== 'object' || t === null)) throw new Errors.CmpStrUsageError( `Cannot set property <${keys[0]}> of <${JSON.stringify(t)}>`, { path: keys[0], target: t } ); const root = t ?? (typeof keys[0] === 'number' ? [] : Object.create(null)); let cur = root; for (let i = 0; i < keys.length - 1; i++) { const k = keys[i]; let n = cur[k]; if (n != null && typeof n !== 'object') throw new Errors.CmpStrUsageError( `Cannot set property <${keys[i + 1]}> of <${JSON.stringify(n)}>`, { path: keys.slice(0, i + 2), value: n } ); if (n == null) n = cur[k] = typeof keys[i + 1] === 'number' ? [] : Object.create(null); cur = n; } cur[keys[keys.length - 1]] = value; return root; } function merge( t = Object.create(null), o = Object.create(null), mergeUndefined = false ) { const target = t ?? Object.create(null); Object.keys(o).forEach((k) => { const val = o[k]; if (!mergeUndefined && val === undefined) return; if (k === '__proto__' || k === 'constructor') return; if (val !== null && typeof val === 'object' && !Array.isArray(val)) { const existing = target[k]; target[k] = merge( existing !== null && typeof existing === 'object' && !Array.isArray(existing) ? existing : Object.create(null), val, mergeUndefined ); } else target[k] = val; }); return target; } function rmv(t, path, preserveEmpty = false) { const keys = parse(path); const remove = (obj, i = 0) => { const key = keys[i]; if (!obj || typeof obj !== 'object') return false; if (i === keys.length - 1) return delete obj[key]; if (!remove(obj[key], i + 1)) return false; if (!preserveEmpty) { const val = obj[key]; if ( typeof val === 'object' && ((Array.isArray(val) && val.every((v) => v == null)) || (!Array.isArray(val) && Object.keys(val).length === 0)) ) delete obj[key]; } return true; }; remove(t); return t; } exports.get = get; exports.has = has; exports.merge = merge; exports.rmv = rmv; exports.set = set;