diff --git a/src/rules/no-html.js b/src/rules/no-html.js index 167c32b6..2d25932b 100644 --- a/src/rules/no-html.js +++ b/src/rules/no-html.js @@ -3,12 +3,6 @@ * @author Nicholas C. Zakas */ -//----------------------------------------------------------------------------- -// Imports -//----------------------------------------------------------------------------- - -import { findOffsets } from "../util.js"; - //----------------------------------------------------------------------------- // Type Definitions //----------------------------------------------------------------------------- @@ -25,7 +19,7 @@ import { findOffsets } from "../util.js"; //----------------------------------------------------------------------------- const htmlTagPattern = - /<([a-z0-9]+(?:-[a-z0-9]+)*)(?:\s(?:[^>"']|"[^"]*"|'[^']*')*)?>/giu; + /<(?[a-z0-9]+(?:-[a-z0-9]+)*)(?:\s(?:[^>"']|"[^"]*"|'[^']*')*)?>/giu; const lineEndingPattern = /\r\n?|\n/u; //----------------------------------------------------------------------------- @@ -74,48 +68,45 @@ export default { }, create(context) { + const { sourceCode } = context; const [{ allowed, allowedIgnoreCase }] = context.options; - const allowedElements = new Set( - allowedIgnoreCase ? allowed.map(tag => tag.toLowerCase()) : allowed, - ); + + /** + * Normalize a tag name based on the `allowedIgnoreCase` option. + * @param {string} tagName The tag name to normalize. + * @returns {string} The normalized tag name. + */ + function normalizeTagName(tagName) { + return allowedIgnoreCase ? tagName.toLowerCase() : tagName; + } + + const allowedElements = new Set(allowed.map(normalizeTagName)); return { html(node) { + /** @type {RegExpExecArray} */ let match; while ((match = htmlTagPattern.exec(node.value)) !== null) { const fullMatch = match[0]; - const tagName = match[1]; - const { lineOffset, columnOffset } = findOffsets( - node.value, - match.index, - ); - const start = { - line: node.position.start.line + lineOffset, - column: node.position.start.column + columnOffset, - }; - + const { tagName } = match.groups; const firstNewlineIndex = fullMatch.search(lineEndingPattern); - const endColumn = - firstNewlineIndex === -1 - ? start.column + fullMatch.length - : start.column + firstNewlineIndex; - - const end = { - line: start.line, - column: endColumn, - }; - - const tagToCheck = allowedIgnoreCase - ? tagName.toLowerCase() - : tagName; - if ( - allowedElements.size === 0 || - !allowedElements.has(tagToCheck) - ) { + + const startOffset = // Adjust `htmlTagPattern` match index to the full source code. + match.index + node.position.start.offset; + const endOffset = + startOffset + + (firstNewlineIndex === -1 + ? fullMatch.length + : firstNewlineIndex); + + if (!allowedElements.has(normalizeTagName(tagName))) { context.report({ - loc: { start, end }, + loc: { + start: sourceCode.getLocFromIndex(startOffset), + end: sourceCode.getLocFromIndex(endOffset), + }, messageId: "disallowedElement", data: { name: tagName,