33 * @author xbinaryx
44 */
55
6- //-----------------------------------------------------------------------------
7- // Imports
8- //-----------------------------------------------------------------------------
9-
10- import { findOffsets } from "../util.js" ;
11-
126//-----------------------------------------------------------------------------
137// Type Definitions
148//-----------------------------------------------------------------------------
159
1610/**
1711 * @import { SourceRange } from "@eslint/core"
18- * @import { Heading, Paragraph, TableCell } from "mdast";
12+ * @import { Heading, Paragraph, TableCell, Html, InlineCode } from "mdast";
1913 * @import { MarkdownRuleDefinition } from "../types.js";
2014 * @typedef {"reversedSyntax" } NoReversedMediaSyntaxMessageIds
2115 * @typedef {[] } NoReversedMediaSyntaxOptions
@@ -28,7 +22,7 @@ import { findOffsets } from "../util.js";
2822
2923/** Matches reversed link/image syntax like `(text)[url]`, ignoring escaped characters like `\(text\)[url]`. */
3024const reversedPattern =
31- / (?< = (?< ! \\ ) (?: \\ { 2 } ) * ) \( ( (?: \\ .| [ ^ ( ) \\ ] | \( [ \s \S ] * \) ) * ) \) \[ ( (?: \\ .| [ ^ \] \\ \n ] ) * ) \] (? ! \( ) / gu;
25+ / (?< = (?< ! \\ ) (?: \\ { 2 } ) * ) \( (?< label > (?: \\ .| [ ^ ( ) \\ ] | \( [ \s \S ] * \) ) * ) \) \[ (?< url > (?: \\ .| [ ^ \] \\ \n ] ) * ) \] (? ! \( ) / gu;
3226
3327/**
3428 * Checks if a match is within any skip range
@@ -69,7 +63,7 @@ export default {
6963 const { sourceCode } = context ;
7064
7165 /** @type {Array<SourceRange> } */
72- let skipRanges = [ ] ;
66+ const skipRanges = [ ] ;
7367
7468 /**
7569 * Finds reversed link/image syntax in a node.
@@ -78,61 +72,26 @@ export default {
7872 */
7973 function findReversedMediaSyntax ( node ) {
8074 const text = sourceCode . getText ( node ) ;
75+
76+ /** @type {RegExpExecArray } */
8177 let match ;
8278
8379 while ( ( match = reversedPattern . exec ( text ) ) !== null ) {
84- const [ reversedSyntax , label , url ] = match ;
85- const matchIndex = match . index ;
86- const matchLength = reversedSyntax . length ;
87-
88- if (
89- isInSkipRange (
90- matchIndex + node . position . start . offset ,
91- skipRanges ,
92- )
93- ) {
80+ const { label, url } = match . groups ;
81+ const startOffset = match . index + node . position . start . offset ; // Adjust `reversedPattern` match index to the full source code.
82+ const endOffset = startOffset + match [ 0 ] . length ;
83+
84+ if ( isInSkipRange ( startOffset , skipRanges ) ) {
9485 continue ;
9586 }
9687
97- const {
98- lineOffset : startLineOffset ,
99- columnOffset : startColumnOffset ,
100- } = findOffsets ( text , matchIndex ) ;
101- const {
102- lineOffset : endLineOffset ,
103- columnOffset : endColumnOffset ,
104- } = findOffsets ( text , matchIndex + matchLength ) ;
105-
106- const baseColumn = 1 ;
107- const nodeStartLine = node . position . start . line ;
108- const nodeStartColumn = node . position . start . column ;
109- const startLine = nodeStartLine + startLineOffset ;
110- const endLine = nodeStartLine + endLineOffset ;
111- const startColumn =
112- ( startLine === nodeStartLine
113- ? nodeStartColumn
114- : baseColumn ) + startColumnOffset ;
115- const endColumn =
116- ( endLine === nodeStartLine ? nodeStartColumn : baseColumn ) +
117- endColumnOffset ;
118-
11988 context . report ( {
12089 loc : {
121- start : {
122- line : startLine ,
123- column : startColumn ,
124- } ,
125- end : {
126- line : endLine ,
127- column : endColumn ,
128- } ,
90+ start : sourceCode . getLocFromIndex ( startOffset ) ,
91+ end : sourceCode . getLocFromIndex ( endOffset ) ,
12992 } ,
13093 messageId : "reversedSyntax" ,
13194 fix ( fixer ) {
132- const startOffset =
133- node . position . start . offset + matchIndex ;
134- const endOffset = startOffset + matchLength ;
135-
13695 return fixer . replaceTextRange (
13796 [ startOffset , endOffset ] ,
13897 `[${ label } ](${ url } )` ,
@@ -143,31 +102,17 @@ export default {
143102 }
144103
145104 return {
146- "heading :matches(html, inlineCode)" ( node ) {
147- skipRanges . push ( sourceCode . getRange ( node ) ) ;
148- } ,
149-
150- "heading:exit" ( node ) {
151- findReversedMediaSyntax ( node ) ;
152- skipRanges = [ ] ;
153- } ,
154-
155- "paragraph :matches(html, inlineCode)" ( node ) {
156- skipRanges . push ( sourceCode . getRange ( node ) ) ;
157- } ,
158-
159- "paragraph:exit" ( node ) {
160- findReversedMediaSyntax ( node ) ;
161- skipRanges = [ ] ;
162- } ,
163-
164- "tableCell :matches(html, inlineCode)" ( node ) {
105+ ":matches(heading, paragraph, tableCell) :matches(html, inlineCode)" (
106+ /** @type {Html | InlineCode } */ node ,
107+ ) {
165108 skipRanges . push ( sourceCode . getRange ( node ) ) ;
166109 } ,
167110
168- "tableCell:exit" ( node ) {
111+ ":matches(heading, paragraph, tableCell):exit" (
112+ /** @type {Heading | Paragraph | TableCell } */ node ,
113+ ) {
169114 findReversedMediaSyntax ( node ) ;
170- skipRanges = [ ] ;
115+ skipRanges . length = 0 ;
171116 } ,
172117 } ;
173118 } ,
0 commit comments