Module: ERBLint::Linters::CustomHelpers

Constant Summary collapse

INTERACTIVE_ELEMENTS =
%w[button summary input select textarea a].freeze

Instance Method Summary collapse

Instance Method Details

#basic_conditional_code_check(code) ⇒ Object

Map possible values from condition



64
65
66
67
# File 'lib/erblint-github/linters/custom_helpers.rb', line 64

def basic_conditional_code_check(code)
  conditional_match = code.match(/["'](.+)["']\sif|unless\s.+/) || code.match(/.+\s?\s["'](.+)["']\s:\s["'](.+)["']/)
  [conditional_match[1], conditional_match[2]].compact if conditional_match
end

#counter_correct?(processed_source) ⇒ Boolean



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/erblint-github/linters/custom_helpers.rb', line 30

def counter_correct?(processed_source)
  comment_node = nil
  expected_count = 0
  rule_name = self.class.name.gsub("ERBLint::Linters::", "")
  offenses_count = @offenses.length

  processed_source.parser.ast.descendants(:erb).each do |node|
    indicator_node, _, code_node, = *node
    indicator = indicator_node&.loc&.source
    comment = code_node&.loc&.source&.strip

    if indicator == "#" && comment.start_with?("erblint:counter") && comment.match(rule_name)
      comment_node = node
      expected_count = comment.match(/\s(\d+)\s?$/)[1].to_i
    end
  end

  if offenses_count.zero?
    # have to adjust to get `\n` so we delete the whole line
    add_offense(processed_source.to_source_range(comment_node.loc.adjust(end_pos: 1)), "Unused erblint:counter comment for #{rule_name}", "") if comment_node
    return false
  end

  first_offense = @offenses[0]

  if comment_node.nil?
    add_offense(processed_source.to_source_range(first_offense.source_range), "#{rule_name}: If you must, add <%# erblint:counter #{rule_name} #{offenses_count} %> to bypass this check.", "<%# erblint:counter #{rule_name} #{offenses_count} %>")
  else
    clear_offenses
    add_offense(processed_source.to_source_range(comment_node.loc), "Incorrect erblint:counter number for #{rule_name}. Expected: #{expected_count}, actual: #{offenses_count}.", "<%# erblint:counter #{rule_name} #{offenses_count} %>") if expected_count != offenses_count
  end
end

#focusable?(tag) ⇒ Boolean



77
78
79
80
81
82
83
84
# File 'lib/erblint-github/linters/custom_helpers.rb', line 77

def focusable?(tag)
  tabindex = possible_attribute_values(tag, "tabindex")
  if INTERACTIVE_ELEMENTS.include?(tag.name)
    tabindex.empty? || tabindex.first.to_i >= 0
  else
    tabindex.any? && tabindex.first.to_i >= 0
  end
end

#generate_offense(klass, processed_source, tag, message = nil, replacement = nil) ⇒ Object



11
12
13
14
15
16
# File 'lib/erblint-github/linters/custom_helpers.rb', line 11

def generate_offense(klass, processed_source, tag, message = nil, replacement = nil)
  message ||= klass::MESSAGE
  message += "\nLearn more at https://github.com/github/erblint-github#rules.\n"
  offense = ["#{simple_class_name}:#{message}", tag.node.loc.source].join("\n")
  add_offense(processed_source.to_source_range(tag.loc), offense, replacement)
end

#generate_offense_from_source_range(klass, source_range, message = nil, replacement = nil) ⇒ Object



18
19
20
21
22
23
# File 'lib/erblint-github/linters/custom_helpers.rb', line 18

def generate_offense_from_source_range(klass, source_range, message = nil, replacement = nil)
  message ||= klass::MESSAGE
  message += "\nLearn more at https://github.com/github/erblint-github#rules.\n"
  offense = ["#{simple_class_name}:#{message}", source_range.source].join("\n")
  add_offense(source_range, offense, replacement)
end

#possible_attribute_values(tag, attr_name) ⇒ Object



25
26
27
28
# File 'lib/erblint-github/linters/custom_helpers.rb', line 25

def possible_attribute_values(tag, attr_name)
  value = tag.attributes[attr_name]&.value || nil
  [value].compact
end

#simple_class_nameObject



73
74
75
# File 'lib/erblint-github/linters/custom_helpers.rb', line 73

def simple_class_name
  self.class.name.gsub("ERBLint::Linters::", "")
end

#tags(processed_source) ⇒ Object



69
70
71
# File 'lib/erblint-github/linters/custom_helpers.rb', line 69

def tags(processed_source)
  processed_source.parser.nodes_with_type(:tag).map { |tag_node| BetterHtml::Tree::Tag.from_node(tag_node) }
end