Module: MaRuKu::In::Markdown::BlockLevelParser

### Home Classes Methods

### In Files

- lib/maruku.rb
- lib/maruku/input/linesource.rb
- lib/maruku/input/parse_block.rb
- lib/maruku/input/parse_doc.rb

### Namespace

- CLASS MaRuKu::In::Markdown::BlockLevelParser::BlockContext
- CLASS MaRuKu::In::Markdown::BlockLevelParser::LineSource

### Methods

- #count_columns
- #element_is_non_inline_html?
- #eventually_comes_a_def_list
- #execute_code_blocks
- #expand_attribute_list
- #find_colspan
- #parse_blocks
- #parse_doc
- #parse_text_as_markdown
- #pick_apart_non_inline_html
- #read_abbreviation
- #read_ald
- #read_code
- #read_definition
- #read_footnote_text
- #read_header12
- #read_header3
- #read_indented_content
- #read_list_item
- #read_paragraph
- #read_quote
- #read_raw_html
- #read_ref_definition
- #read_table
- #read_text_material
- #read_xml_instruction
- #safe_execute_code
- #search_abbreviations
- #split_cells
- #substitute_markdown_inside_raw_html

### Included Modules

- MaRuKu::Helpers
- MaRuKu::Strings
- MaRuKu::In::Markdown::SpanLevelParser

### Class/Module Index

Quicksearch

- MaRuKu
- MaRuKu::AttributeList
- MaRuKu::Errors
- MaRuKu::Exception
- MaRuKu::HTMLElement
- MaRuKu::HTMLFragment
- MaRuKu::Helpers
- MaRuKu::In
- MaRuKu::In::Markdown
- MaRuKu::In::Markdown::BlockLevelParser
- MaRuKu::In::Markdown::BlockLevelParser::BlockContext
- MaRuKu::In::Markdown::BlockLevelParser::LineSource
- MaRuKu::In::Markdown::SpanExtension
- MaRuKu::In::Markdown::SpanLevelParser
- MaRuKu::In::Markdown::SpanLevelParser::CharSourceDebug
- MaRuKu::In::Markdown::SpanLevelParser::CharSourceManual
- MaRuKu::In::Markdown::SpanLevelParser::CharSourceStrscan
- MaRuKu::In::Markdown::SpanLevelParser::HTMLHelper
- MaRuKu::In::Markdown::SpanLevelParser::SpanContext
- MaRuKu::MDDocument
- MaRuKu::MDElement
- MaRuKu::MDHTMLElement
- MaRuKu::MDLine
- MaRuKu::NokogiriHTMLFragment
- MaRuKu::Out
- MaRuKu::Out::EntityTable
- MaRuKu::Out::HTML
- MaRuKu::Out::HTML::HTMLElement
- MaRuKu::Out::Latex
- MaRuKu::Out::Latex::MDDocumentExtensions
- MaRuKu::Out::Markdown
- MaRuKu::REXMLHTMLFragment
- MaRuKu::Section
- MaRuKu::Strings
- Maruku
- Maruku::In
- Maruku::In::Markdown
- Maruku::In::Markdown::FencedCode
- Object
- String
- Textile2Signature

No matching classes.

# MaRuKu::In::Markdown::BlockLevelParser

### Public Instance Methods

count_columns(row) click to toggle source

count the actual number of elements in a row taking into account colspans

    # File lib/maruku/input/parse_block.rb, line 653
    def count_columns(row)
      colCount = 0

      row.each do |cell|
        if cell.al && cell.al.size > 0
          al = find_colspan(cell.al)
          if al != nil
            colCount += al[1].to_i
          else
            colCount += 1
          end
        else
          colCount += 1
        end
      end

      colCount
    end

element_is_non_inline_html?(elem) click to toggle source

Is the given element an HTML element whose root is not an inline element?

    # File lib/maruku/input/parse_block.rb, line 324
    def element_is_non_inline_html?(elem)
      if elem.is_a?(MDElement) && elem.node_type == :raw_html && elem.parsed_html
        first_node_name = elem.parsed_html.first_node_name
        first_node_name && !HTML_INLINE_ELEMS.include?(elem.parsed_html.first_node_name)
      else
        false
      end
    end

