Module: Sourcerer::MarkDownGrade

Defined in:
lib/sourcerer/mark_down_grade.rb

Defined Under Namespace

Classes: BlockquoteWithAbstract, CustomPre, DdConverter, DlPassthrough, DtConverter, HeadingWithId, HrConverter, HtmlComment, InlineSemanticConverter, LiWithNestedLists, LinkConverter, SemanticBlockConverter, SpecialDivConverter, TablePassthrough

Constant Summary collapse

VERSION =
'0.1.0'

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.configObject (readonly)

Returns the value of attribute config.



30
31
32
# File 'lib/sourcerer/mark_down_grade.rb', line 30

def config
  @config
end

Class Method Details

.block_title_line(text) ⇒ Object

Render a block-title line with hard line break for immediate continuation.



735
736
737
# File 'lib/sourcerer/mark_down_grade.rb', line 735

def self.block_title_line text
  "#{format_block_title(text)}  \n"
end

.bootstrap!(options = {}) ⇒ Object

Setup all custom converters Options:

preserve_heading_ids: (default: true) Include <a id="..."> anchors before headings
strip_internal_links: (default: false) Remove href from internal anchor links, keeping only text
convert_tables_to_markdown: (default: false) Convert all tables to markdown UNLESS they have .no-markdown class
convert_dls_to_markdown: (default: true) Convert all DLs to markdown UNLESS they have .no-markdown class


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/sourcerer/mark_down_grade.rb', line 39

def self.bootstrap! options={}
  @config.merge!(options)

  register_pre_converter
  register_heading_converters
  register_dl_converters
  register_inline_semantic_converters
  register_block_converters
  register_table_converter
  register_hr_converter
  register_blockquote_converter
  register_comment_converter
  register_link_converter
  register_list_converters
end

.clean_admonition_inline_title(title, type) ⇒ Object

Remove duplicated admonition label prefixes from converted inline titles.



740
741
742
743
744
745
# File 'lib/sourcerer/mark_down_grade.rb', line 740

