primer_view_components 0.0.48 → 0.0.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +155 -0
- data/app/components/primer/base_component.rb +2 -2
- data/app/components/primer/beta/avatar.rb +1 -1
- data/app/components/primer/{avatar_stack_component.html.erb → beta/avatar_stack.html.erb} +0 -0
- data/app/components/primer/beta/avatar_stack.rb +92 -0
- data/app/components/primer/beta/truncate.html.erb +5 -0
- data/app/components/primer/beta/truncate.rb +110 -0
- data/app/components/primer/border_box_component.rb +27 -1
- data/app/components/primer/clipboard_copy.html.erb +2 -2
- data/app/components/primer/clipboard_copy.rb +1 -1
- data/app/components/primer/dropdown.rb +7 -7
- data/app/components/primer/icon_button.rb +1 -1
- data/app/components/primer/image_crop.html.erb +4 -4
- data/app/components/primer/label_component.rb +13 -12
- data/app/components/primer/navigation/tab_component.rb +16 -2
- data/app/components/primer/progress_bar_component.rb +0 -3
- data/app/components/primer/tab_nav_component.rb +4 -3
- data/app/components/primer/truncate.rb +1 -1
- data/app/components/primer/underline_nav_component.rb +3 -2
- data/app/lib/primer/fetch_or_fallback_helper.rb +2 -0
- data/app/lib/primer/octicon/cache.rb +1 -1
- data/app/lib/primer/tabbed_component_helper.rb +1 -1
- data/app/lib/primer/view_helper.rb +1 -0
- data/lib/primer/classify.rb +4 -16
- data/lib/primer/classify/cache.rb +0 -5
- data/lib/primer/classify/flex.rb +1 -1
- data/lib/primer/classify/functional_colors.rb +1 -1
- data/lib/primer/classify/utilities.rb +51 -13
- data/lib/primer/classify/utilities.yml +16 -0
- data/lib/primer/classify/validation.rb +18 -0
- data/lib/primer/view_components.rb +34 -6
- data/lib/primer/view_components/constants.rb +55 -0
- data/lib/primer/view_components/linters/argument_mappers/base.rb +100 -0
- data/lib/primer/view_components/linters/argument_mappers/button.rb +33 -46
- data/lib/primer/view_components/linters/argument_mappers/clipboard_copy.rb +19 -0
- data/lib/primer/view_components/linters/argument_mappers/helpers/erb_block.rb +67 -0
- data/lib/primer/view_components/linters/argument_mappers/label.rb +49 -0
- data/lib/primer/view_components/linters/argument_mappers/system_arguments.rb +6 -5
- data/lib/primer/view_components/linters/autocorrectable.rb +30 -0
- data/lib/primer/view_components/linters/button_component_migration_counter.rb +9 -23
- data/lib/primer/view_components/linters/clipboard_copy_component_migration_counter.rb +21 -0
- data/lib/primer/view_components/linters/close_button_component_migration_counter.rb +16 -0
- data/lib/primer/view_components/linters/helpers.rb +47 -42
- data/lib/primer/view_components/linters/label_component_migration_counter.rb +25 -0
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/rubocop/config/default.yml +5 -0
- data/lib/rubocop/cop/primer.rb +1 -2
- data/lib/rubocop/cop/primer/deprecated_arguments.rb +173 -0
- data/lib/rubocop/cop/primer/no_tag_memoize.rb +1 -0
- data/lib/rubocop/cop/primer/primer_octicon.rb +178 -0
- data/lib/rubocop/cop/primer/system_argument_instead_of_class.rb +12 -16
- data/lib/tasks/constants.rake +12 -0
- data/lib/tasks/coverage.rake +4 -0
- data/lib/tasks/docs.rake +27 -25
- data/lib/tasks/utilities.rake +9 -13
- data/lib/yard/docs_helper.rb +15 -5
- data/static/arguments.yml +980 -0
- data/static/assets/view-components.svg +18 -0
- data/static/classes.yml +182 -0
- data/static/constants.json +640 -0
- data/static/statuses.json +4 -2
- metadata +29 -10
- data/app/components/primer/avatar_stack_component.rb +0 -90
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module ERBLint
|
6
|
+
module Linters
|
7
|
+
module ArgumentMappers
|
8
|
+
# Maps classes in a label element to arguments for the Label component.
|
9
|
+
class Label < Base
|
10
|
+
SCHEME_MAPPINGS = Primer::ViewComponents::Constants.get(
|
11
|
+
component: "Primer::LabelComponent",
|
12
|
+
constant: "SCHEME_MAPPINGS",
|
13
|
+
symbolize: true
|
14
|
+
).freeze
|
15
|
+
|
16
|
+
VARIANT_MAPPINGS = Primer::ViewComponents::Constants.get(
|
17
|
+
component: "Primer::LabelComponent",
|
18
|
+
constant: "VARIANT_MAPPINGS",
|
19
|
+
symbolize: true
|
20
|
+
).freeze
|
21
|
+
|
22
|
+
DEFAULT_TAG = Primer::ViewComponents::Constants.get(
|
23
|
+
component: "Primer::LabelComponent",
|
24
|
+
constant: "DEFAULT_TAG"
|
25
|
+
).freeze
|
26
|
+
|
27
|
+
ATTRIBUTES = %w[title].freeze
|
28
|
+
|
29
|
+
def attribute_to_args(attribute)
|
30
|
+
{ title: erb_helper.convert(attribute) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def classes_to_args(classes)
|
34
|
+
classes.split.each_with_object({ classes: [] }) do |class_name, acc|
|
35
|
+
next if class_name == "Label"
|
36
|
+
|
37
|
+
if SCHEME_MAPPINGS[class_name] && acc[:scheme].nil?
|
38
|
+
acc[:scheme] = SCHEME_MAPPINGS[class_name]
|
39
|
+
elsif VARIANT_MAPPINGS[class_name] && acc[:variant].nil?
|
40
|
+
acc[:variant] = VARIANT_MAPPINGS[class_name]
|
41
|
+
else
|
42
|
+
acc[:classes] << class_name
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "conversion_error"
|
4
|
+
require_relative "helpers/erb_block"
|
4
5
|
|
5
6
|
module ERBLint
|
6
7
|
module Linters
|
@@ -10,9 +11,11 @@ module ERBLint
|
|
10
11
|
STRING_PARAMETERS = %w[aria- data-].freeze
|
11
12
|
TEST_SELECTOR_REGEX = /test_selector\((?<selector>.+)\)$/.freeze
|
12
13
|
|
13
|
-
attr_reader :attribute
|
14
|
+
attr_reader :attribute, :erb_helper
|
15
|
+
|
14
16
|
def initialize(attribute)
|
15
17
|
@attribute = attribute
|
18
|
+
@erb_helper = Helpers::ErbBlock.new
|
16
19
|
end
|
17
20
|
|
18
21
|
def to_args
|
@@ -28,11 +31,9 @@ module ERBLint
|
|
28
31
|
|
29
32
|
{ test_selector: m[:selector].tr("'", '"') }
|
30
33
|
elsif attr_name == "data-test-selector"
|
31
|
-
{ test_selector: attribute
|
34
|
+
{ test_selector: erb_helper.convert(attribute) }
|
32
35
|
elsif attr_name.start_with?(*STRING_PARAMETERS)
|
33
|
-
|
34
|
-
|
35
|
-
{ "\"#{attr_name}\"" => attribute.value.to_json }
|
36
|
+
{ "\"#{attr_name}\"" => erb_helper.convert(attribute) }
|
36
37
|
else
|
37
38
|
raise ConversionError, "Cannot convert attribute \"#{attr_name}\""
|
38
39
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "argument_mappers/conversion_error"
|
4
|
+
|
5
|
+
module ERBLint
|
6
|
+
module Linters
|
7
|
+
# Helper methods for autocorrectable ERB linters.
|
8
|
+
module Autocorrectable
|
9
|
+
def map_arguments(tag)
|
10
|
+
self.class::ARGUMENT_MAPPER.new(tag).to_s
|
11
|
+
rescue ArgumentMappers::ConversionError
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def correction(args)
|
16
|
+
return nil if args.nil?
|
17
|
+
|
18
|
+
correction = "<%= render #{self.class::COMPONENT}.new"
|
19
|
+
correction += "(#{args})" if args.present?
|
20
|
+
"#{correction} do %>"
|
21
|
+
end
|
22
|
+
|
23
|
+
def message(args, processed_source)
|
24
|
+
return self.class::MESSAGE if args.nil?
|
25
|
+
|
26
|
+
"#{self.class::MESSAGE}\nTry using:\n\n#{correction(args)}\n\nYou can also run erblint in autocorrect mode:\n\nbundle exec erblint -a #{processed_source.filename}\n"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "helpers"
|
4
|
+
require_relative "autocorrectable"
|
4
5
|
require_relative "argument_mappers/button"
|
5
6
|
|
6
7
|
module ERBLint
|
@@ -8,32 +9,17 @@ module ERBLint
|
|
8
9
|
# Counts the number of times a HTML button is used instead of the component.
|
9
10
|
class ButtonComponentMigrationCounter < Linter
|
10
11
|
include Helpers
|
12
|
+
include Autocorrectable
|
13
|
+
|
14
|
+
TAGS = Primer::ViewComponents::Constants.get(
|
15
|
+
component: "Primer::BaseButton",
|
16
|
+
constant: "TAG_OPTIONS"
|
17
|
+
).freeze
|
11
18
|
|
12
|
-
TAGS = %w[button summary a].freeze
|
13
19
|
CLASSES = %w[btn btn-link].freeze
|
14
20
|
MESSAGE = "We are migrating buttons to use [Primer::ButtonComponent](https://primer.style/view-components/components/button), please try to use that instead of raw HTML."
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
def map_arguments(tag)
|
19
|
-
ArgumentMappers::Button.new(tag).to_s
|
20
|
-
rescue ArgumentMappers::ConversionError
|
21
|
-
nil
|
22
|
-
end
|
23
|
-
|
24
|
-
def correction(args)
|
25
|
-
return nil if args.nil?
|
26
|
-
|
27
|
-
correction = "<%= render Primer::ButtonComponent.new"
|
28
|
-
correction += "(#{args})" if args.present?
|
29
|
-
"#{correction} do %>"
|
30
|
-
end
|
31
|
-
|
32
|
-
def message(args)
|
33
|
-
return MESSAGE if args.nil?
|
34
|
-
|
35
|
-
"#{MESSAGE}\n\nTry using:\n\n#{correction(args)}\n\nInstead of:\n"
|
36
|
-
end
|
21
|
+
ARGUMENT_MAPPER = ArgumentMappers::Button
|
22
|
+
COMPONENT = "Primer::ButtonComponent"
|
37
23
|
end
|
38
24
|
end
|
39
25
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "helpers"
|
4
|
+
require_relative "autocorrectable"
|
5
|
+
require_relative "argument_mappers/clipboard_copy"
|
6
|
+
|
7
|
+
module ERBLint
|
8
|
+
module Linters
|
9
|
+
# Counts the number of times a HTML clipboard-copy is used instead of the component.
|
10
|
+
class ClipboardCopyComponentMigrationCounter < Linter
|
11
|
+
include Helpers
|
12
|
+
include Autocorrectable
|
13
|
+
|
14
|
+
TAGS = %w[clipboard-copy].freeze
|
15
|
+
REQUIRED_ARGUMENTS = [/for|value/, "aria-label"].freeze
|
16
|
+
MESSAGE = "We are migrating clipboard-copy to use [Primer::ClipboardCopy](https://primer.style/view-components/components/clipboardcopy), please try to use that instead of raw HTML."
|
17
|
+
ARGUMENT_MAPPER = ArgumentMappers::ClipboardCopy
|
18
|
+
COMPONENT = "Primer::ClipboardCopy"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "helpers"
|
4
|
+
|
5
|
+
module ERBLint
|
6
|
+
module Linters
|
7
|
+
# Counts the number of times a HTML clipboard-copy is used instead of the component.
|
8
|
+
class CloseButtonComponentMigrationCounter < Linter
|
9
|
+
include Helpers
|
10
|
+
|
11
|
+
TAGS = %w[button].freeze
|
12
|
+
CLASSES = %w[close-button].freeze
|
13
|
+
MESSAGE = "We are migrating close-button to use [Primer::CloseButton](https://primer.style/view-components/components/closebutton), please try to use that instead of raw HTML."
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "json"
|
4
4
|
require "openssl"
|
5
|
+
require "primer/view_components/constants"
|
5
6
|
|
6
7
|
module ERBLint
|
7
8
|
module Linters
|
@@ -14,63 +15,67 @@ module ERBLint
|
|
14
15
|
].freeze
|
15
16
|
|
16
17
|
DUMP_FILE = ".erblint-counter-ignore.json"
|
18
|
+
CLASSES = [].freeze
|
19
|
+
REQUIRED_ARGUMENTS = [].freeze
|
17
20
|
|
18
21
|
def self.included(base)
|
19
22
|
base.include(ERBLint::LinterRegistry)
|
23
|
+
end
|
20
24
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
25
|
+
def run(processed_source)
|
26
|
+
@total_offenses = 0
|
27
|
+
@offenses_not_corrected = 0
|
28
|
+
tags = tags(processed_source)
|
29
|
+
tag_tree = build_tag_tree(tags)
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
31
|
+
tags.each do |tag|
|
32
|
+
next if tag.closing?
|
33
|
+
next unless self.class::TAGS&.include?(tag.name)
|
30
34
|
|
31
|
-
|
35
|
+
classes = tag.attributes["class"]&.value&.split(" ") || []
|
36
|
+
tag_tree[tag][:offense] = false
|
32
37
|
|
33
|
-
|
38
|
+
next unless self.class::CLASSES.blank? || (classes & self.class::CLASSES).any?
|
34
39
|
|
35
|
-
|
40
|
+
args = map_arguments(tag)
|
41
|
+
correction = correction(args)
|
36
42
|
|
37
|
-
|
38
|
-
|
43
|
+
attributes = tag.attributes.each.map(&:name).join(" ")
|
44
|
+
matches_required_attributes = self.class::REQUIRED_ARGUMENTS.blank? || self.class::REQUIRED_ARGUMENTS.all? { |arg| attributes.match?(arg) }
|
39
45
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
46
|
+
tag_tree[tag][:offense] = true
|
47
|
+
tag_tree[tag][:correctable] = matches_required_attributes && !correction.nil?
|
48
|
+
tag_tree[tag][:message] = message(args, processed_source)
|
49
|
+
tag_tree[tag][:correction] = correction
|
50
|
+
end
|
45
51
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
52
|
+
tag_tree.each do |tag, h|
|
53
|
+
next unless h[:offense]
|
54
|
+
|
55
|
+
@total_offenses += 1
|
56
|
+
# We always fix the offenses using blocks. The closing tag corresponds to `<% end %>`.
|
57
|
+
if h[:correctable]
|
58
|
+
add_offense(tag.loc, h[:message], h[:correction])
|
59
|
+
add_offense(h[:closing].loc, h[:message], "<% end %>")
|
60
|
+
else
|
61
|
+
@offenses_not_corrected += 1
|
62
|
+
generate_offense(self.class, processed_source, tag, h[:message])
|
58
63
|
end
|
64
|
+
end
|
59
65
|
|
60
|
-
|
66
|
+
counter_correct?(processed_source)
|
61
67
|
|
62
|
-
|
63
|
-
|
68
|
+
dump_data(processed_source) if ENV["DUMP_LINT_DATA"] == "1"
|
69
|
+
end
|
64
70
|
|
65
|
-
|
66
|
-
|
71
|
+
def autocorrect(processed_source, offense)
|
72
|
+
return unless offense.context
|
67
73
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
+
lambda do |corrector|
|
75
|
+
if offense.context.include?(counter_disable)
|
76
|
+
correct_counter(corrector, processed_source, offense)
|
77
|
+
else
|
78
|
+
corrector.replace(offense.source_range, offense.context)
|
74
79
|
end
|
75
80
|
end
|
76
81
|
end
|
@@ -96,7 +101,7 @@ module ERBLint
|
|
96
101
|
# Override this function to customize the linter message.
|
97
102
|
#
|
98
103
|
# @return [String] message to show on linter error.
|
99
|
-
def message(_tag)
|
104
|
+
def message(_tag, _processed_source)
|
100
105
|
self.class::MESSAGE
|
101
106
|
end
|
102
107
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "helpers"
|
4
|
+
require_relative "autocorrectable"
|
5
|
+
require_relative "argument_mappers/label"
|
6
|
+
|
7
|
+
module ERBLint
|
8
|
+
module Linters
|
9
|
+
# Counts the number of times a HTML label is used instead of the component.
|
10
|
+
class LabelComponentMigrationCounter < Linter
|
11
|
+
include Helpers
|
12
|
+
include Autocorrectable
|
13
|
+
|
14
|
+
TAGS = Primer::ViewComponents::Constants.get(
|
15
|
+
component: "Primer::LabelComponent",
|
16
|
+
constant: "TAG_OPTIONS"
|
17
|
+
).freeze
|
18
|
+
|
19
|
+
CLASSES = %w[Label].freeze
|
20
|
+
MESSAGE = "We are migrating labels to use [Primer::LabelComponent](https://primer.style/view-components/components/label), please try to use that instead of raw HTML."
|
21
|
+
ARGUMENT_MAPPER = ArgumentMappers::Label
|
22
|
+
COMPONENT = "Primer::LabelComponent"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/rubocop/cop/primer.rb
CHANGED
@@ -0,0 +1,173 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubocop"
|
4
|
+
require "primer/view_components/statuses"
|
5
|
+
require_relative "../../../../app/lib/primer/view_helper"
|
6
|
+
|
7
|
+
# :nocov:
|
8
|
+
module RuboCop
|
9
|
+
module Cop
|
10
|
+
module Primer
|
11
|
+
# This cop ensures that components don't use deprecated arguments
|
12
|
+
#
|
13
|
+
# bad
|
14
|
+
# Component.new(foo: :deprecated)
|
15
|
+
#
|
16
|
+
# good
|
17
|
+
# Component.new(foo: :bar)
|
18
|
+
class DeprecatedArguments < RuboCop::Cop::Cop
|
19
|
+
INVALID_MESSAGE = <<~STR
|
20
|
+
Avoid using deprecated arguments: https://primer.style/view-components/deprecated.
|
21
|
+
STR
|
22
|
+
|
23
|
+
# This is a hash of deprecated arguments and their replacements.
|
24
|
+
#
|
25
|
+
# * The top level key is the argument.
|
26
|
+
# * The second level key is the value.
|
27
|
+
# * The seceond level value is a string of the full replacement. e.g. "new_argument: :new_value"
|
28
|
+
# If the value is nil, then there is no replacement.
|
29
|
+
#
|
30
|
+
# e.g.
|
31
|
+
# DEPRECATED = {
|
32
|
+
# argument: {
|
33
|
+
# value: "new_argument: :new_value"
|
34
|
+
# }
|
35
|
+
# }
|
36
|
+
#
|
37
|
+
DEPRECATED = {
|
38
|
+
color: {
|
39
|
+
blue: "color: :text_link",
|
40
|
+
gray_dark: "color: :text_primary",
|
41
|
+
gray: "color: :text_secondary",
|
42
|
+
gray_light: "color: :text_tertiary",
|
43
|
+
green: "color: :text_success",
|
44
|
+
yellow: "color: :text_warning",
|
45
|
+
red: "color: :text_danger",
|
46
|
+
gray_0: nil,
|
47
|
+
gray_1: nil,
|
48
|
+
gray_2: nil,
|
49
|
+
gray_3: nil,
|
50
|
+
gray_4: nil,
|
51
|
+
gray_5: nil,
|
52
|
+
gray_6: nil,
|
53
|
+
gray_7: nil,
|
54
|
+
gray_8: nil,
|
55
|
+
gray_9: nil,
|
56
|
+
blue_0: nil,
|
57
|
+
blue_1: nil,
|
58
|
+
blue_2: nil,
|
59
|
+
blue_3: nil,
|
60
|
+
blue_4: nil,
|
61
|
+
blue_5: nil,
|
62
|
+
blue_6: nil,
|
63
|
+
blue_7: nil,
|
64
|
+
blue_8: nil,
|
65
|
+
blue_9: nil,
|
66
|
+
green_0: nil,
|
67
|
+
green_1: nil,
|
68
|
+
green_2: nil,
|
69
|
+
green_3: nil,
|
70
|
+
green_4: nil,
|
71
|
+
green_5: nil,
|
72
|
+
green_6: nil,
|
73
|
+
green_7: nil,
|
74
|
+
green_8: nil,
|
75
|
+
green_9: nil,
|
76
|
+
yellow_0: nil,
|
77
|
+
yellow_1: nil,
|
78
|
+
yellow_2: nil,
|
79
|
+
yellow_3: nil,
|
80
|
+
yellow_4: nil,
|
81
|
+
yellow_5: nil,
|
82
|
+
yellow_6: nil,
|
83
|
+
yellow_7: nil,
|
84
|
+
yellow_8: nil,
|
85
|
+
yellow_9: nil,
|
86
|
+
red_0: nil,
|
87
|
+
red_1: nil,
|
88
|
+
red_2: nil,
|
89
|
+
red_3: nil,
|
90
|
+
red_4: nil,
|
91
|
+
red_5: nil,
|
92
|
+
red_6: nil,
|
93
|
+
red_7: nil,
|
94
|
+
red_8: nil,
|
95
|
+
red_9: nil,
|
96
|
+
purple_0: nil,
|
97
|
+
purple_1: nil,
|
98
|
+
purple_2: nil,
|
99
|
+
purple_3: nil,
|
100
|
+
purple_4: nil,
|
101
|
+
purple_5: nil,
|
102
|
+
purple_6: nil,
|
103
|
+
purple_7: nil,
|
104
|
+
purple_8: nil,
|
105
|
+
purple_9: nil,
|
106
|
+
pink_0: nil,
|
107
|
+
pink_1: nil,
|
108
|
+
pink_2: nil,
|
109
|
+
pink_3: nil,
|
110
|
+
pink_4: nil,
|
111
|
+
pink_5: nil,
|
112
|
+
pink_6: nil,
|
113
|
+
pink_7: nil,
|
114
|
+
pink_8: nil,
|
115
|
+
pink_9: nil,
|
116
|
+
orange_0: nil,
|
117
|
+
orange_1: nil,
|
118
|
+
orange_2: nil,
|
119
|
+
orange_3: nil,
|
120
|
+
orange_4: nil,
|
121
|
+
orange_5: nil,
|
122
|
+
orange_6: nil,
|
123
|
+
orange_7: nil,
|
124
|
+
orange_8: nil,
|
125
|
+
orange_9: nil
|
126
|
+
}
|
127
|
+
}.freeze
|
128
|
+
|
129
|
+
def on_send(node)
|
130
|
+
return unless valid_node?(node)
|
131
|
+
return unless node.arguments?
|
132
|
+
|
133
|
+
# we are looking for hash arguments and they are always last
|
134
|
+
kwargs = node.arguments.last
|
135
|
+
|
136
|
+
return unless kwargs.type == :hash
|
137
|
+
|
138
|
+
kwargs.pairs.each do |pair|
|
139
|
+
# Skip if we're not dealing with a symbol
|
140
|
+
next if pair.key.type != :sym
|
141
|
+
next unless pair.value.type == :sym || pair.value.type == :str
|
142
|
+
|
143
|
+
key = pair.key.value
|
144
|
+
value = pair.value.value.to_sym
|
145
|
+
|
146
|
+
next unless DEPRECATED.key?(key) && DEPRECATED[key].key?(value)
|
147
|
+
|
148
|
+
add_offense(pair, message: INVALID_MESSAGE)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def autocorrect(node)
|
153
|
+
lambda do |corrector|
|
154
|
+
replacement = DEPRECATED[node.key.value][node.value.value.to_sym]
|
155
|
+
corrector.replace(node, replacement) if replacement.present?
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
# We only verify SystemArguments if it's a `.new` call on a component or
|
162
|
+
# a ViewHleper call.
|
163
|
+
def valid_node?(node)
|
164
|
+
view_helpers.include?(node.method_name) || (node.method_name == :new && ::Primer::ViewComponents::STATUSES.key?(node.receiver.const_name))
|
165
|
+
end
|
166
|
+
|
167
|
+
def view_helpers
|
168
|
+
::Primer::ViewHelper::HELPERS.keys.map { |key| "primer_#{key}".to_sym }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|