lib/erb/formatter.rb in erb-formatter-0.6.0 vs lib/erb/formatter.rb in erb-formatter-0.7.0

- old
+ new

@@ -46,14 +46,21 @@ HTML_TAG_OPEN = %r{<(#{TAG_NAME})((?:#{HTML_ATTR})*)(\s*?)(/>|>)}m HTML_TAG_CLOSE = %r{</\s*(#{TAG_NAME})\s*>} SELF_CLOSING_TAG = /\A(area|base|br|col|command|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)\z/i - RUBY_OPEN_BLOCK = ->(code) do - # is nil when the parsing is broken, meaning it's an open expression - Ripper.sexp(code).nil? - end.freeze + begin + require 'prism' # ruby 3.3 + RUBY_OPEN_BLOCK = Prism.method(:parse_failure?) + rescue LoadError + require 'ripper' + RUBY_OPEN_BLOCK = ->(code) do + # is nil when the parsing is broken, meaning it's an open expression + Ripper.sexp(code).nil? + end.freeze + end + RUBY_CLOSE_BLOCK = /\Aend\z/ RUBY_REOPEN_BLOCK = /\A(else|elsif\b(.*)|when\b(.*))\z/ RUBOCOP_STDIN_MARKER = "====================" @@ -66,18 +73,19 @@ def self.format(source, filename: nil) new(source, filename: filename).html end - def initialize(source, line_width: 80, single_class_per_line: false, filename: nil, debug: $DEBUG) + def initialize(source, line_width: 80, single_class_per_line: false, filename: nil, css_class_sorter: nil, debug: $DEBUG) @original_source = source @filename = filename || '(erb)' @line_width = line_width @source = remove_front_matter source.dup @html = +"" @debug = debug @single_class_per_line = single_class_per_line + @css_class_sorter = css_class_sorter html.extend DebugShovel if @debug @tag_stack = [] @pre_pos = 0 @@ -116,12 +124,14 @@ def format_attributes(tag_name, attrs, tag_closing) return "" if attrs.strip.empty? plain_attrs = attrs.tr("\n", " ").squeeze(" ").gsub(erb_tags_regexp, erb_tags) - return " #{plain_attrs}" if "<#{tag_name} #{plain_attrs}#{tag_closing}".size <= line_width + within_line_width = "<#{tag_name} #{plain_attrs}#{tag_closing}".size <= line_width + return " #{plain_attrs}" if within_line_width && !@css_class_sorter && !plain_attrs.match?(/ class=/) + attr_html = "" tag_stack_push(['attr='], attrs) attrs.scan(ATTR).flatten.each do |attr| attr.strip! @@ -131,12 +141,14 @@ attr_html << indented("#{name}") next end value_parts = value[1...-1].strip.split(/\s+/) + value_parts.sort_by!(&@css_class_sorter) if name == 'class' && @css_class_sorter - full_attr = indented("#{name}=#{value[0]}#{value_parts.join(" ")}#{value[-1]}") + full_attr = "#{name}=#{value[0]}#{value_parts.join(" ")}#{value[-1]}" + full_attr = within_line_width ? " #{full_attr}" : indented(full_attr) if full_attr.size > line_width && MULTILINE_ATTR_NAMES.include?(name) && attr.match?(QUOTED_ATTR) attr_html << indented("#{name}=#{value[0]}") tag_stack_push('attr"', value) @@ -156,17 +168,17 @@ attr_html << indented(value_part) end end tag_stack_pop('attr"', value) - attr_html << indented(value[-1]) + attr_html << (within_line_width ? value[-1] : indented(value[-1])) else attr_html << full_attr end end tag_stack_pop(['attr='], attrs) - attr_html << indented("") + attr_html << indented("") unless within_line_width attr_html end def tag_stack_push(tag_name, code) tag_stack << [tag_name, code]