eventually_comes_a_def_list(src) click to toggle source

If current line is text, a definition list is coming if 1) text,empty,*,definition

    # File lib/maruku/input/parse_block.rb, line 681
    def eventually_comes_a_def_list(src)
      src.tell_me_the_future =~ %{^t+e?d}
    end

execute_code_blocks() click to toggle source

    # File lib/maruku/input/parse_doc.rb, line 123
    def execute_code_blocks
      each_element(:xml_instr) do |e|
        if e.target == 'maruku'
          result = safe_execute_code(e, e.code)
          if result.kind_of?(String)
            puts "Result is : #{result.inspect}"
          end
        end
      end
    end

expand_attribute_list(al, result) click to toggle source

Expands an attribute list in an Hash

    # File lib/maruku/input/parse_doc.rb, line 72
    def expand_attribute_list(al, result)
      al.each do |k, v|
        case k
        when :class
          if result[:class]
            result[:class] << " " << v
          else
            result[:class] = v
          end
        when :id
          result[:id] = v
        when :ref
          if self.ald[v]
            already = (result[:expanded_references] ||= [])
            if !already.include?(v)
              already << v
              expand_attribute_list(self.ald[v], result)
            else
              already << v
              maruku_error "Circular reference between labels.\n\n" +
              "Label #{v.inspect} calls itself via recursion.\nThe recursion is " +
                already.map(&:inspect).join(' => ')
            end
          else
            if result[:unresolved_references]
              result[:unresolved_references] << " " << v
            else
              result[:unresolved_references] = v
            end

            # $stderr.puts "Unresolved reference #{v.inspect} (avail: #{self.ald.keys.inspect})"
            result[v.to_sym] = true
          end
        else
          result[k.to_sym] = v
        end
      end
    end

find_colspan(al) click to toggle source

Search an attribute list looking for a colspan

    # File lib/maruku/input/parse_block.rb, line 675
    def find_colspan(al)
      al.find {|alElem| alElem[0] == "colspan" }
    end

parse_blocks(src) click to toggle source

Input is a LineSource

    # File lib/maruku/input/parse_block.rb, line 24
    def parse_blocks(src)
      output = BlockContext.new

      # run state machine
      while src.cur_line
        next if check_block_extensions(src, output, src.cur_line)

        md_type = src.cur_line.md_type

        # Prints detected type (useful for debugging)
        #puts "parse_blocks #{md_type}|#{src.cur_line}"
        case md_type
        when :empty
          output << :empty
          src.ignore_line
        when :ial
          m = InlineAttributeList.match src.shift_line
          content = m[1] || ""
          src2 = CharSource.new(content, src)
          interpret_extension(src2, output)
        when :ald
          output << read_ald(src)
        when :text
          # paragraph, or table, or definition list
          read_text_material(src, output)
        when :header2, :hrule
          # hrule
          src.shift_line
          output << md_hrule
        when :header3
          output << read_header3(src)
        when :ulist, :olist
          list_type = (md_type == :ulist) ? :ul : :ol
          li = read_list_item(src)
          # append to current list if we have one
          if output.last.kind_of?(MDElement) &&
              output.last.node_type == list_type then
            output.last.children << li
          else
            output << md_el(list_type, li)
          end
        when :quote
          output << read_quote(src)
        when :code
          e = read_code(src)
          output << e if e
        when :raw_html
          # More extra hacky stuff - if there's more than just HTML, we either wrap it
          # in a paragraph or break it up depending on whether it's an inline element or not
          e = read_raw_html(src)
          unless e.empty?
            if e.first.parsed_html &&
                (first_node_name = e.first.parsed_html.first_node_name) &&
                HTML_INLINE_ELEMS.include?(first_node_name) &&
                !%(svg math).include?(first_node_name)
              content = [e.first]
              if e.size > 1
                content.concat(e[1].children)
              end
              output << md_par(content)
            else
              output.concat(e)
            end
          end
        when :footnote_text
          output << read_footnote_text(src)
        when :ref_definition
          if src.parent && src.cur_index == 0
            read_text_material(src, output)
          else
            read_ref_definition(src, output)
          end
        when :abbreviation
          output << read_abbreviation(src)
        when :xml_instr
          read_xml_instruction(src, output)
        else # unhandled line type at this level
          # Just treat it as raw text
          read_text_material(src, output)
        end
      end

      merge_ial(output, src, output)
      output.delete_if do |x|
        # Strip out IAL
        (x.kind_of?(MDElement) && x.node_type == :ial) ||
        # get rid of empty line markers
        x == :empty
      end

      # See for each list if we can omit the paragraphs
      # TODO: do this after
      output.each do |c|
        # Remove paragraphs that we can get rid of
        if [:ul, :ol].include?(c.node_type) && c.children.none?(&:want_my_paragraph)
          c.children.each do |d|
            if d.children.first && d.children.first.node_type == :paragraph
              d.children = d.children.first.children + d.children[1..-1]
            end
          end
        elsif c.node_type == :definition_list && c.children.none?(&:want_my_paragraph)
          c.children.each do |definition|
            definition.definitions.each do |dd|
              if dd.children.first.node_type == :paragraph
                dd.children = dd.children.first.children + dd.children[1..-1]
              end
            end
          end
        end
      end

      output
    end

