first commit
This commit is contained in:
307
app_vue/node_modules/@hapi/hoek/lib/contain.js
generated
vendored
Normal file
307
app_vue/node_modules/@hapi/hoek/lib/contain.js
generated
vendored
Normal file
@ -0,0 +1,307 @@
|
||||
'use strict';
|
||||
|
||||
const Assert = require('./assert');
|
||||
const DeepEqual = require('./deepEqual');
|
||||
const EscapeRegex = require('./escapeRegex');
|
||||
const Utils = require('./utils');
|
||||
|
||||
|
||||
const internals = {};
|
||||
|
||||
|
||||
module.exports = function (ref, values, options = {}) { // options: { deep, once, only, part, symbols }
|
||||
|
||||
/*
|
||||
string -> string(s)
|
||||
array -> item(s)
|
||||
object -> key(s)
|
||||
object -> object (key:value)
|
||||
*/
|
||||
|
||||
if (typeof values !== 'object') {
|
||||
values = [values];
|
||||
}
|
||||
|
||||
Assert(!Array.isArray(values) || values.length, 'Values array cannot be empty');
|
||||
|
||||
// String
|
||||
|
||||
if (typeof ref === 'string') {
|
||||
return internals.string(ref, values, options);
|
||||
}
|
||||
|
||||
// Array
|
||||
|
||||
if (Array.isArray(ref)) {
|
||||
return internals.array(ref, values, options);
|
||||
}
|
||||
|
||||
// Object
|
||||
|
||||
Assert(typeof ref === 'object', 'Reference must be string or an object');
|
||||
return internals.object(ref, values, options);
|
||||
};
|
||||
|
||||
|
||||
internals.array = function (ref, values, options) {
|
||||
|
||||
if (!Array.isArray(values)) {
|
||||
values = [values];
|
||||
}
|
||||
|
||||
if (!ref.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (options.only &&
|
||||
options.once &&
|
||||
ref.length !== values.length) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
let compare;
|
||||
|
||||
// Map values
|
||||
|
||||
const map = new Map();
|
||||
for (const value of values) {
|
||||
if (!options.deep ||
|
||||
!value ||
|
||||
typeof value !== 'object') {
|
||||
|
||||
const existing = map.get(value);
|
||||
if (existing) {
|
||||
++existing.allowed;
|
||||
}
|
||||
else {
|
||||
map.set(value, { allowed: 1, hits: 0 });
|
||||
}
|
||||
}
|
||||
else {
|
||||
compare = compare || internals.compare(options);
|
||||
|
||||
let found = false;
|
||||
for (const [key, existing] of map.entries()) {
|
||||
if (compare(key, value)) {
|
||||
++existing.allowed;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
map.set(value, { allowed: 1, hits: 0 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup values
|
||||
|
||||
let hits = 0;
|
||||
for (const item of ref) {
|
||||
let match;
|
||||
if (!options.deep ||
|
||||
!item ||
|
||||
typeof item !== 'object') {
|
||||
|
||||
match = map.get(item);
|
||||
}
|
||||
else {
|
||||
compare = compare || internals.compare(options);
|
||||
|
||||
for (const [key, existing] of map.entries()) {
|
||||
if (compare(key, item)) {
|
||||
match = existing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
++match.hits;
|
||||
++hits;
|
||||
|
||||
if (options.once &&
|
||||
match.hits > match.allowed) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate results
|
||||
|
||||
if (options.only &&
|
||||
hits !== ref.length) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const match of map.values()) {
|
||||
if (match.hits === match.allowed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (match.hits < match.allowed &&
|
||||
!options.part) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !!hits;
|
||||
};
|
||||
|
||||
|
||||
internals.object = function (ref, values, options) {
|
||||
|
||||
Assert(options.once === undefined, 'Cannot use option once with object');
|
||||
|
||||
const keys = Utils.keys(ref, options);
|
||||
if (!keys.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Keys list
|
||||
|
||||
if (Array.isArray(values)) {
|
||||
return internals.array(keys, values, options);
|
||||
}
|
||||
|
||||
// Key value pairs
|
||||
|
||||
const symbols = Object.getOwnPropertySymbols(values).filter((sym) => values.propertyIsEnumerable(sym));
|
||||
const targets = [...Object.keys(values), ...symbols];
|
||||
|
||||
const compare = internals.compare(options);
|
||||
const set = new Set(targets);
|
||||
|
||||
for (const key of keys) {
|
||||
if (!set.has(key)) {
|
||||
if (options.only) {
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!compare(values[key], ref[key])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set.delete(key);
|
||||
}
|
||||
|
||||
if (set.size) {
|
||||
return options.part ? set.size < targets.length : false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
internals.string = function (ref, values, options) {
|
||||
|
||||
// Empty string
|
||||
|
||||
if (ref === '') {
|
||||
return values.length === 1 && values[0] === '' || // '' contains ''
|
||||
!options.once && !values.some((v) => v !== ''); // '' contains multiple '' if !once
|
||||
}
|
||||
|
||||
// Map values
|
||||
|
||||
const map = new Map();
|
||||
const patterns = [];
|
||||
|
||||
for (const value of values) {
|
||||
Assert(typeof value === 'string', 'Cannot compare string reference to non-string value');
|
||||
|
||||
if (value) {
|
||||
const existing = map.get(value);
|
||||
if (existing) {
|
||||
++existing.allowed;
|
||||
}
|
||||
else {
|
||||
map.set(value, { allowed: 1, hits: 0 });
|
||||
patterns.push(EscapeRegex(value));
|
||||
}
|
||||
}
|
||||
else if (options.once ||
|
||||
options.only) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!patterns.length) { // Non-empty string contains unlimited empty string
|
||||
return true;
|
||||
}
|
||||
|
||||
// Match patterns
|
||||
|
||||
const regex = new RegExp(`(${patterns.join('|')})`, 'g');
|
||||
const leftovers = ref.replace(regex, ($0, $1) => {
|
||||
|
||||
++map.get($1).hits;
|
||||
return ''; // Remove from string
|
||||
});
|
||||
|
||||
// Validate results
|
||||
|
||||
if (options.only &&
|
||||
leftovers) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
let any = false;
|
||||
for (const match of map.values()) {
|
||||
if (match.hits) {
|
||||
any = true;
|
||||
}
|
||||
|
||||
if (match.hits === match.allowed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (match.hits < match.allowed &&
|
||||
!options.part) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// match.hits > match.allowed
|
||||
|
||||
if (options.once) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !!any;
|
||||
};
|
||||
|
||||
|
||||
internals.compare = function (options) {
|
||||
|
||||
if (!options.deep) {
|
||||
return internals.shallow;
|
||||
}
|
||||
|
||||
const hasOnly = options.only !== undefined;
|
||||
const hasPart = options.part !== undefined;
|
||||
|
||||
const flags = {
|
||||
prototype: hasOnly ? options.only : hasPart ? !options.part : false,
|
||||
part: hasOnly ? !options.only : hasPart ? options.part : false
|
||||
};
|
||||
|
||||
return (a, b) => DeepEqual(a, b, flags);
|
||||
};
|
||||
|
||||
|
||||
internals.shallow = function (a, b) {
|
||||
|
||||
return a === b;
|
||||
};
|
Reference in New Issue
Block a user