# class RailsGuides::Markdown

### Public Class Methods

new(view, layout) click to toggle source

    # File guides/rails_guides/markdown.rb, line 8
    def initialize(view, layout)
      @view = view
      @layout = layout
      @index_counter = Hash.new(0)
      @raw_header = ''
      @node_ids = {}
    end

### Public Instance Methods

render(body) click to toggle source

    # File guides/rails_guides/markdown.rb, line 16
    def render(body)
      @raw_body = body
      extract_raw_header_and_body
      generate_header
      generate_title
      generate_body
      generate_structure
      generate_index
      render_page
    end

### Private Instance Methods

dom_id(nodes) click to toggle source

    # File guides/rails_guides/markdown.rb, line 29
    def dom_id(nodes)
      dom_id = dom_id_text(nodes.last.text)

      # Fix duplicate node by prefix with its parent node
      if @node_ids[dom_id]
        if @node_ids[dom_id].size > 1
          duplicate_nodes = @node_ids.delete(dom_id)
          new_node_id = "#{duplicate_nodes[-2][:id]}-#{duplicate_nodes.last[:id]}"
          duplicate_nodes.last[:id] = new_node_id
          @node_ids[new_node_id] = duplicate_nodes
        end

        dom_id = "#{nodes[-2][:id]}-#{dom_id}"
      end

      @node_ids[dom_id] = nodes
      dom_id
    end

dom_id_text(text) click to toggle source

    # File guides/rails_guides/markdown.rb, line 48
    def dom_id_text(text)
      escaped_chars = Regexp.escape('\/`*_{}[]()#+-.!:,;|&<>^~=\"')

      text.downcase.gsub(/\?/, '-questionmark')
                   .gsub(/!/, '-bang')
                   .gsub(/[#{escaped_chars}]+/, ' ').strip
                   .gsub(/\s+/, '-')
    end

engine() click to toggle source

    # File guides/rails_guides/markdown.rb, line 57
    def engine
      @engine ||= Redcarpet::Markdown.new(Renderer, {
        no_intra_emphasis: true,
        fenced_code_blocks: true,
        autolink: true,
        strikethrough: true,
        superscript: true,
        tables: true
      })
    end

extract_raw_header_and_body() click to toggle source

    # File guides/rails_guides/markdown.rb, line 68
    def extract_raw_header_and_body
      if @raw_body =~ /^\-{40,}$/
        @raw_header, _, @raw_body = @raw_body.partition(/^\-{40,}$/).map(&:strip)
      end
    end

generate_body() click to toggle source

    # File guides/rails_guides/markdown.rb, line 74
    def generate_body
      @body = engine.render(@raw_body)
    end

generate_header() click to toggle source

    # File guides/rails_guides/markdown.rb, line 78
    def generate_header
      @header = engine.render(@raw_header).html_safe
    end

generate_index() click to toggle source

    # File guides/rails_guides/markdown.rb, line 111
          def generate_index
            if @headings_for_index.present?
              raw_index = ''
              @headings_for_index.each do |level, node, label|
                if level == 1
                  raw_index += "1. [#{label}](##{node[:id]})\n"
                elsif level == 2
                  raw_index += "    * [#{label}](##{node[:id]})\n"
                end
              end

              @index = Nokogiri::HTML.fragment(engine.render(raw_index)).tap do |doc|
                doc.at('ol')[:class] = 'chapters'
              end.to_html

              @index = "          <div id="subCol">
                <h3 class="chapter"><img src="images/chapters_icon.gif" alt="" />Chapters</h3>
                #{@index}
              </div>
    ".html_safe
            end
          end

generate_structure() click to toggle source

    # File guides/rails_guides/markdown.rb, line 82
    def generate_structure
      @headings_for_index = []
      if @body.present?
        @body = Nokogiri::HTML.fragment(@body).tap do |doc|
          hierarchy = []

          doc.children.each do |node|
            if node.name =~ /^h[3-6]$/
              case node.name
              when 'h3'
                hierarchy = [node]
                @headings_for_index << [1, node, node.inner_html]
              when 'h4'
                hierarchy = hierarchy[0, 1] + [node]
                @headings_for_index << [2, node, node.inner_html]
              when 'h5'
                hierarchy = hierarchy[0, 2] + [node]
              when 'h6'
                hierarchy = hierarchy[0, 3] + [node]
              end

              node[:id] = dom_id(hierarchy)
              node.inner_html = "#{node_index(hierarchy)} #{node.inner_html}"
            end
          end
        end.to_html
      end
    end

generate_title() click to toggle source

    # File guides/rails_guides/markdown.rb, line 135
    def generate_title
      if heading = Nokogiri::HTML.fragment(@header).at(:h2)
        @title = "#{heading.text} — Ruby on Rails Guides"
      else
        @title = "Ruby on Rails Guides"
      end
    end

node_index(hierarchy) click to toggle source

    # File guides/rails_guides/markdown.rb, line 143
    def node_index(hierarchy)
      case hierarchy.size
      when 1
        @index_counter[2] = @index_counter[3] = @index_counter[4] = 0
        "#{@index_counter[1] += 1}"
      when 2
        @index_counter[3] = @index_counter[4] = 0
        "#{@index_counter[1]}.#{@index_counter[2] += 1}"
      when 3
        @index_counter[4] = 0
        "#{@index_counter[1]}.#{@index_counter[2]}.#{@index_counter[3] += 1}"
      when 4
        "#{@index_counter[1]}.#{@index_counter[2]}.#{@index_counter[3]}.#{@index_counter[4] += 1}"
      end
    end

render_page() click to toggle source

    # File guides/rails_guides/markdown.rb, line 159
    def render_page
      @view.content_for(:header_section) { @header }
      @view.content_for(:page_title) { @title }
      @view.content_for(:index_section) { @index }
      @view.render(:layout => @layout, :text => @body)
    end