parse_doc(s) click to toggle source

    # File lib/maruku/input/parse_doc.rb, line 6
      def parse_doc(s)
        # Remove BOM if it is present
        s = s.sub(/^\xEF\xBB\xBF/, '')
        meta2 = parse_email_headers(s)
        data = meta2.delete :data

        self.attributes.merge! meta2

    Attribute: encoding
    Scope:     document
    Summary:   Encoding for the document.

    If the `encoding` attribute is specified, then the content
    will be converted from the specified encoding to UTF-8.

        enc = self.attributes.delete(:encoding) || 'utf-8'
        if enc.downcase != 'utf-8'
          # Switch to ruby 1.9 String#encode
          # with backward 1.8 compatibility
          if data.respond_to?(:encode!)
            data.encode!('UTF-8', enc)
          else
            require 'iconv'
            data = Iconv.new('utf-8', enc).iconv(data)
          end
        end

        @children = parse_text_as_markdown(data)

        if markdown_extra?
          self.search_abbreviations
          self.substitute_markdown_inside_raw_html
        end

        self.toc = create_toc

        # use title if not set
        self.attributes[:title] ||= toc.header_element.children.join if toc.header_element

        # Now do the attributes magic
        each_element do |e|
          # default attribute list
          if default = self.ald[e.node_type.to_s]
            expand_attribute_list(default, e.attributes)
          end
          expand_attribute_list(e.al, e.attributes)
    #     puts "#{e.node_type}: #{e.attributes.inspect}"
        end

    Attribute: unsafe_features
    Scope:     global
    Summary:   Enables execution of XML instructions.

    Disabled by default because of security concerns.

        if Maruku::Globals[:unsafe_features]
          self.execute_code_blocks
          # TODO: remove executed code blocks
        end
      end

parse_text_as_markdown(text) click to toggle source

Splits the string and calls parse_lines_as_markdown

    # File lib/maruku/input/parse_block.rb, line 17
    def parse_text_as_markdown(text)
      lines =  split_lines(text)
      src = LineSource.new(lines)
      parse_blocks(src)
    end

pick_apart_non_inline_html(children) click to toggle source

If there are non-inline HTML tags in the paragraph, break them out into their own elements and make paragraphs out of everything else.

    # File lib/maruku/input/parse_block.rb, line 294
    def pick_apart_non_inline_html(children)
      output = []
      para_children = []

      children.each do |child|
        if element_is_non_inline_html?(child)
          unless para_children.empty?
            # Fix up paragraphs before non-inline elements having an extra space
            last_child = para_children.last
            if last_child.is_a?(String) && !last_child.empty?
              last_child.replace last_child[0..-2]
            end

            output << md_par(para_children)
            para_children = []
          end
          output << child
        else
          para_children << child
        end
      end

      unless para_children.empty?
        output << md_par(para_children)
      end

      output
    end

