primer_view_components 0.0.61 → 0.0.65

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +746 -613
  3. data/app/components/primer/alpha/border_box/header.rb +1 -2
  4. data/app/components/primer/alpha/button_marketing.rb +4 -4
  5. data/app/components/primer/alpha/tab_nav.rb +1 -1
  6. data/app/components/primer/alpha/tab_panels.rb +2 -2
  7. data/app/components/primer/alpha/underline_nav.rb +2 -1
  8. data/app/components/primer/alpha/underline_panels.rb +2 -2
  9. data/app/components/primer/base_component.rb +8 -36
  10. data/app/components/primer/beta/auto_complete/item.rb +1 -1
  11. data/app/components/primer/beta/auto_complete.rb +4 -2
  12. data/app/components/primer/beta/avatar.rb +1 -1
  13. data/app/components/primer/beta/blankslate.html.erb +2 -2
  14. data/app/components/primer/beta/blankslate.rb +7 -6
  15. data/app/components/primer/beta/breadcrumbs.rb +2 -2
  16. data/app/components/primer/beta/text.rb +1 -1
  17. data/app/components/primer/border_box_component.rb +1 -1
  18. data/app/components/primer/box_component.rb +3 -2
  19. data/app/components/primer/button_component.html.erb +3 -9
  20. data/app/components/primer/button_component.rb +61 -28
  21. data/app/components/primer/button_group.rb +9 -15
  22. data/app/components/primer/clipboard_copy.rb +1 -1
  23. data/app/components/primer/close_button.rb +1 -1
  24. data/app/components/primer/component.rb +77 -0
  25. data/app/components/primer/counter_component.rb +1 -1
  26. data/app/components/primer/details_component.rb +1 -1
  27. data/app/components/primer/dropdown/menu.rb +1 -1
  28. data/app/components/primer/dropdown.html.erb +0 -1
  29. data/app/components/primer/dropdown.rb +2 -1
  30. data/app/components/primer/dropdown_menu_component.rb +1 -1
  31. data/app/components/primer/flash_component.rb +3 -2
  32. data/app/components/primer/flex_component.rb +16 -16
  33. data/app/components/primer/flex_item_component.rb +1 -1
  34. data/app/components/primer/hellip_button.rb +1 -1
  35. data/app/components/primer/hidden_text_expander.rb +1 -1
  36. data/app/components/primer/image.rb +3 -3
  37. data/app/components/primer/image_crop.rb +2 -1
  38. data/app/components/primer/label_component.rb +23 -13
  39. data/app/components/primer/layout_component.rb +1 -0
  40. data/app/components/primer/local_time.rb +1 -1
  41. data/app/components/primer/markdown.rb +1 -1
  42. data/app/components/primer/menu_component.rb +2 -1
  43. data/app/components/primer/navigation/tab_component.rb +1 -0
  44. data/app/components/primer/octicon_component.rb +4 -2
  45. data/app/components/primer/octicon_symbols_component.rb +2 -2
  46. data/app/components/primer/popover_component.rb +3 -3
  47. data/app/components/primer/progress_bar_component.rb +7 -6
  48. data/app/components/primer/spinner_component.html.erb +4 -7
  49. data/app/components/primer/spinner_component.rb +1 -1
  50. data/app/components/primer/subhead_component.rb +3 -1
  51. data/app/components/primer/tab_container_component.rb +1 -1
  52. data/app/components/primer/time_ago_component.rb +1 -1
  53. data/app/components/primer/timeline_item_component.rb +4 -3
  54. data/app/components/primer/tooltip.rb +1 -0
  55. data/app/lib/primer/octicon/cache.rb +4 -10
  56. data/lib/primer/classify/utilities.rb +17 -44
  57. data/lib/primer/classify/utilities.yml +298 -68
  58. data/lib/primer/classify.rb +92 -178
  59. data/lib/primer/view_components/engine.rb +1 -0
  60. data/lib/primer/view_components/linters/argument_mappers/button.rb +4 -4
  61. data/lib/primer/view_components/linters/blankslate_api_migration.rb +11 -5
  62. data/lib/primer/view_components/version.rb +1 -1
  63. data/lib/rubocop/cop/primer/deprecated_arguments.rb +1 -1
  64. data/lib/rubocop/cop/primer/deprecated_button_arguments.rb +51 -0
  65. data/lib/rubocop/cop/primer/deprecated_label_schemes.rb +68 -0
  66. data/lib/rubocop/cop/primer/deprecated_layout_component.rb +30 -0
  67. data/lib/rubocop/cop/primer/primer_octicon.rb +1 -3
  68. data/lib/tasks/custom_utilities.yml +298 -0
  69. data/lib/tasks/docs.rake +1 -1
  70. data/lib/tasks/utilities.rake +21 -4
  71. data/static/arguments.yml +16 -7
  72. data/static/classes.yml +19 -18
  73. data/static/constants.json +25 -15
  74. metadata +10 -12
  75. data/app/components/primer/auto_complete/auto_complete.d.ts +0 -1
  76. data/app/components/primer/auto_complete/auto_complete.js +0 -1
  77. data/app/components/primer/auto_complete/auto_component.d.ts +0 -1
  78. data/app/components/primer/auto_complete/auto_component.js +0 -1
  79. data/lib/primer/classify/cache.rb +0 -109
  80. data/lib/primer/classify/flex.rb +0 -111
