@@ -28,12 +28,12 @@ module.exports = {
28
28
} ,
29
29
create ( context ) {
30
30
const sourceCode = context . sourceCode ?? context . getSourceCode ( )
31
-
31
+
32
32
// Helper function to check if a node is in a text block
33
- const isNodeInTextBlock = ( node ) => {
33
+ const isNodeInTextBlock = node => {
34
34
let siblings = node . parent . children
35
35
if ( ! siblings || siblings . length === 0 ) return false
36
-
36
+
37
37
// Filter out whitespace nodes
38
38
siblings = siblings . filter ( childNode => {
39
39
return (
@@ -46,17 +46,17 @@ module.exports = {
46
46
! ( childNode . type === 'Literal' && / ^ \s + $ / . test ( childNode . value ) )
47
47
)
48
48
} )
49
-
49
+
50
50
const index = siblings . findIndex ( childNode => {
51
51
return childNode . range === node . range
52
52
} )
53
-
53
+
54
54
const prevSibling = siblings [ index - 1 ]
55
55
const nextSibling = siblings [ index + 1 ]
56
-
56
+
57
57
const prevSiblingIsText = prevSibling && prevSibling . type === 'JSXText'
58
58
const nextSiblingIsText = nextSibling && nextSibling . type === 'JSXText'
59
-
59
+
60
60
// If there's text on either side
61
61
if ( prevSiblingIsText || nextSiblingIsText ) {
62
62
// Skip if the only text adjacent to the link is a period
@@ -65,55 +65,49 @@ module.exports = {
65
65
}
66
66
return true
67
67
}
68
-
68
+
69
69
return false
70
70
}
71
-
71
+
72
72
return {
73
73
JSXElement ( node ) {
74
74
const name = getJSXOpeningElementName ( node . openingElement )
75
75
const parentName = node . parent . openingElement ?. name ?. name
76
76
const parentsToSkip = [ 'Heading' , 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' ]
77
-
77
+
78
78
// Check for HTML anchor elements
79
- if (
80
- isHTMLElement ( node . openingElement ) &&
81
- name === 'a' &&
82
- node . parent . children
83
- ) {
79
+ if ( isHTMLElement ( node . openingElement ) && name === 'a' && node . parent . children ) {
84
80
// Skip if anchor is nested inside of a heading
85
81
if ( parentsToSkip . includes ( parentName ) ) return
86
-
82
+
87
83
// Skip if anchor has className (might have distinguishing styles)
88
84
const classNameAttribute = getJSXOpeningElementAttribute ( node . openingElement , 'className' )
89
85
if ( classNameAttribute ) return
90
-
86
+
91
87
// Check for anchor in text block
92
88
if ( isNodeInTextBlock ( node ) ) {
93
89
// Skip if anchor child is a JSX element
94
90
const jsxElementChildren = node . children . filter ( child => child . type === 'JSXElement' )
95
91
if ( jsxElementChildren . length > 0 ) return
96
-
92
+
97
93
// Report and autofix
98
94
context . report ( {
99
95
node,
100
96
messageId : 'htmlAnchorInTextBlock' ,
101
97
fix ( fixer ) {
102
98
// Get all attributes from the anchor to transfer to Link
103
- const attributes = node . openingElement . attributes
104
- . map ( attr => sourceCode . getText ( attr ) )
105
- . join ( ' ' )
106
-
99
+ const attributes = node . openingElement . attributes . map ( attr => sourceCode . getText ( attr ) ) . join ( ' ' )
100
+
107
101
// Create the Link component opening and closing tags
108
102
const openingTag = `<Link ${ attributes } >`
109
103
const closingTag = '</Link>'
110
-
104
+
111
105
// Apply fixes to the opening and closing tags
112
106
const openingFix = fixer . replaceText ( node . openingElement , openingTag )
113
107
const closingFix = fixer . replaceText ( node . closingElement , closingTag )
114
-
108
+
115
109
return [ openingFix , closingFix ]
116
- }
110
+ } ,
117
111
} )
118
112
}
119
113
}
0 commit comments