d11 theme
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

188 lines
8.3 KiB

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports._testMethods = exports.hasWordCheck = exports.isWordValid = exports.calcTextInclusionRanges = exports.validateText = exports.minWordSplitLen = exports.defaultMinWordLength = exports.defaultMaxDuplicateProblems = exports.defaultMaxNumberOfProblems = void 0;
const Text = __importStar(require("./util/text"));
const TextRange = __importStar(require("./util/TextRange"));
const RxPat = __importStar(require("./Settings/RegExpPatterns"));
exports.defaultMaxNumberOfProblems = 200;
exports.defaultMaxDuplicateProblems = 5;
exports.defaultMinWordLength = 4;
exports.minWordSplitLen = 3;
function validateText(text, dict, options) {
const { maxNumberOfProblems = exports.defaultMaxNumberOfProblems, maxDuplicateProblems = exports.defaultMaxDuplicateProblems, } = options;
const mapOfProblems = new Map();
const includeRanges = calcTextInclusionRanges(text, options);
const validator = lineValidator(dict, options);
return Text.extractLinesOfText(text)
.concatMap(mapTextOffsetsAgainstRanges(includeRanges))
.concatMap(validator)
.filter((wo) => {
const word = wo.text;
// Keep track of the number of times we have seen the same problem
mapOfProblems.set(word, (mapOfProblems.get(word) || 0) + 1);
// Filter out if there is too many
return mapOfProblems.get(word) < maxDuplicateProblems;
})
.take(maxNumberOfProblems);
}
exports.validateText = validateText;
function calcTextInclusionRanges(text, options) {
const { ignoreRegExpList = [], includeRegExpList = [] } = options;
const filteredIncludeList = includeRegExpList.filter((a) => !!a);
const finalIncludeList = filteredIncludeList.length ? filteredIncludeList : ['.*'];
const includeRanges = TextRange.excludeRanges(TextRange.findMatchingRangesForPatterns(finalIncludeList, text), TextRange.findMatchingRangesForPatterns(ignoreRegExpList, text));
return includeRanges;
}
exports.calcTextInclusionRanges = calcTextInclusionRanges;
function lineValidator(dict, options) {
const { minWordLength = exports.defaultMinWordLength, flagWords = [], ignoreWords = [], allowCompoundWords = false, ignoreCase = true, caseSensitive = false, } = options;
const checkOptions = {
...options,
allowCompoundWords,
ignoreCase,
caseSensitive,
};
const setOfFlagWords = new Set(flagWords);
const mappedIgnoreWords = options.caseSensitive
? ignoreWords
: ignoreWords.concat(ignoreWords.map((a) => a.toLowerCase()));
const ignoreWordsSet = new Set(mappedIgnoreWords);
const setOfKnownSuccessfulWords = new Set();
const rememberFilter = (fn) => (v) => {
const keep = fn(v);
if (!keep) {
setOfKnownSuccessfulWords.add(v.text);
}
return keep;
};
const filterAlreadyChecked = (wo) => {
return !setOfKnownSuccessfulWords.has(wo.text);
};
function testForFlaggedWord(wo) {
return setOfFlagWords.has(wo.text) || setOfFlagWords.has(wo.text.toLowerCase());
}
function checkFlagWords(word) {
const isFlagged = testForFlaggedWord(word);
word.isFlagged = isFlagged;
return word;
}
function checkWord(word, options) {
const isFlagged = testForFlaggedWord(word);
const isFound = isFlagged ? undefined : isWordValid(dict, word, word.line, options);
return { ...word, isFlagged, isFound };
}
const fn = (lineSegment) => {
function checkFullWord(vr) {
if (vr.isFlagged) {
return [vr];
}
const codeWordResults = Text.extractWordsFromCodeTextOffset(vr)
.filter(filterAlreadyChecked)
.filter(rememberFilter((wo) => wo.text.length >= minWordLength))
.map((t) => ({ ...t, line: vr.line }))
.map((wo) => {
const vr = { ...wo, text: wo.text.toLowerCase() };
return vr;
})
.map((wo) => (wo.isFlagged ? wo : checkWord(wo, checkOptions)))
.filter(rememberFilter((wo) => wo.isFlagged || !wo.isFound))
.filter(rememberFilter((wo) => !ignoreWordsSet.has(wo.text)))
.filter(rememberFilter((wo) => !RxPat.regExHexDigits.test(wo.text))) // Filter out any hex numbers
.filter(rememberFilter((wo) => !RxPat.regExRepeatedChar.test(wo.text))) // Filter out any repeated characters like xxxxxxxxxx
// get back the original text.
.map((wo) => ({ ...wo, text: Text.extractText(lineSegment, wo.offset, wo.offset + wo.text.length) }))
.toArray();
if (!codeWordResults.length || ignoreWordsSet.has(vr.text) || checkWord(vr, checkOptions).isFound) {
rememberFilter((_) => false)(vr);
return [];
}
return codeWordResults;
}
// Check the whole words, not yet split
const checkedWords = Text.extractWordsFromTextOffset(lineSegment)
.filter(filterAlreadyChecked)
.filter(rememberFilter((wo) => wo.text.length >= minWordLength))
.map((wo) => ({ ...wo, line: lineSegment }))
.map(checkFlagWords)
.concatMap(checkFullWord);
return checkedWords;
};
return fn;
}
function isWordValid(dict, wo, line, options) {
const firstTry = hasWordCheck(dict, wo.text, options);
return (firstTry ||
// Drop the first letter if it is preceded by a '\'.
(line.text[wo.offset - line.offset - 1] === '\\' && hasWordCheck(dict, wo.text.slice(1), options)));
}
exports.isWordValid = isWordValid;
function hasWordCheck(dict, word, options) {
word = word.replace(/\\/g, '');
// Do not pass allowCompounds down if it is false, that allows for the dictionary to override the value based upon its own settings.
return dict.has(word, convertCheckOptionsToHasOptions(options));
}
exports.hasWordCheck = hasWordCheck;
function convertCheckOptionsToHasOptions(opt) {
const { ignoreCase, allowCompoundWords } = opt;
return {
ignoreCase,
useCompounds: allowCompoundWords || undefined,
};
}
/**
* Returns a mapper function that will
* @param includeRanges Allowed ranges for words.
*/
function mapTextOffsetsAgainstRanges(includeRanges) {
let rangePos = 0;
const mapper = (textOffset) => {
if (!includeRanges.length) {
return [];
}
const parts = [];
const { text, offset } = textOffset;
const wordEndPos = offset + text.length;
let wordStartPos = offset;
while (rangePos && (rangePos >= includeRanges.length || includeRanges[rangePos].startPos > wordStartPos)) {
rangePos -= 1;
}
while (wordStartPos < wordEndPos) {
while (includeRanges[rangePos] && includeRanges[rangePos].endPos <= wordStartPos) {
rangePos += 1;
}
if (!includeRanges[rangePos] || wordEndPos < includeRanges[rangePos].startPos) {
break;
}
const { startPos, endPos } = includeRanges[rangePos];
const a = Math.max(wordStartPos, startPos);
const b = Math.min(wordEndPos, endPos);
parts.push({ offset: a, text: text.slice(a - offset, b - offset) });
wordStartPos = b;
}
return parts.filter((wo) => !!wo.text);
};
return mapper;
}
exports._testMethods = {
mapWordsAgainstRanges: mapTextOffsetsAgainstRanges,
};
//# sourceMappingURL=textValidator.js.map