@@ -1,221 +1,135 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "classify/cache"
4
- require_relative "classify/flex"
5
3
  require_relative "classify/utilities"
6
4
  require_relative "classify/validation"
7
5
 
8
6
  module Primer
9
7
  # :nodoc:
10
8
  class Classify
11
- # Keys where we can simply translate { key: value } into ".key-value"
12
- CONCAT_KEYS = %i[text box_shadow].freeze
13
-
14
- TEXT_KEYS = %i[font_family font_style font_weight text_align text_transform].freeze
15
- BOX_SHADOW_KEY = :box_shadow
16
-
17
- BREAKPOINTS = ["", "-sm", "-md", "-lg", "-xl"].freeze
18
-
19
- BOOLEAN_MAPPINGS = {
20
- underline: {
21
- mappings: [
22
- {
23
- value: true,
24
- css_class: "text-underline"
25
- },
26
- {
27
- value: false,
28
- css_class: "no-underline"
29
- }
30
- ]
31
- },
32
- top: {
33
- mappings: [
34
- {
35
- value: false,
36
- css_class: "top-0"
37
- }
38
- ]
39
- },
40
- bottom: {
41
- mappings: [
42
- {
43
- value: false,
44
- css_class: "bottom-0"
45
- }
46
- ]
47
- },
48
- left: {
49
- mappings: [
50
- {
51
- value: false,
52
- css_class: "left-0"
53
- }
54
- ]
55
- },
56
- right: {
57
- mappings: [
58
- {
59
- value: false,
60
- css_class: "right-0"
61
- }
62
- ]
63
- }
9
+ FLEX_VALUES = [1, :auto].freeze
10
+
11
+ FLEX_WRAP_MAPPINGS = {
12
+ wrap: "flex-wrap",
13
+ nowrap: "flex-nowrap",
14
+ reverse: "flex-wrap-reverse"
64
15
  }.freeze
65
- BORDER_KEY = :border
66
- BORDER_MARGIN_KEYS = %i[border_top border_bottom border_left border_right].freeze
67
- BORDER_RADIUS_KEY = :border_radius
68
- TYPOGRAPHY_KEYS = [:font_size].freeze
69
- VALID_KEYS = (
70
- Primer::Classify::Utilities::UTILITIES.keys +
71
- CONCAT_KEYS +
72
- BOOLEAN_MAPPINGS.keys +
73
- BORDER_MARGIN_KEYS +
74
- TYPOGRAPHY_KEYS +
75
- TEXT_KEYS +
76
- Primer::Classify::Flex::KEYS +
77
- [
78
- BORDER_KEY,
79
- BORDER_RADIUS_KEY,
80
- BOX_SHADOW_KEY
81
- ]
82
- ).freeze
83
16
 
84
- class << self
85
- def call(classes: "", style: nil, **args)
86
- extract_css_attrs(args).tap do |extracted_results|
87
- classes = +"#{validated_class_names(classes)} #{extracted_results[:class]}"
88
- classes.strip!
89
- extracted_results[:class] = presence(classes)
90
-
91
- styles = "#{extracted_results[:style]}#{style}"
92
- extracted_results[:style] = presence(styles)
93
- end
94
- end
17
+ FLEX_ALIGN_SELF_VALUES = [:auto, :start, :end, :center, :baseline, :stretch].freeze
95
18
 
96
- private
19
+ FLEX_DIRECTION_VALUES = [:column, :column_reverse, :row, :row_reverse].freeze
97
20
 
98
- # do this instead of using Rails' presence/blank?, which are a lot slower
99
- def presence(obj)
100
- # rubocop:disable Rails/Blank
101
- !obj || obj.empty? ? nil : obj
102
- # rubocop:enable Rails/Blank
103
- end
21
+ FLEX_JUSTIFY_CONTENT_VALUES = [:flex_start, :flex_end, :center, :space_between, :space_around].freeze
104
22
 
105
- def validated_class_names(classes)
106
- return if classes.blank?
23
+ FLEX_ALIGN_ITEMS_VALUES = [:flex_start, :flex_end, :center, :baseline, :stretch].freeze
107
24
 
108
- if raise_on_invalid_options? && !ENV["PRIMER_WARNINGS_DISABLED"]
109
- invalid_class_names =
110
- classes.split.each_with_object([]) do |class_name, memo|
111
- memo << class_name if Primer::Classify::Validation.invalid?(class_name)
112
- end
25
+ LOOKUP = Primer::Classify::Utilities::UTILITIES
113
26
 
114
- if invalid_class_names.any?
115
- raise ArgumentError, "Use System Arguments (https://primer.style/view-components/system-arguments) "\
116
- "instead of Primer CSS class #{'name'.pluralize(invalid_class_names.length)} #{invalid_class_names.to_sentence}. "\
117
- "This warning will not be raised in production. Set PRIMER_WARNINGS_DISABLED=1 to disable this warning."
118
- end
119
- end
120
-
121
- classes
122
- end
123
-
124
- # NOTE: This is a fairly naive implementation that we're building as we go.
125
- # Feel free to refactor as this is thoroughly tested.
27
+ class << self
28
+ # Utility for mapping component configuration into Primer CSS class names.
126
29
  #
127
- # Utility for mapping component configuration into Primer CSS class names
30
+ # **args can contain utility keys that mimic the interface used by
31
+ # https://github.com/primer/components, as well as the special entries :classes
32
+ # and :style.
128
33
  #
129
- # styles_hash - A hash with utility keys that mimic the interface used by https://github.com/primer/components
34
+ # Returns a hash containing two entries. The :classes entry is a string of
35
+ # Primer CSS class names, including any classes given in the :classes entry
36
+ # in **args. The :style entry is the value of the given :style entry given in
37
+ # **args.
130
38
  #
131
- # Returns a string of Primer CSS class names and style attributes to be added to an HTML tag.
132
39
  #
133
40
  # Example usage:
134
- # extract_css_attrs({ mt: 4, py: 2 }) => "mt-4 py-2"
135
- def extract_css_attrs(styles_hash)
136
- classes = []
137
- styles = +""
138
-
139
- styles_hash.each do |key, value|
140
- if value.is_a?(Array)
141
- raise ArgumentError, "#{key} does not support responsive values" unless Primer::Classify::Flex::RESPONSIVE_KEYS.include?(key) || Primer::Classify::Utilities.supported_key?(key)
41
+ # extract_css_attrs({ mt: 4, py: 2 }) => { classes: "mt-4 py-2", style: nil }
42
+ # extract_css_attrs(classes: "d-flex", mt: 4, py: 2) => { classes: "d-flex mt-4 py-2", style: nil }
43
+ # extract_css_attrs(classes: "d-flex", style: "float: left", mt: 4, py: 2) => { classes: "d-flex mt-4 py-2", style: "float: left" }
44
+ #
45
+ def call(args = {})
46
+ style = nil
47
+ classes = [].tap do |result|
48
+ args.each do |key, val|
49
+ case key
50
+ when :classes
51
+ # insert :classes first to avoid huge doc diffs
52
+ if (class_names = validated_class_names(val))
53
+ result.unshift(class_names)
54
+ end
55
+ next
56
+ when :style
57
+ style = val
58
+ next
59
+ end
142
60
 
143
- value.each_with_index do |val, index|
144
- extract_one_css_attr(classes, styles, key, val, BREAKPOINTS[index])
61
+ next unless LOOKUP[key]
62
+
63
+ if val.is_a?(Array)
64
+ # A while loop is ~3.5x faster than Array#each.
65
+ brk = 0
66
+ while brk < val.size
67
+ item = val[brk]
68
+
69
+ if item.nil?
70
+ brk += 1
71
+ next
72
+ end
73
+
74
+ # Believe it or not, three calls to Hash#[] and an inline rescue
75
+ # are about 30% faster than Hash#dig. It also ensures validate is
76
+ # only called when necessary, i.e. when the class can't be found
77
+ # in the lookup table.
78
+ # rubocop:disable Style/RescueModifier
79
+ found = (LOOKUP[key][item][brk] rescue nil) || validate(key, item, brk)
80
+ # rubocop:enable Style/RescueModifier
81
+ result << found if found
82
+ brk += 1
83
+ end
84
+ else
85
+ next if val.nil?
86
+
87
+ # rubocop:disable Style/RescueModifier
88
+ found = (LOOKUP[key][val][0] rescue nil) || validate(key, val, 0)
89
+ # rubocop:enable Style/RescueModifier
90
+ result << found if found
145
91
  end
146
- else
147
- extract_one_css_attr(classes, styles, key, value, BREAKPOINTS[0])
148
92
  end
149
- end
93
+ end.join(" ")
150
94
 
95
+ # This is much faster than Rails' presence method.
96
+ # rubocop:disable Rails/Blank
151
97
  {
152
- class: classes.join(" "),
153
- style: styles
98
+ class: !classes || classes.empty? ? nil : classes,
99
+ style: !style || style.empty? ? nil : style
154
100
  }
101
+ # rubocop:enable Rails/Blank
155
102
  end
156
103
 
157
- def extract_one_css_attr(classes, styles, key, val, breakpoint)
158
- found_classes = Primer::Classify::Cache.instance.fetch(breakpoint, key, val) do
159
- classes_from(key, val, breakpoint)
160
- end
161
-
162
- classes << found_classes if found_classes
104
+ private
163
105
 
164
- found_styles = styles_from(key, val, breakpoint)
165
- styles << found_styles if found_styles
106
+ def validate(key, val, brk)
107
+ brk_str = Primer::Classify::Utilities::BREAKPOINTS[brk]
108
+ Primer::Classify::Utilities.validate(key, val, brk_str)
166
109
  end
167
110
 
168
- def styles_from(key, val, _breakpoint)
169
- # Turn this into an if/else like classes_from when we have more branches.
170
- # Could be that way now, but it makes Rubocop unhappy.
171
- end
111
+ def validated_class_names(classes)
112
+ return if classes.blank?
172
113
 
173
- def classes_from(key, val, breakpoint)
174
- return if val.nil? || val == ""
114
+ if raise_on_invalid_options? && !ENV["PRIMER_WARNINGS_DISABLED"]
115
+ invalid_class_names =
116
+ classes.split.each_with_object([]) do |class_name, memo|
117
+ memo << class_name if Primer::Classify::Validation.invalid?(class_name)
118
+ end
175
119
 
176
- if Primer::Classify::Utilities.supported_key?(key)
177
- Primer::Classify::Utilities.classname(key, val, breakpoint)
178
- elsif BOOLEAN_MAPPINGS.key?(key)
179
- bools = BOOLEAN_MAPPINGS[key][:mappings].each_with_object([]) do |m, memo|
180
- memo << m[:css_class] if m[:value] == val && m[:css_class].present?
181
- end
182
- bools.empty? ? nil : bools.join(" ")
183
- elsif key == BORDER_KEY
184
- if val == true
185
- "border"
186
- else
187
- "border-#{val.to_s.dasherize}"
188
- end
189
- elsif BORDER_MARGIN_KEYS.include?(key)
190
- "#{key.to_s.dasherize}-#{val}"
191
- elsif key == BORDER_RADIUS_KEY
192
- "rounded-#{val}"
193
- elsif Primer::Classify::Flex::KEYS.include?(key)
194
- Primer::Classify::Flex.classes(key, val, breakpoint)
195
- elsif TEXT_KEYS.include?(key)
196
- "text-#{val.to_s.dasherize}"
197
- elsif TYPOGRAPHY_KEYS.include?(key)
198
- if val == :small || val == :normal
199
- "text-#{val.to_s.dasherize}"
200
- else
201
- "f#{val.to_s.dasherize}"
202
- end
203
- elsif key == BOX_SHADOW_KEY
204
- if val == true
205
- "color-shadow-small"
206
- elsif val == :none || val.blank?
207
- "box-shadow-none"
208
- else
209
- "color-shadow-#{val.to_s.dasherize}"
120
+ if invalid_class_names.any?
121
+ raise ArgumentError, "Use System Arguments (https://primer.style/view-components/system-arguments) "\
122
+ "instead of Primer CSS class #{'name'.pluralize(invalid_class_names.length)} #{invalid_class_names.to_sentence}. "\
123
+ "This warning will not be raised in production. Set PRIMER_WARNINGS_DISABLED=1 to disable this warning."
210
124
  end
211
125
  end
126
+
127
+ classes
212
128
  end
213
129
 
214
130
  def raise_on_invalid_options?
215
131
  Rails.application.config.primer_view_components.raise_on_invalid_options
216
132
  end
217
133
  end
218
-
219
- Cache.instance.preload!
220
134
  end
221
135
  end
@@ -18,6 +18,7 @@ module Primer
18
18
  config.primer_view_components.raise_on_invalid_options = false
19
19
  config.primer_view_components.silence_deprecations = false
20
20
  config.primer_view_components.validate_class_names = !Rails.env.production?
21
+ config.primer_view_components.raise_on_invalid_aria = false
21
22
 
22
23
  initializer "primer_view_components.assets" do |app|
23
24
  app.config.assets.precompile += %w[primer_view_components] if app.config.respond_to?(:assets)
@@ -13,9 +13,9 @@ module ERBLint
13
13
  symbolize: true
14
14
  ).freeze
