Class: Markdown::Merge::Cleanse::BlockSpacing

Inherits:
Object
  • Object
show all
Defined in:
lib/markdown/merge/cleanse/block_spacing.rb

Overview

Fixes missing blank lines between block elements in Markdown.

Markdown best practices require blank lines between:

  • List items and headings
  • Thematic breaks (---) and following content
  • HTML blocks (like ) and following markdown
  • Nested list items and headings

This class detects and fixes these issues without using a full markdown parser, making it safe to use on documents that might have syntax issues.

Examples:

Basic usage

fixer = Markdown::Merge::Cleanse::BlockSpacing.new(content)
if fixer.malformed?
  fixed_content = fixer.fix
end

Check specific issues

fixer = Markdown::Merge::Cleanse::BlockSpacing.new(content)
fixer.issues.each do |issue|
  puts "Line #{issue[:line]}: #{issue[:type]}"
end

Constant Summary collapse

THEMATIC_BREAK =

Patterns for block elements that should have blank lines after them

/\A\s*(?:---+|\*\*\*+|___+)\s*\z/
HEADING =
/\A\s*\#{1,6}\s+/
LIST_ITEM =
/\A\s*(?:[-*+]|\d+\.)\s+/
HTML_CLOSE_TAG =
%r{\A\s*</[a-zA-Z][a-zA-Z0-9]*>\s*\z}
HTML_OPEN_TAG =
/\A\s*<[a-zA-Z][a-zA-Z0-9]*(?:\s|>)/
HTML_ANY_TAG =
%r{\A\s*</?[a-zA-Z]}
/\A\s*\[[^\]]+\]:\s*/
HTML_BLOCK_ELEMENTS =

Block-level HTML elements that can span multiple lines These create a context where we shouldn't insert blank lines

%w[
  ul
  ol
  li
  dl
  dt
  dd
  div
  table
  thead
  tbody
  tfoot
  tr
  th
  td
  blockquote
  pre
  figure
  figcaption
  details
  summary
  section
  article
  aside
  nav
  header
  footer
  main
  address
  form
  fieldset
].freeze
HTML_BLOCK_OPEN =

Pattern to match opening block-level HTML tags

/\A\s*<(#{HTML_BLOCK_ELEMENTS.join('|')})(?:\s|>)/i
HTML_BLOCK_CLOSE =

Pattern to match closing block-level HTML tags

%r{\A\s*</(#{HTML_BLOCK_ELEMENTS.join('|')})>}i
MARKDOWN_CONTAINER_ELEMENTS =

HTML elements that contain markdown content (not HTML content) These should have blank lines before their closing tags

%w[details].freeze
MARKDOWN_CONTAINER_CLOSE =

Pattern to match closing tags for markdown containers

%r{\A\s*</(#{MARKDOWN_CONTAINER_ELEMENTS.join('|')})>}i
MARKDOWN_CONTENT =

Markdown content: anything that's not blank, not HTML, and not a link ref def

lambda { |line|
  stripped = line.strip
  return false if stripped.empty?
  return false if stripped.start_with?('<')
  return false if line.match?(LINK_REF_DEF)

  true
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source) ⇒ BlockSpacing

Initialize a new BlockSpacing fixer.

Parameters:

  • source (String)

    The markdown content to analyze



109
110
111
112
113
# File 'lib/markdown/merge/cleanse/block_spacing.rb', line 109

def initialize(source)
  @source = source
  @issues = []
  analyze
end

Instance Attribute Details

#issuesArray<Hash> (readonly)

Returns Issues found.

Returns:

  • (Array<Hash>)

    Issues found



104
105
106
# File 'lib/markdown/merge/cleanse/block_spacing.rb', line 104

def issues
  @issues
end

#sourceString (readonly)

Returns The original content.

Returns:

  • (String)

    The original content



101
102
103
# File 'lib/markdown/merge/cleanse/block_spacing.rb', line 101

def source
  @source
end

Instance Method Details

#fixString

Fix the block spacing issues.

Returns:

  • (String)

    Content with blank lines added where needed



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/markdown/merge/cleanse/block_spacing.rb', line 132

def fix
  return source unless malformed?

  lines = source.lines
  result = []
  insertions = @issues.map { |i| i[:line] }.to_set

  lines.each_with_index do |line, idx|
    result << line
    # If this line needs a blank line after it, add one
    result << "\n" if insertions.include?(idx + 1) && !line.strip.empty? # issues use 1-based line numbers
  end

  result.join
end

#issue_countInteger

Get the count of issues found.

Returns:

  • (Integer)

    number of issues



125
126
127
# File 'lib/markdown/merge/cleanse/block_spacing.rb', line 125

def issue_count
  @issues.size
end

#malformed?Boolean

Check if the content has block spacing issues.

Returns:

  • (Boolean)

    true if issues were found



118
119
120
# File 'lib/markdown/merge/cleanse/block_spacing.rb', line 118

def malformed?
  @issues.any?
end