gitlab-org--gitlab-foss/haml_lint/linter/no_plain_nodes.rb

91 lines
2.2 KiB
Ruby

# frozen_string_literal: true
require 'active_support/core_ext/array/grouping'
module HamlLint
class Linter
class NoPlainNodes < Linter
include ::HamlLint::LinterRegistry
def visit_tag(node)
if inline_plain_node?(node)
check_inline(node)
elsif !node.script.empty?
check_script(node)
else
check(node)
end
end
private
def check(node)
text_in_node(node).each { |string| record(node, string) }
end
def check_inline(node)
text = inline_text(node)
record(node, text) unless text.empty?
end
def check_script(node)
text = inline_text(node)
record(node, text) unless text.start_with?('=') || text.empty?
end
# Build an array of all strings in child text nodes.
# non text nodes are nil, where we'll split the sentences.
def text_in_node(node)
texts = node.children.map do |child|
child.text.strip if text_node?(child)
end
texts.split(nil).map { |sentence| sentence.join(' ') unless sentence.empty? }.compact
end
# Removes a node's attributes and tag from the source code,
# returning the inline text of a node.
def inline_text(node)
text = node.source_code.gsub("%#{node.tag_name}", '')
attributes = node.attributes_source.map(&:last)
attributes.each { |attribute| text = text.gsub(attribute, '') }
text = strip_html_entities(text)
text.strip
end
def record(node, string)
record_lint(node, message(string))
end
def message(string)
"`#{string}` is a plain node. Please use an i18n method like `#{fixed(string)}`"
end
def fixed(string)
"= _('#{string}')"
end
def inline_plain_node?(node)
node.children.empty? && node.script.empty?
end
def plain_node?(node)
node.is_a?(::HamlLint::Tree::PlainNode)
end
def text_node?(node)
return false unless plain_node?(node)
text = strip_html_entities(node.text)
!text.empty?
end
def strip_html_entities(text)
text.gsub(/&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});/i, "")
end
end
end
end