module Brief class Document::Structure attr_accessor :fragment, :content_lines def initialize(fragment, content_lines = []) @fragment = fragment @content_lines = content_lines end def prescan content_lines.each_with_index do |line, index| if line.match(/^#/) line = line.strip level = line.count('#') text = line.gsub('#', '').strip if level > 0 && text.length > 0 line_number = index + 1 heading = find_heading_by(level, text) if heading heading.element.set_attribute('data-line-number', line_number) end end end end end # Markdown rendered HTML comes in the forms of a bunch of siblings, # and no parents. We need to introduce the concept of ownership of # sections of the document, by using the heading level (h1 - h6) as # a form of rank. # # All h1 elements will 'own' the h2,h3,h4,h5,h6 # elements underneath them. def create_wrappers return if @elements_have_been_wrapped elements = fragment.children # The different groups of elements mapping = [] # The current bucket of elements that is being # collected, will get reset whenever it runs into # an element that is a greater heading rank bucket = [] current_level = Util.level(elements.first) elements.each_cons(2) do |element, next_element| bucket << element # We will have run into a greater header, so close up the bucket # and put it into the mapping if Util.is_header?(next_element) && Util.level(next_element) >= current_level mapping.push([current_level, bucket]) bucket = [] end if Util.is_header?(element) current_level = Util.level(element) end end # we never ended up reaching a header, so close up and move on if !mapping.include?(bucket) mapping.push([current_level, bucket]) end base_fragment = Nokogiri::HTML.fragment("
") mapping.map! do |item| level, group = item group.reject! { |i| i.text == "\n" } if level == 0 base_fragment = fragment = Nokogiri::HTML.fragment("