15
15
 
16
- VARIANT_MAPPINGS = Primer::ViewComponents::Constants.get(
16
+ SIZE_MAPPINGS = Primer::ViewComponents::Constants.get(
17
17
  component: "Primer::ButtonComponent",
18
- constant: "VARIANT_MAPPINGS",
18
+ constant: "SIZE_MAPPINGS",
19
19
  symbolize: true
20
20
  ).freeze
21
21
 
@@ -55,8 +55,8 @@ module ERBLint
55
55
 
56
56
  if SCHEME_MAPPINGS[class_name] && acc[:scheme].nil?
57
57
  acc[:scheme] = SCHEME_MAPPINGS[class_name]
58
- elsif VARIANT_MAPPINGS[class_name] && acc[:variant].nil?
59
- acc[:variant] = VARIANT_MAPPINGS[class_name]
58
+ elsif SIZE_MAPPINGS[class_name] && acc[:size].nil?
59
+ acc[:size] = SIZE_MAPPINGS[class_name]
60
60
  elsif class_name == "btn-block"
61
61
  acc[:block] = true
62
62
  elsif class_name == "BtnGroup-item"
@@ -17,7 +17,7 @@ module ERBLint
17
17
 
18
18
  next unless code.include?("Primer::BlankslateComponent")
19
19
  # Don't fix custom blankslates
20
- next if code.end_with?("do")
20
+ next if code.end_with?("do", "|")
21
21
 
22
22
  line = erb_node.loc.source_line
23
23
  indent = line.split("<%=").first.size
@@ -61,7 +61,7 @@ module ERBLint
61
61
 
62
62
  case pair.key.value.to_sym
63
63
  when :title
64
- new_blankslate[:slots][:heading][:content] = pair.value.value
64
+ new_blankslate[:slots][:heading][:content] = extract_value(pair.value)
65
65
  when :title_tag
66
66
  new_blankslate[:slots][:heading][:tag] = source_value
67
67
  when :icon
@@ -73,15 +73,15 @@ module ERBLint
73
73
  when :image_alt
74
74
  new_blankslate[:slots][:visual_image][:alt] = source_value
75
75
  when :description
76
- new_blankslate[:slots][:description][:content] = pair.value.value
76
+ new_blankslate[:slots][:description][:content] = extract_value(pair.value)
77
77
  when :button_text
78
- new_blankslate[:slots][:primary_action][:content] = pair.value.value
78
+ new_blankslate[:slots][:primary_action][:content] = extract_value(pair.value)
79
79
  when :button_url
80
80
  new_blankslate[:slots][:primary_action][:href] = source_value
81
81
  when :button_classes
82
82
  new_blankslate[:slots][:primary_action][:classes] = source_value
83
83
  when :link_text
84
- new_blankslate[:slots][:secondary_action][:content] = pair.value.value
84
+ new_blankslate[:slots][:secondary_action][:content] = extract_value(pair.value)
85
85
  when :link_url
86
86
  new_blankslate[:slots][:secondary_action][:href] = source_value
87
87
  when :large
@@ -141,6 +141,12 @@ module ERBLint
141
141
 
142
142
  "(#{string_args})"
143
143
  end
144
+
145
+ def extract_value(value)
146
+ return value.value if value.type == :str
147
+
148
+ "<%= #{value.source} %>"
149
+ end
144
150
  end
145
151
  end
146
152
  end
@@ -5,7 +5,7 @@ module Primer
5
5
  module VERSION
6
6
  MAJOR = 0
7
7
  MINOR = 0
8
- PATCH = 61
8
+ PATCH = 65
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH].join(".")
11
11
  end
