Files
SnowLuma/.pnpm-store/v11/files/20/1add5de7a98f962182fb88dc5f42409adb208832da4abae41e1164555574e5b88d23017d46e639e84192f7171d459a30cabd307805d1503f5de7a34e8df9e5
TanTan 2a69b23b47
Dev Build / cleanup (push) Canceled after 0s
Dev Build / typecheck (push) Canceled after 0s
Dev Build / build (linux-arm64, ubuntu-24.04-arm, linux-arm64) (push) Canceled after 0s
Dev Build / build (linux-x64, ubuntu-latest, linux-x64) (push) Canceled after 0s
Dev Build / build (win-x64, windows-latest, win32-x64) (push) Canceled after 0s
Dev Build / dispatch-dev-docker (push) Canceled after 0s
docs: 仓库链接指向本镜像仓库
2026-11-13 09:27:07 +08:00

164 lines
5.6 KiB
Plaintext

import { buildRankedDictionary } from './utils/helper.mjs';
import l33tTable from './data/l33tTable.mjs';
import translationKeys from './data/translationKeys.mjs';
import TrieNode from './matcher/dictionary/variants/matching/unmunger/TrieNode.mjs';
import l33tTableToTrieNode from './matcher/dictionary/variants/matching/unmunger/l33tTableToTrieNode.mjs';
import { timeEstimationValuesDefaults, checkTimeEstimationValues } from './TimeEstimates.mjs';
class Options {
constructor(options = {}, customMatchers = {}) {
this.matchers = {};
this.l33tTable = l33tTable;
this.trieNodeRoot = l33tTableToTrieNode(l33tTable, new TrieNode());
this.dictionary = {
userInputs: []
};
this.rankedDictionaries = {};
this.rankedDictionariesMaxWordSize = {};
this.translations = translationKeys;
this.graphs = {};
this.useLevenshteinDistance = false;
this.levenshteinThreshold = 2;
this.l33tMaxSubstitutions = 100;
this.maxLength = 256;
this.wordSequenceNames = ['cardinalNumbers', 'ordinalNumbers', 'daysOfWeek', 'months', 'seasons', 'timePeriods', 'rainbowColors', 'directions', 'intermediateDirections', 'sizeProgression', 'militaryAlphabet', 'planets', 'zodiacSigns', 'chineseZodiac'];
this.timeEstimationValues = {
scoring: {
...timeEstimationValuesDefaults.scoring
},
attackTime: {
...timeEstimationValuesDefaults.attackTime
}
};
this.setOptions(options);
Object.entries(customMatchers).forEach(([name, matcher]) => {
this.addMatcher(name, matcher);
});
}
isWordSequence(key) {
return this.wordSequenceNames.some(name => key === name || key.startsWith(`${name}-`));
}
// eslint-disable-next-line max-statements,complexity
setOptions(options = {}) {
if (options.l33tTable) {
this.l33tTable = options.l33tTable;
this.trieNodeRoot = l33tTableToTrieNode(options.l33tTable, new TrieNode());
}
if (options.dictionary) {
this.dictionary = options.dictionary;
this.setRankedDictionaries();
}
if (options.translations) {
this.setTranslations(options.translations);
}
if (options.graphs) {
this.graphs = options.graphs;
}
if (options.useLevenshteinDistance !== undefined) {
this.useLevenshteinDistance = options.useLevenshteinDistance;
}
if (options.levenshteinThreshold !== undefined) {
this.levenshteinThreshold = options.levenshteinThreshold;
}
if (options.l33tMaxSubstitutions !== undefined) {
this.l33tMaxSubstitutions = options.l33tMaxSubstitutions;
}
if (options.maxLength !== undefined) {
this.maxLength = options.maxLength;
}
if (options.timeEstimationValues !== undefined) {
checkTimeEstimationValues(options.timeEstimationValues);
this.timeEstimationValues = {
scoring: {
...options.timeEstimationValues.scoring
},
attackTime: {
...options.timeEstimationValues.attackTime
}
};
}
}
setTranslations(translations) {
if (this.checkCustomTranslations(translations)) {
this.translations = translations;
} else {
throw new Error('Invalid translations object fallback to keys');
}
}
checkCustomTranslations(translations) {
let valid = true;
Object.keys(translationKeys).forEach(type => {
if (type in translations) {
const translationType = type;
Object.keys(translationKeys[translationType]).forEach(key => {
if (!(key in translations[translationType])) {
valid = false;
}
const translation = translations[translationType][key];
if (typeof translation !== 'string' && typeof translation !== 'function') {
valid = false;
}
});
} else {
valid = false;
}
});
return valid;
}
setRankedDictionaries() {
const rankedDictionaries = {};
const rankedDictionariesMaxWorkSize = {};
Object.keys(this.dictionary).forEach(name => {
rankedDictionaries[name] = buildRankedDictionary(this.dictionary[name]);
rankedDictionariesMaxWorkSize[name] = this.getRankedDictionariesMaxWordSize(this.dictionary[name]);
});
this.rankedDictionaries = rankedDictionaries;
this.rankedDictionariesMaxWordSize = rankedDictionariesMaxWorkSize;
}
getRankedDictionariesMaxWordSize(list) {
const data = list.map(el => {
if (typeof el !== 'string') {
return el.toString().length;
}
return el.length;
});
// do not use Math.max(...data) because it can result in max stack size error because every entry will be used as an argument
if (data.length === 0) {
return 0;
}
return data.reduce((a, b) => Math.max(a, b), -Infinity);
}
buildSanitizedRankedDictionary(list) {
const sanitizedInputs = [];
list.forEach(input => {
const inputType = typeof input;
if (inputType === 'string' || inputType === 'number' || inputType === 'boolean') {
sanitizedInputs.push(input.toString().toLowerCase());
}
});
return buildRankedDictionary(sanitizedInputs);
}
getUserInputsOptions(dictionary) {
let rankedDictionary = {};
let rankedDictionaryMaxWordSize = 0;
if (dictionary) {
rankedDictionary = this.buildSanitizedRankedDictionary(dictionary);
rankedDictionaryMaxWordSize = this.getRankedDictionariesMaxWordSize(dictionary);
}
return {
rankedDictionary,
rankedDictionaryMaxWordSize
};
}
addMatcher(name, matcher) {
if (this.matchers[name]) {
console.info(`Matcher ${name} already exists`);
} else {
this.matchers[name] = matcher;
}
}
}
export { Options as default };
//# sourceMappingURL=Options.mjs.map