def self.clean_admonition_inline_title title, type
  normalized = title.to_s.strip
  label = "#{type.to_s.strip.capitalize}:"
  normalized = normalized.sub(/\A#{Regexp.escape(label)}\s*/i, '')
  normalized.empty? ? nil : normalized
end

.convert(html, options = {}) ⇒ Object



794
795
796
# File 'lib/sourcerer/mark_down_grade.rb', line 794

def self.convert html, options={}
  convert_html(html, options)
end

.convert_html(html, options = {}) ⇒ Object

Convert HTML into Markdown with MarkDownGrade converters. Options include:

convert_tables_to_markdown: Override global config for table conversion (true/false)
convert_dls_to_markdown: Override global config for DL conversion (true/false)


751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
# File 'lib/sourcerer/mark_down_grade.rb', line 751

def self.convert_html html, options={}
  bootstrap! unless @setup_complete
  @setup_complete = true

  # Determine effective table and DL conversion modes
  effective_table_mode = determine_table_conversion_mode(html.to_s, options)
  effective_dl_mode = determine_dl_conversion_mode(html.to_s, options)
  Thread.current[:sourcerer_table_conversion_mode] = effective_table_mode
  Thread.current[:sourcerer_dl_conversion_mode] = effective_dl_mode

  begin
    normalized_html = normalize_html_for_markdown(html.to_s)
    markdown = ReverseMarkdown.convert(normalized_html, options)
    markdown = markdown.gsub(/(\*\*[^\n]+\*\*  \n)\n+(?=\S)/, '\\1')
    markdown = markdown.gsub(/<figcaption>\s+/, '<figcaption>')
    markdown = markdown.gsub(%r{\s+</figcaption>}, '</figcaption>')
    markdown = normalize_blank_lines(markdown)

    # Replace checkbox markers: handle indented list items and maintain correct dash placement
    replace_checkbox_markers(markdown)
  ensure
    Thread.current[:sourcerer_table_conversion_mode] = nil
    Thread.current[:sourcerer_dl_conversion_mode] = nil
  end
end

.format_block_title(text) ⇒ Object

Apply strong formatting consistently across block titles.



727
728
729
730
731
732
# File 'lib/sourcerer/mark_down_grade.rb', line 727

def self.format_block_title text
  normalized = normalize_block_title(text)
  plain = normalized.gsub(/\*\*([^*]+)\*\*/, '\\1')
  plain = plain.gsub(/\*([^*]+)\*/, '\\1').strip
  plain.empty? ? normalized : "**#{plain}**"
end

.normalize_blank_lines(markdown) ⇒ Object

Collapse whitespace-only lines to truly blank ones, then collapse runs of 3+ consecutive newlines down to a single blank line (one \n\n). Nested definition lists and example blocks otherwise stack indentation and blank lines from each conversion level, producing long runs of whitespace-only lines.



781
782
783
# File 'lib/sourcerer/mark_down_grade.rb', line 781

def self.normalize_blank_lines markdown
  markdown.gsub(/^[ \t]+$/, '').gsub(/\n{3,}/, "\n\n")
end

.normalize_block_title(text) ⇒ Object

Normalize block titles so escaped inline emphasis from html5s is converted to markdown emphasis consistently with html5 conversions.



720
721
722
723
724
# File 'lib/sourcerer/mark_down_grade.rb', line 720

def self.normalize_block_title text
  normalized = text.to_s.strip.gsub(/\s+/, ' ')
  normalized = normalized.gsub(/\\\*([^*]+)\\\*/, '**\\1**')
  normalized.gsub(/(?<![\\*])\*([^*]+)\*(?!\*)/, '**\\1**')
end

.register_block_convertersObject

Register block converter for special div classes.



679
680
681
682
683
684
685
686
# File 'lib/sourcerer/mark_down_grade.rb', line 679

def self.register_block_converters
  ReverseMarkdown::Converters.register :div, SpecialDivConverter.new
  semantic = SemanticBlockConverter.new
  ReverseMarkdown::Converters.register :section, semantic
  ReverseMarkdown::Converters.register :aside, semantic
  ReverseMarkdown::Converters.register :figure, semantic
  ReverseMarkdown::Converters.register :nav, semantic
end

.register_blockquote_converterObject

Register blockquote converter with abstract handling.



699
700
701
# File 'lib/sourcerer/mark_down_grade.rb', line 699

def self.register_blockquote_converter
  ReverseMarkdown::Converters.register :blockquote, BlockquoteWithAbstract.new
end

.register_comment_converterObject

Register HTML comment converter.



704
705
706
# File 'lib/sourcerer/mark_down_grade.rb', line 704

def self.register_comment_converter
  ReverseMarkdown::Converters.register :comment, HtmlComment.new
end

.register_dl_convertersObject

Register all definition list converters. DlPassthrough handles opt-in conversion; DtConverter and DdConverter are called only when DlPassthrough decides to convert a given

.



665
666
667
668
669
# File 'lib/sourcerer/mark_down_grade.rb', line 665

def self.register_dl_converters
  ReverseMarkdown::Converters.register :dl, DlPassthrough.new
  ReverseMarkdown::Converters.register :dt, DtConverter.new
  ReverseMarkdown::Converters.register :dd, DdConverter.new
end

.register_heading_convertersObject

Register heading converter that preserves ids.



652
653
654
655
656
657
658
659
660
# File 'lib/sourcerer/mark_down_grade.rb', line 652

def self.register_heading_converters
  converter = HeadingWithId.new
  ReverseMarkdown::Converters.register :h1, converter
  ReverseMarkdown::Converters.register :h2, converter
  ReverseMarkdown::Converters.register :h3, converter
  ReverseMarkdown::Converters.register :h4, converter
  ReverseMarkdown::Converters.register :h5, converter
  ReverseMarkdown::Converters.register :h6, converter
end

.register_hr_converterObject

Register horizontal-rule converter.



694
695
696
# File 'lib/sourcerer/mark_down_grade.rb', line 694

def self.register_hr_converter
  ReverseMarkdown::Converters.register :hr, HrConverter.new
end

.register_inline_semantic_convertersObject

Register inline semantic converters.



672
673
674
675
676
# File 'lib/sourcerer/mark_down_grade.rb', line 672

def self.register_inline_semantic_converters
  ReverseMarkdown::Converters.register(:em, InlineSemanticConverter.new('em', ReverseMarkdown::Converters::Em.new))
  ReverseMarkdown::Converters.register(:strong, InlineSemanticConverter.new('strong', ReverseMarkdown::Converters::Strong.new))
  ReverseMarkdown::Converters.register(:code, InlineSemanticConverter.new('code', ReverseMarkdown::Converters::Code.new))
end

Register custom link converter to support id-only anchors and optional stripping.



709
710
711
# File 'lib/sourcerer/mark_down_grade.rb', line 709

def self.register_link_converter
  ReverseMarkdown::Converters.register :a, LinkConverter.new
end

.register_list_convertersObject

Register list item converter to handle nested lists and checkboxes.



714
715
716
# File 'lib/sourcerer/mark_down_grade.rb', line 714

def self.register_list_converters
  ReverseMarkdown::Converters.register :li, LiWithNestedLists.new
end

.register_pre_converterObject

Register the enhanced Pre converter.



647
648
649
# File 'lib/sourcerer/mark_down_grade.rb', line 647

def self.register_pre_converter
  ReverseMarkdown::Converters.register :pre, CustomPre.new
end

.register_table_converterObject

Register table passthrough converter.



689
690
691
# File 'lib/sourcerer/mark_down_grade.rb', line 689

def self.register_table_converter
  ReverseMarkdown::Converters.register :table, TablePassthrough.new
end

.replace_checkbox_markers(markdown) ⇒ Object

Replace checkbox placeholder markers with proper Markdown checkbox syntax. Handles various indentation levels and ensures correct list item formatting.



787
788
789
790
791
792
# File 'lib/sourcerer/mark_down_grade.rb', line 787

def self.replace_checkbox_markers markdown
  # Replace checkbox markers that appear after list item dashes
  # Pattern: optional indentation + dash + space + marker + space
  markdown.gsub(/^(\s*- )<!--CHECKBOX_CHECKED-->\s/, '\1[x] ')
          .gsub(/^(\s*- )<!--CHECKBOX_UNCHECKED-->\s/, '\1[ ] ')
end