@@ -22,7 +22,7 @@ module RuboCop
22
22
  #
23
23
  # * The top level key is the argument.
24
24
  # * The second level key is the value.
25
- # * The seceond level value is a string of the full replacement. e.g. "new_argument: :new_value"
25
+ # * The second level value is a string of the full replacement. e.g. "new_argument: :new_value"
26
26
  # If the value is nil, then there is no replacement.
27
27
  #
28
28
  # e.g.
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ # :nocov:
6
+ module RuboCop
7
+ module Cop
8
+ module Primer
9
+ # This cop ensures that `ButtonComponent` doesn't use deprecated arguments.
10
+ #
11
+ # bad
12
+ # ButtonComponent.new(variant: :small)
13
+ #
14
+ # good
15
+ # ButtonComponent.new(size: :small)
16
+ class DeprecatedButtonArguments < BaseCop
17
+ INVALID_MESSAGE = <<~STR
18
+ `variant` is deprecated. Use `size` instead.
19
+ STR
20
+
21
+ def_node_matcher :button_component?, <<~PATTERN
22
+ (send (const (const nil? :Primer) :ButtonComponent) :new ...)
23
+ PATTERN
24
+
25
+ DEPRECATIONS = {
26
+ variant: :size
27
+ }.freeze
28
+
29
+ def on_send(node)
30
+ return unless button_component?(node)
31
+
32
+ kwargs = node.arguments.last
33
+
34
+ return if kwargs.nil?
35
+
36
+ pair = kwargs.pairs.find { |x| x.key.value == :variant }
37
+
38
+ return if pair.nil?
39
+
40
+ add_offense(pair.key, message: INVALID_MESSAGE)
41
+ end
42
+
43
+ def autocorrect(node)
44
+ lambda do |corrector|
45
+ corrector.replace(node, DEPRECATIONS[node.value])
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ # :nocov:
6
+ module RuboCop
7
+ module Cop
8
+ module Primer
9
+ # This cop ensures that components don't use deprecated `Label` schemes.
10
+ #
11
+ # bad
12
+ # Primer::LabelComponent.new(scheme: :info)
13
+ #
14
+ # good
15
+ # Primer::LabelComponent.new(scheme: :accent)
16
+ class DeprecatedLabelSchemes < BaseCop
17
+ INVALID_MESSAGE = <<~STR
18
+ Avoid using deprecated schemes: https://primer.style/view-components/deprecated#labelcomponent.
19
+ STR
20
+
21
+ # This is a hash of deprecated schemes and their replacements.
22
+ DEPRECATIONS = {
23
+ info: ":accent",
24
+ warning: ":attention",
25
+ orange: ":severe",
26
+ purple: ":done"
27
+ }.freeze
28
+
29
+ def on_send(node)
30
+ return unless label_node?(node)
31
+ return unless node.arguments?
32
+
33
+ # we are looking for hash arguments and they are always last
34
+ kwargs = node.arguments.last
35
+
36
+ return unless kwargs.type == :hash
37
+
38
+ kwargs.pairs.each do |pair|
39
+ # Skip if we're not dealing with a symbol
40
+ next if pair.key.type != :sym
41
+ next unless pair.value.type == :sym || pair.value.type == :str
42
+
43
+ value = pair.value.value.to_sym
44
+
45
+ next unless DEPRECATIONS.key?(value)
46
+
47
+ add_offense(pair.value, message: INVALID_MESSAGE)
48
+ end
49
+ end
50
+
51
+ def autocorrect(node)
52
+ lambda do |corrector|
53
+ replacement = DEPRECATIONS[node.value.to_sym]
54
+ corrector.replace(node, replacement)
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def label_node?(node)
61
+ return if node.nil?
62
+
63
+ node.method_name == :new && !node.receiver.nil? && node.receiver.const_name == "Primer::LabelComponent"
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module Primer
8
+ # This cop ensures that the deprecated `Primer::LayoutComponent` isn't used.
9
+ #
10
+ # bad
11
+ # Primer::LayoutComponent.new(foo: :deprecated)
12
+ #
13
+ # good
14
+ # Primer::Alpha::Layout.new(foo: :deprecated)
15
+ class DeprecatedLayoutComponent < BaseCop
16
+ MSG = "Please try Primer::Alpha::Layout instead."
17
+
18
+ def_node_matcher :legacy_component?, <<~PATTERN
19
+ (send (const (const nil? :Primer) :LayoutComponent) :new ...)
20
+ PATTERN
21
+
22
+ def on_send(node)
23
+ return unless legacy_component?(node)
24
+
25
+ add_offense(node, message: MSG)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -163,9 +163,7 @@ module RuboCop
163
163
 
164
164
  color = case args[:color]
165
165
  when :text_white
166
- :text_white
167
- when :text_link
168
- :icon_info
166
+ :on_emphasis
169
167
  when Symbol
170
168
  args[:color].to_s.gsub("text_", "icon_").to_sym
171
169
  end