read_abbreviation(src) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 361
    def read_abbreviation(src)
      unless (l = src.shift_line) =~ Abbreviation
        maruku_error "Bug: it's Andrea's fault. Tell him.\n#{l.inspect}"
      end

      abbr = $1
      desc = $2

      if !abbr || abbr.empty?
        maruku_error "Bad abbrev. abbr=#{abbr.inspect} desc=#{desc.inspect}"
      end

      self.abbreviations[abbr] = desc

      md_abbr_def(abbr, desc)
    end

read_ald(src) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 158
    def read_ald(src)
      if (l = src.shift_line) =~ AttributeDefinitionList
        id = $1
        al = read_attribute_list(CharSource.new($2, src))
        self.ald[id] = al;
        md_ald(id, al)
      else
        maruku_error "Bug Bug:\n#{l.inspect}"
        nil
      end
    end

read_code(src) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 490
    def read_code(src)
      # collect all indented lines
      lines = []
      while src.cur_line && [:code, :empty].include?(src.cur_line.md_type)
        lines << strip_indent(src.shift_line, 4)
      end

      #while lines.last && (lines.last.md_type == :empty )
      while lines.last && lines.last.strip.size == 0
        lines.pop
      end

      while lines.first && lines.first.strip.size == 0
        lines.shift
      end

      return nil if lines.empty?

      source = lines.join("\n")

      md_codeblock(source)
    end

read_definition(src) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 685
    def read_definition(src)
      # Read one or more terms
      terms = []
      while src.cur_line && src.cur_line.md_type == :text
        terms << md_el(:definition_term, parse_span(src.shift_line))
      end

      want_my_paragraph = false

      raise "Chunky Bacon!" unless src.cur_line

      # one optional empty
      if src.cur_line.md_type == :empty
        want_my_paragraph = true
        src.shift_line
      end

      raise "Chunky Bacon!" unless src.cur_line.md_type == :definition

      # Read one or more definitions
      definitions = []
      while src.cur_line && src.cur_line.md_type == :definition
        parent_offset = src.cur_index

        first = src.shift_line
        first =~ Definition
        first = $1

        lines, w_m_p = read_indented_content(src, 4, :definition, :definition)
        want_my_paragraph ||= w_m_p

        lines.unshift first

        src2 = LineSource.new(lines, src, parent_offset)
        children = parse_blocks(src2)
        definitions << md_el(:definition_data, children)
      end

      md_el(:definition, terms + definitions, {
              :terms => terms,
              :definitions => definitions,
              :want_my_paragraph => want_my_paragraph
            })
    end

read_footnote_text(src) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 378
    def read_footnote_text(src)
      parent_offset = src.cur_index

      first = src.shift_line

      unless first =~ FootnoteText
        maruku_error "Bug (it's Andrea's fault)"
      end

      id = $1
      text = $2 || ''

      indentation = 4 #first.size-text.size

      #   puts "id =_#{id}_; text=_#{text}_ indent=#{indentation}"

      break_list = [:footnote_text, :ref_definition, :definition, :abbreviation]
      item_type = :footnote_text
      lines, _ = read_indented_content(src, indentation, break_list, item_type)

      # add first line
      lines.unshift text unless text.strip.empty?

      src2 = LineSource.new(lines, src, parent_offset)
      children = parse_blocks(src2)

      e = md_footnote(id, children)
      self.footnotes[id] = e
      e
    end

read_header12(src) click to toggle source

reads a header (with ----- or ========)

    # File lib/maruku/input/parse_block.rb, line 171
    def read_header12(src)
      line = src.shift_line.strip
      al = nil
      # Check if there is an IAL
      if new_meta_data? and line =~ /^(.*?)\{(.*?)\}\s*$/
        line = $1.strip
        ial = $2
        al = read_attribute_list(CharSource.new(ial, src))
      end
      text = parse_span line
      if text.empty?
        text = "{#{ial}}"
        al = nil
      end
      level = src.cur_line.md_type == :header2 ? 2 : 1;
      src.shift_line
      md_header(level, text, al)
    end

read_header3(src) click to toggle source

