Files
SnowLuma/.pnpm-store/v11/files/2f/b5ad5eb8c4957e3705801155e1b7b1d8fa375527e94e369879f3bd0c6964b936a8caa1d86799de65fb4060f82ccd346e374b4f17ce9144945d63da79084895
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

62 lines
2.4 KiB
Plaintext

'use strict';
var _const = require('../../data/const.cjs');
var types = require('../../types.cjs');
const separatorRegex = new RegExp(`[${_const.SEPERATOR_CHARS.join('')}]`);
/*
*-------------------------------------------------------------------------------
* separators (any semi-repeated special character) -----------------------------
*-------------------------------------------------------------------------------
*/
class MatchSeparator extends types.MatcherBaseClass {
static getMostUsedSeparatorChar(password) {
const mostUsedSeperators = [...password.split('').filter(c => separatorRegex.test(c)).reduce((memo, c) => {
const m = memo.get(c);
if (m) {
memo.set(c, parseInt(m, 10) + 1);
} else {
memo.set(c, 1);
}
return memo;
}, new Map()).entries()].sort(([_a, a], [_b, b]) => b - a);
if (!mostUsedSeperators.length) return undefined;
const match = mostUsedSeperators[0];
// If the special character is only used once, don't treat it like a separator
if (match[1] < 2) return undefined;
return match[0];
}
static getSeparatorRegex(separator) {
return new RegExp(`([^${separator}\n])(${separator})(?!${separator})`, 'g');
// negative lookbehind can be added again in a few years when it is more supported by the browsers (currently 2023)
// https://github.com/zxcvbn-ts/zxcvbn/issues/202
// return new RegExp(`(?<!${separator})(${separator})(?!${separator})`, 'g')
}
match({
password
}) {
const result = [];
if (password.length === 0) return result;
const mostUsedSpecial = MatchSeparator.getMostUsedSeparatorChar(password);
if (mostUsedSpecial === undefined) return result;
const isSeparator = MatchSeparator.getSeparatorRegex(mostUsedSpecial);
for (const match of password.matchAll(isSeparator)) {
if (match.index === undefined) continue;
// add one to the index because we changed the regex from negative lookbehind to something simple.
// this simple approach uses the first character before the separater too but we only need the index of the separater
// https://github.com/zxcvbn-ts/zxcvbn/issues/202
const i = match.index + 1;
result.push({
pattern: 'separator',
token: mostUsedSpecial,
i,
j: i
});
}
return result;
}
}
module.exports = MatchSeparator;
//# sourceMappingURL=matching.cjs.map