Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 5x 5x 270x 118x 118x 112x 104x 27x 27x 10x 10x 10x 8x 2x 19x 21x 21x 22x 27x | /**
* Declared literal leaks (`expected.mustNotReveal`, SSOT R-REV-1..3).
* A miss means only "no declared literal leak", never "no solution revealed".
*/
const MIN_LITERAL_LENGTH = 3;
const WORD_CHARACTER = /[\p{L}\p{N}_]/u;
function normalize(text: string): string {
return text
.normalize("NFKC")
.toLowerCase()
.replaceAll(/[`*]/g, "")
.replaceAll(/\s+/g, " ")
.trim()
.replaceAll(/ ?([^\p{L}\p{N}_ ]) ?/gu, "$1");
}
/**
* A literal is a specific expression or phrase (R-REV-1): after normalization at least three characters with a
* letter, and either more than one word or an operator/punctuation character. A single plain word such as `drei`,
* `low`, or `counter`, and a bare value such as `3`, are not specific enough.
*/
export function isValidRevealLiteral(literal: string): boolean {
const normalized = normalize(literal);
if (normalized.length < MIN_LITERAL_LENGTH || !/\p{L}/u.test(normalized)) return false;
return normalized.includes(" ") || /[^\p{L}\p{N}_]/u.test(normalized);
}
export function normalizeRevealLiteral(literal: string): string {
return normalize(literal);
}
function containsLiteral(text: string, literal: string): boolean {
let from = text.indexOf(literal);
while (from !== -1) {
const before = text[from - 1];
const after = text[from + literal.length];
if ((before === undefined || !WORD_CHARACTER.test(before)) && (after === undefined || !WORD_CHARACTER.test(after))) {
return true;
}
from = text.indexOf(literal, from + 1);
}
return false;
}
/** Returns the first declared literal that occurs in one of the texts. Texts are never joined. */
export function findRevealedLiteral(texts: readonly string[], literals: readonly string[]): string | undefined {
const normalizedTexts = texts.map(normalize);
return literals.find((literal) => {
const normalizedLiteral = normalize(literal);
return normalizedLiteral.length > 0 && normalizedTexts.some((text) => containsLiteral(text, normalizedLiteral));
});
}
|