reads a header like '#### header ####'

    # File lib/maruku/input/parse_block.rb, line 191
    def read_header3(src)
      line = src.shift_line.strip
      al = nil
      # Check if there is an IAL
      if new_meta_data? and line =~ /^(.*?)\{(.*?)\}\s*$/
        line = $1.strip
        ial = $2
        al = read_attribute_list(CharSource.new(ial, src))
      end
      level = line[/^#+/].size
      text = parse_span line.gsub(/\A#+|#+\z/, '')
      if text.empty?
        text = "{#{ial}}"
        al = nil
      end
      md_header(level, text, al)
    end

read_indented_content(src, indentation, break_list, item_type, ial_offset=0) click to toggle source

This is the only ugly function in the code base. It is used to read list items, descriptions, footnote text

    # File lib/maruku/input/parse_block.rb, line 412
    def read_indented_content(src, indentation, break_list, item_type, ial_offset=0)
      lines = []
      # collect all indented lines
      saw_empty = false
      saw_anything_after = false
      break_list = Array(break_list)
      len = indentation - ial_offset

      while src.cur_line
        num_leading_spaces = src.cur_line.number_of_leading_spaces
        break if num_leading_spaces < len && ![:text, :empty].include?(src.cur_line.md_type)

        line = strip_indent(src.cur_line, indentation)
        md_type = line.md_type

        if md_type == :empty
          saw_empty = true
          lines << line
          src.shift_line
          next
        end

        # Unquestioningly grab anything that's deeper-indented
        if md_type != :code && num_leading_spaces > len
          lines << line
          src.shift_line
          next
        end

        # after a white line
        if saw_empty
          # we expect things to be properly aligned
          break if num_leading_spaces < len
          saw_anything_after = true
        else
          break if break_list.include?(md_type)
        end

        lines << line
        src.shift_line

        # You are only required to indent the first line of
        # a child paragraph.
        if md_type == :text
          while src.cur_line && src.cur_line.md_type == :text
            lines << strip_indent(src.shift_line, indentation)
          end
        end
      end

      # TODO fix this
      want_my_paragraph = saw_anything_after ||
        (saw_empty && src.cur_line && src.cur_line.md_type == item_type)

      # create a new context

      while lines.last && lines.last.md_type == :empty
        lines.pop
      end

      return lines, want_my_paragraph
    end

read_list_item(src) click to toggle source

Reads one list item, either ordered or unordered.

    # File lib/maruku/input/parse_block.rb, line 334
    def read_list_item(src)
      parent_offset = src.cur_index

      item_type = src.cur_line.md_type
      first = src.shift_line

      indentation, ial = spaces_before_first_char(first)
      al = read_attribute_list(CharSource.new(ial, src)) if ial
      ial_offset = ial ? ial.length + 3 : 0
      lines, want_my_paragraph = read_indented_content(src, indentation, [], item_type, ial_offset)

      # in case there is a second line and this line starts a new list, format it.
      if !lines.empty? && [:ulist, :olist].include?(MaRuKu::MDLine.new(lines.first).md_type)
        lines.unshift ""
      end

      # add first line
      # Strip first '*', '-', '+' from first line
      first_changed = first.gsub(/([^\t]*)(\t)/) { $1 + " " * (TAB_SIZE - $1.length % TAB_SIZE) }
      stripped = first_changed[indentation, first_changed.size - 1]
      lines.unshift stripped
      src2 = LineSource.new(lines, src, parent_offset)
      children = parse_blocks(src2)

      md_li(children, want_my_paragraph, al)
    end

read_paragraph(src) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 271
    def read_paragraph(src)
      lines = [src.shift_line]
      while src.cur_line
        # :olist does not break
        case t = src.cur_line.md_type
        when :quote, :header3, :empty, :ref_definition, :ial, :xml_instr
          break
        when :olist, :ulist
          break if !src.next_line || src.next_line.md_type == t
        end
        break if src.cur_line.strip.empty?
        break if src.next_line && [:header1, :header2].include?(src.next_line.md_type)
        break if any_matching_block_extension?(src.cur_line)

        lines << src.shift_line
      end
      children = parse_span(lines, src)

      pick_apart_non_inline_html(children)
    end

read_quote(src) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 476
    def read_quote(src)
      parent_offset = src.cur_index

      lines = []
      # collect all indented lines
      while src.cur_line && src.cur_line.md_type == :quote
        lines << unquote(src.shift_line)
      end

      src2 = LineSource.new(lines, src, parent_offset)
      children = parse_blocks(src2)
      md_quote(children)
    end

read_raw_html(src) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 238
    def read_raw_html(src)
      extra_line = nil
      h = HTMLHelper.new
      begin
        l = src.shift_line
        h.eat_this(l)
        #     puts "\nBLOCK:\nhtml -> #{l.inspect}"
        while src.cur_line && !h.is_finished?
          l = src.shift_line
          #       puts "html -> #{l.inspect}"
          h.eat_this "\n" + l
        end
      rescue => e
        maruku_error "Bad block-level HTML:\n#{e.inspect.gsub(/^/, '|')}\n", src
      end
      unless h.rest =~ /^\s*$/
        extra_line = h.rest
      end
      raw_html = h.stuff_you_read

      is_inline = HTML_INLINE_ELEMS.include?(h.first_tag)

      if extra_line
        remainder = is_inline ? parse_span(extra_line) : parse_text_as_markdown(extra_line)
        if extra_line.start_with?(' ')
          remainder[0] = ' ' + remainder[0] if remainder[0].is_a?(String)
        end
        is_inline ? [md_html(raw_html), md_par(remainder)] : [md_html(raw_html)] + remainder
      else
        [md_html(raw_html)]
      end
    end

read_ref_definition(src, out) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 513
    def read_ref_definition(src, out)
      line = src.shift_line

      # if link is incomplete, shift next line
      if src.cur_line &&
          ![:footnote_text, :ref_definition, :definition, :abbreviation].include?(src.cur_line.md_type) &&
          (1..3).include?(src.cur_line.number_of_leading_spaces)
        line << " " << src.shift_line
      end

      match = LinkRegex.match(line)
      unless match
        maruku_error "Link does not respect format: '#{line}'" and return
      end

      id = match[1]
      url = match[2]
      title = match[3] || match[4] || match[5]
      id = sanitize_ref_id(id)

      hash = self.refs[id] = {
        :url => url,
        :title => title
      }

      stuff = (match[6] || '')
      stuff.split.each do |couple|
        k, v = couple.split('=')
        v ||= ""
        v = v[1..-2] if v.start_with?('"') # strip quotes
        hash[k.to_sym] = v
      end

      out << md_ref_def(id, url, :title => title)
    end

read_table(src) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 563
    def read_table(src)
      head = split_cells(src.shift_line).map do |s|
        md_el(:head_cell, parse_span(s))
      end

      separator = split_cells(src.shift_line)

      align = separator.map do |s|
        # ex: :-------------------:
        # If the separator starts and ends with a colon,
        # center the cell. If it's on the right, right-align,
        # otherwise left-align.
        starts = s.start_with? ':'
        ends = s.end_with? ':'
        if s.empty? # blank
          nil
        elsif starts && ends
          :center
        elsif ends
          :right
        else
          :left
        end
      end

      align.pop if align[-1].nil? # trailing blank
      num_columns = align.size

      head.pop if head.size == num_columns + 1 && head[-1].al.size == 0 # trailing blank

      if head.size != num_columns
        maruku_error "Table head does not have #{num_columns} columns: \n#{head.inspect}"
        tell_user "I will ignore this table."
        # XXX try to recover
        return md_br
      end

      rows = []
      while src.cur_line && src.cur_line.include?('|')
        row = []
        colCount = 0
        colspan = 1
        currElem = nil
        currIdx = 0
        split_cells(src.shift_line, true).map do |s|
          if s.empty?
            # empty cells increase the colspan of the previous cell
            found = false
            colspan +=  1
            al = (currElem &&currElem.al) || AttributeList.new
            if al.size > 0
              elem = find_colspan(al)
              if elem != nil
                elem[1] = colspan.to_s
                found = true
              end
            end
            al.push(["colspan", colspan.to_s]) unless found # also handles the case of and empty attribute list
          else
            colspan = 1
            row[currIdx] = md_el(:cell, parse_span(s))
            currElem = row[currIdx]
            currIdx += 1
          end
        end

        #
        # sanity check - make sure the current row has the right number of columns (including spans)
        #                If not, dump the table and return a break
        #
        num_columns = count_columns(row)
        if num_columns == head.size + 1 && row[-1].al.size == 0 #trailing blank cell
          row.pop
          num_columns -= 1
        end
        if head.size != num_columns
          maruku_error  "Row does not have #{head.size} columns: \n#{row.inspect} - #{num_columns}"
          tell_user "I will ignore this table."
          # XXX need to recover
          return md_br
        end
        rows << row
      end
      rows.unshift(head) # put the header row on the processed table
      md_el(:table, rows, { :align => align })
    end

read_text_material(src, output) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 138
    def read_text_material(src, output)
      if src.cur_line.include?('|') && # if contains a pipe, it could be a table header
          src.next_line &&
          src.next_line.rstrip =~ TableSeparator
        output << read_table(src)
      elsif src.next_line && [:header1, :header2].include?(src.next_line.md_type)
        output << read_header12(src)
      elsif eventually_comes_a_def_list(src)
        definition = read_definition(src)
        if output.last.kind_of?(MDElement) &&
            output.last.node_type == :definition_list then
          output.last.children << definition
        else
          output << md_el(:definition_list, definition)
        end
      else # Start of a paragraph
        output.concat read_paragraph(src)
      end
    end

read_xml_instruction(src, output) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 209
    def read_xml_instruction(src, output)
      m = /^\s*<\?((\w+)\s*)?(.*)$/.match src.shift_line
      raise "BugBug" unless m
      target = m[2] || ''
      code = m[3]
      until code.include?('?>')
        code << "\n" << src.shift_line
      end
      unless code =~ /\?>\s*$/
        garbage = (/\?>(.*)$/.match(code))[1]
        maruku_error "Trailing garbage on last line: #{garbage.inspect}:\n" +
          code.gsub(/^/, '|'), src
      end
      code.gsub!(/\?>\s*$/, '')

      if target == 'mrk' && MaRuKu::Globals[:unsafe_features]
        result = safe_execute_code(self, code)
        if result
          if result.kind_of? String
            raise "Not expected"
          else
            output.push(*result)
          end
        end
      else
        output << md_xml_instr(target, code)
      end
    end

safe_execute_code(object, code) click to toggle source

    # File lib/maruku/input/parse_doc.rb, line 111
    def safe_execute_code(object, code)
      begin
        object.instance_eval(code)
      rescue StandardError, ScriptError => e
        maruku_error "Exception while executing this:\n" +
          code.gsub(/^/, ">") +
          "\nThe error was:\n" +
          (e.inspect + "\n" + e.caller.join("\n")).gsub(/^/, "|")
        nil
      end
    end

search_abbreviations() click to toggle source

    # File lib/maruku/input/parse_doc.rb, line 134
    def search_abbreviations
      abbreviations.each do |abbrev, title|
        reg = Regexp.new(Regexp.escape(abbrev))
        replace_each_string do |s|
          # bug if many abbreviations are present (agorf)
          p = StringScanner.new(s)
          a = []
          until p.eos?
            o = ''
            o << p.getch until p.scan(reg) or p.eos?
            a << o unless o.empty?
            a << md_abbr(abbrev.dup, title ? title.dup : nil) if p.matched == abbrev
          end
          a
        end
      end
    end

split_cells(s, allowBlank = false) click to toggle source

    # File lib/maruku/input/parse_block.rb, line 549
    def split_cells(s, allowBlank = false)
      if allowBlank
        if /^[|].*[|]$/ =~ s # handle the simple and decorated table cases
          s.split('|', -1)[1..-2]   # allow blank cells, but only keep the inner elements of the cells
        elsif /^.*[|]$/ =~ s
          s.split('|', -1)[0..-2]   # allow blank cells, but only keep the inner elements of the cells
        else
          s.split('|', -1)
        end
      else
        s.split('|').reject(&:empty?).map(&:strip)
      end
    end

substitute_markdown_inside_raw_html() click to toggle source

(PHP Markdown extra) Search for elements that have markdown=1 or markdown=block defined

    # File lib/maruku/input/parse_doc.rb, line 154
    def substitute_markdown_inside_raw_html
      each_element(:raw_html) do |e|
        html = e.parsed_html
        next unless html

        html.process_markdown_inside_elements(self)
      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.