cmpstr
Version:
CmpStr is a lightweight, fast and well performing package for calculating string similarity
188 lines (186 loc) • 7 kB
JavaScript
// CmpStr v3.0.1 dev-052fa0c-250614 by Paul Köhler @komed3 / MIT License
/**
* Filter Utility
* src/utils/Filter.ts
*
* This module provides a Filter class that allows for the management and application of
* filters to strings based on hooks. Filters can be added, removed, paused, resumed, and
* applied to input strings. Each filter has an id, a function, a priority, and options
* for activation and overrideability.
*
* @module Utils/Filter
* @author Paul Köhler (komed3)
* @license MIT
*/
/**
* The Filter class provides a way to manage and apply filters to strings based on hooks.
*/
class Filter {
/**
* A static map to hold all filters.
* The key is the hook name, and the value is an array of FilterEntry objects.
*/
static filters = new Map();
/**
* Finds a filter by its hook and id.
*
* @param {string} hook - The name of the hook
* @param {string} id - The id of the filter
* @returns {FilterEntry|undefined} - The FilterEntry if found, otherwise undefined
*/
static find(hook, id) {
return Filter.filters.get(hook)?.find((f) => f.id === id);
}
/**
* Adds a filter to the specified hook.
*
* @param {string} hook - The name of the hook
* @param {string} id - The id of the filter
* @param {FilterFn} fn - The filter function
* @param {FilterOptions} [opt] - Additional options for the filter
* @returns {boolean} - Returns true if the filter was added, false if it was not added due to override restrictions
*/
static add(hook, id, fn, opt = {}) {
const { priority = 10, active = true, overrideable = true } = opt;
// Check if the filter already exists
const filter = Filter.filters.get(hook) ?? [];
const index = filter.findIndex((f) => f.id === id);
// If the filter already exists and is not overrideable, return false
if (index >= 0) {
const f = filter[index];
if (!f.overrideable) return false;
filter.splice(index, 1);
}
// Add the new filter entry
filter.push({ id, fn, priority, active, overrideable });
// Sort the filters by priority
filter.sort((a, b) => a.priority - b.priority);
// Update the filters map
Filter.filters.set(hook, filter);
return true;
}
/**
* Removes a filter by its hook and id.
*
* @param {string} hook - The name of the hook
* @param {string} id - The id of the filter
* @returns {boolean} - Returns true if the filter was removed, false if it was not found
*/
static remove(hook, id) {
// Get the filter array for the specified hook
const filter = Filter.filters.get(hook);
// If the filter array does not exist, return false
if (!filter) return false;
// Find the index of the filter with the specified id
const index = filter.findIndex((f) => f.id === id);
// If the filter is found, remove it and return true
if (index >= 0) {
filter.splice(index, 1);
return true;
}
return false;
}
/**
* Pauses a filter by its hook and id.
*
* @param {string} hook - The name of the hook
* @param {string} id - The id of the filter
* @returns {boolean} - Returns true if the filter was paused, false if it was not found
*/
static pause(hook, id) {
// Find the filter entry by hook and id
const f = Filter.find(hook, id);
if (!f) return false;
// Set the active property to false to pause the filter
f.active = false;
return true;
}
/**
* Resumes a filter by its hook and id.
*
* @param {string} hook - The name of the hook
* @param {string} id - The id of the filter
* @returns {boolean} - Returns true if the filter was resumed, false if it was not found
*/
static resume(hook, id) {
// Find the filter entry by hook and id
const f = Filter.find(hook, id);
if (!f) return false;
// Set the active property to true to resume the filter
f.active = true;
return true;
}
/**
* Lists all filters for a given hook.
*
* @param {string} hook - The name of the hook
* @param {boolean} active - If true, only list active filters
* @returns {string[]} - An array of filter ids
*/
static list(hook, active = false) {
// Get the filter array for the specified hook
const filter = Filter.filters.get(hook) ?? [];
const list = [];
// If active is true, filter the entries based on their active status
for (const f of filter) if (!active || f.active) list.push(f.id);
return list;
}
/**
* Applies all active filters for a given hook to the input string(s).
*
* @param {string} hook - The name of the hook
* @param {string|string[]} input - The input string(s) to be filtered
* @returns {string|string[]} - The filtered string(s)
*/
static apply(hook, input) {
// Get the filter array for the specified hook
const filter = Filter.filters.get(hook);
// If no filters are found for the hook or if no filters are active, return the input unchanged
if (!filter || filter.every((f) => !f.active)) return input;
// Apply each active filter function to the given string
const applyOne = (s) => {
for (const f of filter) if (f.active) s = f.fn(s);
return s;
};
// If the input is an array, apply the filter to each element, otherwise just once
return Array.isArray(input) ? input.map(applyOne) : applyOne(input);
}
/**
* Applies all active filters for a given hook to the input string(s) asynchronously.
* Each filter function may return a Promise or a plain string; all are awaited in order.
*
* @param {string} hook - The name of the hook
* @param {string|string[]} input - The input string(s) to be filtered
* @returns {Promise<string|string[]>} - The filtered string(s)
*/
static async applyAsync(hook, input) {
// Get the filter array for the specified hook
const filter = Filter.filters.get(hook);
// If no filters are found for the hook or if no filters are active, return the input unchanged
if (!filter || filter.every((f) => !f.active)) return input;
// Apply each active filter function to the given string
// Support both sync and async filter functions
const applyOne = async (s) => {
for (const f of filter) if (f.active) s = await Promise.resolve(f.fn(s));
return s;
};
// If the input is an array, apply the filter to each element, otherwise just once
// Use Promise.all to handle multiple promises if input is an array
return Array.isArray(input)
? Promise.all(input.map(applyOne))
: applyOne(input);
}
/**
* Clears all filters or filters for a specific hook.
*
* @param {string} [hook] - Optional name of the hook to clear filters for
*/
static clear(hook) {
// If a specific hook is provided, delete its filters
if (hook) Filter.filters.delete(hook);
// If no hook is provided, clear all filters
else Filter.filters.clear();
}
}
export { Filter };
//# sourceMappingURL=Filter.js.map