Refactor to remove helper withinAnyRange.

This commit is contained in:
David Anson 2024-09-28 15:41:40 -07:00
parent 5e568d0da9
commit 124b7e2276
3 changed files with 60 additions and 92 deletions

View file

@ -386,24 +386,6 @@ function addErrorContextForLine(onError, lines, lineIndex, lineNumber) {
} }
module.exports.addErrorContextForLine = addErrorContextForLine; module.exports.addErrorContextForLine = addErrorContextForLine;
/**
* Determines whether the specified range is within another range.
*
* @param {number[][]} ranges Array of ranges (line, index, length).
* @param {number} lineIndex Line index to check.
* @param {number} index Index to check.
* @param {number} length Length to check.
* @returns {boolean} True iff the specified range is within.
*/
const withinAnyRange = (ranges, lineIndex, index, length) => (
!ranges.every((span) => (
(lineIndex !== span[0]) ||
(index < span[1]) ||
(index + length > span[1] + span[2])
))
);
module.exports.withinAnyRange = withinAnyRange;
/** /**
* Defines a range within a file (start line/column to end line/column, subset of MicromarkToken). * Defines a range within a file (start line/column to end line/column, subset of MicromarkToken).
* *
@ -5819,10 +5801,8 @@ module.exports = {
const { addErrorDetailIf, escapeForRegExp, withinAnyRange } = const { addErrorDetailIf, escapeForRegExp, hasOverlap } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { filterByPredicate, filterByTypes, parse } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
const { filterByPredicate, filterByTypes, parse } =
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
const ignoredChildTypes = new Set( const ignoredChildTypes = new Set(
[ "codeFencedFence", "definition", "reference", "resource" ] [ "codeFencedFence", "definition", "reference", "resource" ]
@ -5866,43 +5846,47 @@ module.exports = {
token.children.filter((t) => !ignoredChildTypes.has(t.type)) token.children.filter((t) => !ignoredChildTypes.has(t.type))
) )
); );
/** @type {import("../helpers").FileRange[]} */
const exclusions = []; const exclusions = [];
const autoLinked = new Set(); const scannedTokens = new Set();
for (const name of names) { for (const name of names) {
const escapedName = escapeForRegExp(name); const escapedName = escapeForRegExp(name);
const startNamePattern = /^\W/.test(name) ? "" : "\\b_*"; const startNamePattern = /^\W/.test(name) ? "" : "\\b_*";
const endNamePattern = /\W$/.test(name) ? "" : "_*\\b"; const endNamePattern = /\W$/.test(name) ? "" : "_*\\b";
const namePattern = const namePattern = `(${startNamePattern})(${escapedName})${endNamePattern}`;
`(${startNamePattern})(${escapedName})${endNamePattern}`;
const nameRe = new RegExp(namePattern, "gi"); const nameRe = new RegExp(namePattern, "gi");
for (const token of contentTokens) { for (const token of contentTokens) {
let match = null; let match = null;
while ((match = nameRe.exec(token.text)) !== null) { while ((match = nameRe.exec(token.text)) !== null) {
const [ , leftMatch, nameMatch ] = match; const [ , leftMatch, nameMatch ] = match;
const index = token.startColumn - 1 + match.index + leftMatch.length; const column = token.startColumn + match.index + leftMatch.length;
const length = nameMatch.length; const length = nameMatch.length;
const lineIndex = token.startLine - 1; const lineNumber = token.startLine;
/** @type {import("../helpers").FileRange} */
const nameRange = {
"startLine": lineNumber,
"startColumn": column,
"endLine": lineNumber,
"endColumn": column + length - 1
};
if ( if (
!withinAnyRange(exclusions, lineIndex, index, length) && !names.includes(nameMatch) &&
!names.includes(nameMatch) !exclusions.some((exclusion) => hasOverlap(exclusion, nameRange))
) { ) {
let urlRanges = []; /** @type {import("../helpers").FileRange[]} */
if (!autoLinked.has(token)) { let autolinkRanges = [];
urlRanges = filterByTypes( if (!scannedTokens.has(token)) {
parse(token.text), autolinkRanges = filterByTypes(parse(token.text), [ "literalAutolink" ])
[ "literalAutolink" ] .map((tok) => ({
).map( "startLine": lineNumber,
(t) => [ "startColumn": token.startColumn + tok.startColumn - 1,
lineIndex, "endLine": lineNumber,
token.startColumn - 1 + t.startColumn - 1, "endColumn": token.endColumn + tok.endColumn - 1
t.endColumn - t.startColumn }));
] exclusions.push(...autolinkRanges);
); scannedTokens.add(token);
exclusions.push(...urlRanges);
autoLinked.add(token);
} }
if (!withinAnyRange(urlRanges, lineIndex, index, length)) { if (!autolinkRanges.some((autolinkRange) => hasOverlap(autolinkRange, nameRange))) {
const column = index + 1;
addErrorDetailIf( addErrorDetailIf(
onError, onError,
token.startLine, token.startLine,
@ -5919,7 +5903,7 @@ module.exports = {
); );
} }
} }
exclusions.push([ lineIndex, index, length ]); exclusions.push(nameRange);
} }
} }
} }

View file

@ -374,24 +374,6 @@ function addErrorContextForLine(onError, lines, lineIndex, lineNumber) {
} }
module.exports.addErrorContextForLine = addErrorContextForLine; module.exports.addErrorContextForLine = addErrorContextForLine;
/**
* Determines whether the specified range is within another range.
*
* @param {number[][]} ranges Array of ranges (line, index, length).
* @param {number} lineIndex Line index to check.
* @param {number} index Index to check.
* @param {number} length Length to check.
* @returns {boolean} True iff the specified range is within.
*/
const withinAnyRange = (ranges, lineIndex, index, length) => (
!ranges.every((span) => (
(lineIndex !== span[0]) ||
(index < span[1]) ||
(index + length > span[1] + span[2])
))
);
module.exports.withinAnyRange = withinAnyRange;
/** /**
* Defines a range within a file (start line/column to end line/column, subset of MicromarkToken). * Defines a range within a file (start line/column to end line/column, subset of MicromarkToken).
* *

View file

@ -2,10 +2,8 @@
"use strict"; "use strict";
const { addErrorDetailIf, escapeForRegExp, withinAnyRange } = const { addErrorDetailIf, escapeForRegExp, hasOverlap } = require("../helpers");
require("../helpers"); const { filterByPredicate, filterByTypes, parse } = require("../helpers/micromark.cjs");
const { filterByPredicate, filterByTypes, parse } =
require("../helpers/micromark.cjs");
const ignoredChildTypes = new Set( const ignoredChildTypes = new Set(
[ "codeFencedFence", "definition", "reference", "resource" ] [ "codeFencedFence", "definition", "reference", "resource" ]
@ -49,43 +47,47 @@ module.exports = {
token.children.filter((t) => !ignoredChildTypes.has(t.type)) token.children.filter((t) => !ignoredChildTypes.has(t.type))
) )
); );
/** @type {import("../helpers").FileRange[]} */
const exclusions = []; const exclusions = [];
const autoLinked = new Set(); const scannedTokens = new Set();
for (const name of names) { for (const name of names) {
const escapedName = escapeForRegExp(name); const escapedName = escapeForRegExp(name);
const startNamePattern = /^\W/.test(name) ? "" : "\\b_*"; const startNamePattern = /^\W/.test(name) ? "" : "\\b_*";
const endNamePattern = /\W$/.test(name) ? "" : "_*\\b"; const endNamePattern = /\W$/.test(name) ? "" : "_*\\b";
const namePattern = const namePattern = `(${startNamePattern})(${escapedName})${endNamePattern}`;
`(${startNamePattern})(${escapedName})${endNamePattern}`;
const nameRe = new RegExp(namePattern, "gi"); const nameRe = new RegExp(namePattern, "gi");
for (const token of contentTokens) { for (const token of contentTokens) {
let match = null; let match = null;
while ((match = nameRe.exec(token.text)) !== null) { while ((match = nameRe.exec(token.text)) !== null) {
const [ , leftMatch, nameMatch ] = match; const [ , leftMatch, nameMatch ] = match;
const index = token.startColumn - 1 + match.index + leftMatch.length; const column = token.startColumn + match.index + leftMatch.length;
const length = nameMatch.length; const length = nameMatch.length;
const lineIndex = token.startLine - 1; const lineNumber = token.startLine;
/** @type {import("../helpers").FileRange} */
const nameRange = {
"startLine": lineNumber,
"startColumn": column,
"endLine": lineNumber,
"endColumn": column + length - 1
};
if ( if (
!withinAnyRange(exclusions, lineIndex, index, length) && !names.includes(nameMatch) &&
!names.includes(nameMatch) !exclusions.some((exclusion) => hasOverlap(exclusion, nameRange))
) { ) {
let urlRanges = []; /** @type {import("../helpers").FileRange[]} */
if (!autoLinked.has(token)) { let autolinkRanges = [];
urlRanges = filterByTypes( if (!scannedTokens.has(token)) {
parse(token.text), autolinkRanges = filterByTypes(parse(token.text), [ "literalAutolink" ])
[ "literalAutolink" ] .map((tok) => ({
).map( "startLine": lineNumber,
(t) => [ "startColumn": token.startColumn + tok.startColumn - 1,
lineIndex, "endLine": lineNumber,
token.startColumn - 1 + t.startColumn - 1, "endColumn": token.endColumn + tok.endColumn - 1
t.endColumn - t.startColumn }));
] exclusions.push(...autolinkRanges);
); scannedTokens.add(token);
exclusions.push(...urlRanges);
autoLinked.add(token);
} }
if (!withinAnyRange(urlRanges, lineIndex, index, length)) { if (!autolinkRanges.some((autolinkRange) => hasOverlap(autolinkRange, nameRange))) {
const column = index + 1;
addErrorDetailIf( addErrorDetailIf(
onError, onError,
token.startLine, token.startLine,
@ -102,7 +104,7 @@ module.exports = {
); );
} }
} }
exclusions.push([ lineIndex, index, length ]); exclusions.push(nameRange);
} }
} }
} }