class ERBLint::Linters::CloseButtonComponentMigrationCounter

Counts the number of times a HTML clipboard-copy is used instead of the component.

Constants

ALLOWED_OCTICON_ARGS
ARGUMENT_MAPPER
CLASSES
COMPONENT
MESSAGE
TAGS

Private Instance Methods

add_correction(tag, tag_tree) click to toggle source

Overriding the basic correction since this component will rewrite the whole tag block.

# File lib/primer/view_components/linters/close_button_component_migration_counter.rb, line 83
def add_correction(tag, tag_tree)
  offense_loc = tag.loc.with(end_pos: tag_tree[:closing].loc.to_range.last)
  add_offense(offense_loc, tag_tree[:message], tag_tree[:correction])
end
aria_label_from_octicon(kwargs) click to toggle source

Extracts the aria-label value from the octicon kwargs. It can either be in `“aria-label”: “value”“ or `aria: { label: “value” } }`.

# File lib/primer/view_components/linters/close_button_component_migration_counter.rb, line 90
def aria_label_from_octicon(kwargs)
  return if kwargs.blank? || kwargs.type != :hash || kwargs.pairs.blank?

  aria_label = kwargs.pairs.find { |x| x.key.value == :"aria-label" }

  return aria_label.value.source if aria_label

  aria_hash = kwargs.pairs.find { |x| x.key.value == :aria }

  return if aria_hash.blank?

  aria_label = aria_hash.value.pairs.find { |x| x.key.value == :label }

  aria_label&.value&.source
end
correction(args) click to toggle source

Overriding the basic correction since this component does not uses content blocks.

# File lib/primer/view_components/linters/close_button_component_migration_counter.rb, line 74
def correction(args)
  return if args.nil?

  correction = "<%= render #{self.class::COMPONENT}.new"
  correction += "(#{args})" if args.present?
  "#{correction} %>"
end
custom_attributes?(kwargs) click to toggle source
# File lib/primer/view_components/linters/close_button_component_migration_counter.rb, line 106
def custom_attributes?(kwargs)
  return false if kwargs.blank? || kwargs.type != :hash || kwargs.pairs.blank?

  (kwargs.keys.map { |key| key.value.to_s } - ALLOWED_OCTICON_ARGS).present?
end
erb_ast(code) click to toggle source
# File lib/primer/view_components/linters/close_button_component_migration_counter.rb, line 112
def erb_ast(code)
  RuboCop::AST::ProcessedSource.new(code, RUBY_VERSION.to_f).ast
end
icon(args) click to toggle source
# File lib/primer/view_components/linters/close_button_component_migration_counter.rb, line 116
def icon(args)
  return args.first.value.to_sym if args.first.type == :sym || args.first.type == :str

  args.last.pairs.find { |x| x.key.value == :icon }.value.value.to_sym
end
map_arguments(tag, tag_tree) click to toggle source
# File lib/primer/view_components/linters/close_button_component_migration_counter.rb, line 23
def map_arguments(tag, tag_tree)
  # We can only autocorrect cases where the tag only has an octicon as content.
  return if tag_tree[:children].size != 1

  nodes = tag_tree[:children].first.children
  erb_nodes = nodes.select { |node| node.try(:type) == :erb }

  # Don't correct if there are multiple ERB nodes.
  return if erb_nodes.size != 1

  _, _, code_node = *erb_nodes.first
  code = code_node.children.first.strip
  ast = erb_ast(code)

  # We'll only autocorrect cases where the only content is an octicon.
  if ast.method_name == :primer_octicon || ast.method_name == :octicon
    octicon_kwargs = ast.arguments[1]
    icon = icon(ast.arguments)
  elsif ast.method_name == :render && code.include?("Primer::OcticonComponent")
    octicon_kwargs = ast.arguments.first.arguments.last
    icon = icon(ast.arguments.first.arguments)
  else
    return
  end

  # Don't autocorrect if using a custom icon
  return unless icon == :x
  # Don't autocorrect if the octicon has custom arguments
  return if custom_attributes?(octicon_kwargs)

  octicon_aria_label = aria_label_from_octicon(octicon_kwargs)
  tag_aria_label = tag.attributes.each.find { |a| a.name == "aria-label" }

  # Can't autocorrect if there is no aria-label.
  return if octicon_aria_label.blank? && tag_aria_label.blank?

  args = ARGUMENT_MAPPER.new(tag).to_s

  # Argument mapper will add the `aria-label` if the tag has it.
  return args if tag_aria_label.present?

  aria_label_arg = "\"aria-label\": #{octicon_aria_label}"

  return aria_label_arg if args.blank?

  "#{args}, #{aria_label_arg}"
rescue ArgumentMappers::ConversionError
  nil
end