From 95afdfaeeb301699df3bbac0fde9cad0dda4d5f1 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Tue, 23 Apr 2019 20:04:11 +0100 Subject: Add HamlLint::Linter::NoPlainNodes linter Add a simple haml_lint linter to report all plain nodes. "Plain nodes" in HAML are scritpless plaintext leaf nodes. Add haml-lint_todo to onboard new haml linters. Excludes existing NoPlainNodes lints. --- lib/haml_lint/linter/no_plain_nodes.rb | 84 ++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 lib/haml_lint/linter/no_plain_nodes.rb (limited to 'lib') diff --git a/lib/haml_lint/linter/no_plain_nodes.rb b/lib/haml_lint/linter/no_plain_nodes.rb new file mode 100644 index 00000000000..d5cea0d07cf --- /dev/null +++ b/lib/haml_lint/linter/no_plain_nodes.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +require 'active_support/core_ext/array/grouping' + +module HamlLint + class Linter + class NoPlainNodes < Linter + include 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 + 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) + + !node.text.empty? + end + end + end +end -- cgit v1.2.3