#!/usr/bin/env ruby # frozen_string_literal: true require "rubygems" require "bundler/setup" require "find" require "haml" error_count = 0 warning_count = 0 # Patterns that compile but produce wrong HTML in Haml 7. # e.g. `.text-base-content\\/60` creates class "text-base-content" with text "\/60" # instead of class "text-base-content/60". Use {class: "..."} attribute hashes. SUSPECT_CLASS_PATTERNS = [ %r{^\s*[%.]\S*\\/}, # escaped slash in dot-notation: .foo\/bar /^\s*[%.]\S*\\:/, # escaped colon in dot-notation: .hover\:bg-red ].freeze Find.find(File.expand_path("../../app/views", __dir__)) do |path| next unless path.end_with?(".haml") source = File.read(path) # --- Errors --- begin compiled = Haml::Engine.new.call(source) # Check for Ruby syntax errors in the compiled code # Wrapping in a `def` so `yield` and `return` in templates don't trigger syntax errors. RubyVM::InstructionSequence.compile("def _haml_compilation_test\n#{compiled}\nend\n") rescue Haml::SyntaxError => e $stderr.puts "\nFile: #{path}" $stderr.puts e.message error_count += 1 next rescue SyntaxError => e $stderr.puts "\nFile: #{path}" $stderr.puts "Ruby syntax error in compiled Haml:" $stderr.puts e.message error_count += 1 next end # Haml 7 defers certain errors (e.g. illegal nesting) into the compiled # Ruby source as `raise Haml::SyntaxError.new(...)` instead of failing at # parse time. Detect those deferred errors by scanning the output. if compiled.include?("Haml::SyntaxError") if (match = compiled.match(/Haml::SyntaxError\.new\(%q\[(.+?)\]/)) message = match[1] end if (line_match = compiled.match(/Haml::SyntaxError\.new\(%q\[.+?\],\s*(\d+)\)/)) line = line_match[1] end $stderr.puts "\nFile: #{path}#{line ? ":#{line}" : ""}" $stderr.puts message || "Deferred Haml::SyntaxError detected in compiled output" error_count += 1 end # --- Recommendations --- # Detect escaped class patterns that compile but produce incorrect HTML. source.each_line.with_index(1) do |line, lineno| SUSPECT_CLASS_PATTERNS.each do |pattern| next unless line.match?(pattern) $stderr.puts "\n[warning] File: #{path}:#{lineno}" $stderr.puts " Escaped class in dot-notation produces incorrect HTML in Haml 7." $stderr.puts " Use {class: \"...\"} attribute hash instead." $stderr.puts " > #{line.strip}" warning_count += 1 end end end if warning_count > 0 $stderr.puts "\n#{warning_count} warning(s) found (do not cause build failure)" end exit(error_count.zero? ? 0 : 1)