diff --git a/src/language/markdown-source-code.js b/src/language/markdown-source-code.js index 6127be89..2c45f96b 100644 --- a/src/language/markdown-source-code.js +++ b/src/language/markdown-source-code.js @@ -13,7 +13,6 @@ import { ConfigCommentParser, Directive, } from "@eslint/plugin-kit"; -import { findOffsets } from "../util.js"; //----------------------------------------------------------------------------- // Types @@ -66,53 +65,38 @@ class InlineConfigComment { /** * Extracts inline configuration comments from an HTML node. * @param {Html} node The HTML node to extract comments from. + * @param {MarkdownSourceCode} sourceCode The Markdown source code object. * @returns {Array} The inline configuration comments found in the node. */ -function extractInlineConfigCommentsFromHTML(node) { +function extractInlineConfigCommentsFromHTML(node, sourceCode) { if (!configCommentStart.test(node.value)) { return []; } + + /** @type {Array} */ const comments = []; + /** @type {RegExpExecArray} */ let match; while ((match = htmlComment.exec(node.value))) { if (configCommentStart.test(match[0])) { - const comment = match[0]; - - // calculate location of the comment inside the node - const start = { - ...node.position.start, - }; - - const end = { - ...node.position.start, - }; - - const { - lineOffset: startLineOffset, - columnOffset: startColumnOffset, - } = findOffsets(node.value, match.index); - - start.line += startLineOffset; - start.column += startColumnOffset; - start.offset += match.index; - - const commentLineCount = comment.split("\n").length - 1; - - end.line = start.line + commentLineCount; - end.column = - commentLineCount === 0 - ? start.column + comment.length - : comment.length - comment.lastIndexOf("\n"); - end.offset = start.offset + comment.length; + // calculate offset of the comment inside the node + const startOffset = match.index + node.position.start.offset; + const endOffset = startOffset + match[0].length; comments.push( new InlineConfigComment({ value: match[1].trim(), position: { - start, - end, + start: { + ...sourceCode.getLocFromIndex(startOffset), + offset: startOffset, + }, + end: { + ...sourceCode.getLocFromIndex(endOffset), + offset: endOffset, + }, }, }), ); @@ -191,8 +175,8 @@ export class MarkdownSourceCode extends TextSourceCodeBase { */ getInlineConfigNodes() { if (!this.#inlineConfigComments) { - this.#inlineConfigComments = this.#htmlNodes.flatMap( - extractInlineConfigCommentsFromHTML, + this.#inlineConfigComments = this.#htmlNodes.flatMap(htmlNode => + extractInlineConfigCommentsFromHTML(htmlNode, this), ); } diff --git a/src/util.js b/src/util.js index e2dee3e7..36cf9954 100644 --- a/src/util.js +++ b/src/util.js @@ -23,34 +23,6 @@ export const htmlCommentPattern = //gu; // Helpers //----------------------------------------------------------------------------- -/** - * Finds the line and column offsets for a given offset in a string. - * @param {string} text The text to search. - * @param {number} offset The offset to find. - * @returns {{lineOffset:number,columnOffset:number}} The location of the offset. - * Note that `columnOffset` should be used as an offset to the column number - * of the given text in the source code only when `lineOffset` is 0. - * Otherwise, it should be used as a 0-based column number in the source code. - */ -export function findOffsets(text, offset) { - let lineOffset = 0; - let columnOffset = 0; - - for (let i = 0; i < offset; i++) { - if (text[i] === "\n") { - lineOffset++; - columnOffset = 0; - } else { - columnOffset++; - } - } - - return { - lineOffset, - columnOffset, - }; -} - /** * Checks if a frontmatter block contains a title matching the given pattern * @param {string} value The frontmatter content diff --git a/tests/util.test.js b/tests/util.test.js index be01a358..f5c2de57 100644 --- a/tests/util.test.js +++ b/tests/util.test.js @@ -8,57 +8,13 @@ //------------------------------------------------------------------------------ import assert from "node:assert"; -import { - findOffsets, - frontmatterHasTitle, - stripHtmlComments, -} from "../src/util.js"; +import { frontmatterHasTitle, stripHtmlComments } from "../src/util.js"; //------------------------------------------------------------------------------ // Tests //------------------------------------------------------------------------------ describe("util", () => { - describe("findOffsets()", () => { - it("should return correct offsets for a simple string", () => { - const text = "Hello world!"; - const offset = 6; // 'w' in "world" - const result = findOffsets(text, offset); - assert.deepStrictEqual(result, { lineOffset: 0, columnOffset: 6 }); - }); - - it("should handle line breaks correctly", () => { - const text = "Hello\nworld!"; - const offset = 6; // 'w' in "world" - const result = findOffsets(text, offset); - assert.deepStrictEqual(result, { lineOffset: 1, columnOffset: 0 }); - }); - - it("should handle Windows-style line endings", () => { - const text = "Hello\r\nworld!"; - const offset = 7; // 'w' in "world" - const result = findOffsets(text, offset); - assert.deepStrictEqual(result, { lineOffset: 1, columnOffset: 0 }); - }); - - it("should handle offsets at the start of the string", () => { - const text = "Hello, world!"; - const offset = 0; // Start of the string - const result = findOffsets(text, offset); - assert.deepStrictEqual(result, { lineOffset: 0, columnOffset: 0 }); - }); - - it("should handle offsets at the end of the string", () => { - const text = "Hello, world!"; - const offset = text.length - 1; // Last character '!' - const result = findOffsets(text, offset); - assert.deepStrictEqual(result, { - lineOffset: 0, - columnOffset: text.length - 1, - }); - }); - }); - describe("frontmatterHasTitle()", () => { const pattern = /^title:\s*My Document$/u;