Skip to content

Commit 04cd016

Browse files
Adrien Skoic
authored andcommitted
Add autocorrect to Rails/LinkToBlank (#6604)
1 parent 00318ce commit 04cd016

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

lib/rubocop/cop/rails/link_to_blank.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ class LinkToBlank < Cop
2525
(pair {(sym :rel) (str "rel")} (str #contains_noopener?))
2626
PATTERN
2727

28+
def_node_matcher :rel_node?, <<-PATTERN
29+
(pair {(sym :rel) (str "rel")} (str _))
30+
PATTERN
31+
2832
def on_send(node)
2933
return unless node.method?(:link_to)
3034

@@ -38,8 +42,41 @@ def on_send(node)
3842
end
3943
end
4044

45+
def autocorrect(node)
46+
lambda do |corrector|
47+
send_node = node.parent.parent
48+
49+
option_nodes = send_node.each_child_node(:hash)
50+
rel_node = nil
51+
option_nodes.map(&:children).each do |options|
52+
rel_node ||= options.find { |o| rel_node?(o) }
53+
end
54+
55+
if rel_node
56+
append_to_rel(rel_node, corrector)
57+
else
58+
add_rel(send_node, node, corrector)
59+
end
60+
end
61+
end
62+
4163
private
4264

65+
def append_to_rel(rel_node, corrector)
66+
existing_rel = rel_node.children.last.value
67+
str_range = rel_node.children.last.loc.expression.adjust(
68+
begin_pos: 1,
69+
end_pos: -1
70+
)
71+
corrector.replace(str_range, "#{existing_rel} noopener")
72+
end
73+
74+
def add_rel(send_node, offence_node, corrector)
75+
quote_style = offence_node.children.last.source[0]
76+
new_rel_exp = ", rel: #{quote_style}noopener#{quote_style}"
77+
corrector.insert_after(send_node.loc.expression, new_rel_exp)
78+
end
79+
4380
def contains_noopener?(str)
4481
return false unless str
4582

manual/cops_rails.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,7 @@ Include | `app/controllers/**/*.rb` | Array
11831183

11841184
Enabled by default | Supports autocorrection
11851185
--- | ---
1186-
Enabled | No
1186+
Enabled | Yes
11871187

11881188
This cop checks for calls to `link_to` that contain a
11891189
`target: '_blank'` but no `rel: 'noopener'`. This can be a security

spec/rubocop/cop/rails/link_to_blank_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@
3434
RUBY
3535
end
3636

37+
it 'autocorrects with a new rel' do
38+
new_source = autocorrect_source(<<-RUBY.strip_indent)
39+
link_to 'Click here', 'https://www.example.com', target: '_blank'
40+
RUBY
41+
expect(new_source).to eq(<<-RUBY.strip_indent)
42+
link_to 'Click here', 'https://www.example.com', target: '_blank', rel: 'noopener'
43+
RUBY
44+
end
45+
3746
it 'registers an offence when using a string for the target key' do
3847
expect_offense(<<-RUBY.strip_indent)
3948
link_to 'Click here', 'https://www.example.com', "target" => '_blank'
@@ -49,6 +58,19 @@
4958
end
5059
RUBY
5160
end
61+
62+
it 'autocorrects with a new rel when using the block syntax' do
63+
new_source = autocorrect_source(<<-RUBY.strip_indent)
64+
link_to 'https://www.example.com', target: '_blank' do
65+
"Click here"
66+
end
67+
RUBY
68+
expect(new_source).to eq(<<-RUBY.strip_indent)
69+
link_to 'https://www.example.com', target: '_blank', rel: 'noopener' do
70+
"Click here"
71+
end
72+
RUBY
73+
end
5274
end
5375

5476
context 'when using rel' do
@@ -59,6 +81,15 @@
5981
^^^^^^^^^^^^^^^^^^^^ Specify a `:rel` option containing noopener.
6082
RUBY
6183
end
84+
85+
it 'autocorrects by appending to the existing rel' do
86+
new_source = autocorrect_source(<<-RUBY.strip_indent)
87+
link_to 'Click here', 'https://www.example.com', target: '_blank', rel: 'foo'
88+
RUBY
89+
expect(new_source).to eq(<<-RUBY.strip_indent)
90+
link_to 'Click here', 'https://www.example.com', target: '_blank', rel: 'foo noopener'
91+
RUBY
92+
end
6293
end
6394

6495
context 'when the rel contains noopener' do

0 commit comments

Comments
 (0)