class Kramdown::Parser::Kramdown

Public Instance Methods

parse_atx_header() click to toggle source

Parse the Atx header at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/header.rb, line 21
def parse_atx_header
  return false if !after_block_boundary?

  start_line_number = @src.current_line_number
  @src.check(ATX_HEADER_MATCH)
  level, text, id = @src[1], @src[2].to_s.strip, @src[3]
  return false if text.empty?

  @src.pos += @src.matched_size
  el = new_block_el(:header, nil, nil, :level => level.length, :raw_text => text, :location => start_line_number, :original_text => @src[0].chomp)
  add_text(text, el)
  el.attr['id'] = id if id
  @tree.children << el
  true
end
parse_blockquote() click to toggle source

Parse the blockquote at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/blockquote.rb, line 6
def parse_blockquote
  start_line_number = @src.current_line_number
  result = @src.scan(PARAGRAPH_MATCH)
  while !@src.match?(self.class::LAZY_END)
    result << @src.scan(PARAGRAPH_MATCH)
  end
  raw_text = result.dup
  result.gsub!(BLOCKQUOTE_START, '')

  el = new_block_el(:blockquote, nil, nil, :location => start_line_number, :raw_text => raw_text)
  @tree.children << el
  parse_blocks(el, result)
  true
end
parse_codeblock() click to toggle source

Parse the indented codeblock at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/code_block.rb, line 6
def parse_codeblock
  start_line_number = @src.current_line_number
  data = @src.scan(self.class::CODEBLOCK_MATCH)
  data.gsub!(/\n( {0,3}\S)/, ' \\1')
  data.gsub!(INDENT, '')
  @tree.children << new_block_el(:codeblock, data, nil, :location => start_line_number, :raw_text => @src.matched.dup)
  true
end
parse_codeblock_fenced() click to toggle source

Parse the fenced codeblock at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/code_block.rb, line 16
def parse_codeblock_fenced
  if @src.check(self.class::FENCED_CODEBLOCK_MATCH)
    start_line_number = @src.current_line_number
    @src.pos += @src.matched_size
    el = new_block_el(:codeblock, @src[5], nil, :location => start_line_number, :raw_text => @src.matched.dup)
    lang = @src[3].to_s.strip
    unless lang.empty?
      el.options[:lang] = lang
      el.attr['class'] = "language-#{@src[4]}"
    end
    @tree.children << el
    true
  else
    false
  end
end
parse_codespan() click to toggle source

Parse the codespan at the current scanner location.

# File lib/monkey_patches/kramdown/parser/kramdown/code_span.rb, line 5
def parse_codespan
  start_line_number = @src.current_line_number
  result = @src.scan(CODESPAN_DELIMITER)
  simple = (result.length == 1)
  saved_pos = @src.save_pos

  if simple && @src.pre_match =~ /\s\Z/ && @src.match?(/\s/)
    add_text(result)
    return
  end

  if text = @src.scan_until(/#{result}/)
    raw_text = result + text
    text.sub!(/#{result}\Z/, '')
    if !simple
      text = text[1..-1] if text[0..0] == ' '
      text = text[0..-2] if text[-1..-1] == ' '
    end
    @tree.children << Element.new(:codespan, text, nil, :location => start_line_number, :raw_text => raw_text)
  else
    @src.revert_pos(saved_pos)
    add_text(result)
  end
end
parse_emphasis() click to toggle source

Parse the emphasis at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/emphasis.rb, line 6
def parse_emphasis
  start_line_number = @src.current_line_number
  saved_pos = @src.save_pos

  result = @src.scan(EMPHASIS_START)
  element = (result.length == 2 ? :strong : :em)
  type = result[0..0]

  if (type == '_' && @src.pre_match =~ /[[:alpha:]-]\z/) || @src.check(/\s/) ||
    @tree.type == element || @stack.any? { |el, _| el.type == element }
    add_text(result)
    return
  end

  sub_parse = lambda do |delim, elem|
    el = Element.new(elem, nil, nil, :location => start_line_number, :delim => delim)
    stop_re = /#{Regexp.escape(delim)}/
    found = parse_spans(el, stop_re) do
      (@src.pre_match[-1, 1] !~ /\s/) &&
        (elem != :em || !@src.match?(/#{Regexp.escape(delim*2)}(?!#{Regexp.escape(delim)})/)) &&
        (type != '_' || !@src.match?(/#{Regexp.escape(delim)}[[:alnum:]]/)) && el.children.size > 0
    end
    [found, el, stop_re]
  end

  found, el, stop_re = sub_parse.call(result, element)
  if !found && element == :strong && @tree.type != :em
    @src.revert_pos(saved_pos)
    @src.pos += 1
    found, el, stop_re = sub_parse.call(type, :em)
  end
  if found
    @src.scan(stop_re)
    @tree.children << el
  else
    @src.revert_pos(saved_pos)
    @src.pos += result.length
    add_text(result)
  end
end
parse_escaped_chars() click to toggle source

Parse the backslash-escaped character at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/escaped_chars.rb, line 6
def parse_escaped_chars
  @src.pos += @src.matched_size
  add_text(@src[0])
end
parse_footnote_marker() click to toggle source

Parse the footnote marker at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/footnote.rb, line 5
def parse_footnote_marker
  start_line_number = @src.current_line_number
  @src.pos += @src.matched_size
  fn_def = @footnotes[@src[1]]
  if fn_def
    if fn_def[:eob]
      update_attr_with_ial(fn_def[:eob].attr, fn_def[:eob].options[:ial] || {})
      fn_def[:attr] = fn_def[:eob].attr
      fn_def[:options] = fn_def[:eob].options
      fn_def.delete(:eob)
    end
    fn_def[:marker] ||= []
    fn_def[:marker].push(Element.new(:footnote, fn_def[:content], fn_def[:attr],
                                     fn_def[:options].merge(:name => @src[1], :location => start_line_number, :raw_text => @src[0].dup)))
    @tree.children << fn_def[:marker].last
  else
    warning("Footnote definition for '#{@src[1]}' not found on line #{start_line_number}")
    add_text(@src.matched)
  end
end
parse_horizontal_rule() click to toggle source

Parse the horizontal rule at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/horizontal_rule.rb, line 6
def parse_horizontal_rule
  start_line_number = @src.current_line_number
  @src.pos += @src.matched_size
  @tree.children << new_block_el(:hr, nil, nil, :location => start_line_number, raw_text: @src[0].dup)
  true
end
parse_list() click to toggle source
# File lib/monkey_patches/kramdown/parser/kramdown/list.rb, line 4
def parse_list
  start_line_number = @src.current_line_number
  type, list_start_re = (@src.check(LIST_START_UL) ? [:ul, LIST_START_UL] : [:ol, LIST_START_OL])
  list = new_block_el(type, nil, nil, :location => start_line_number, :raw_text => "")

  item = nil
  content_re, lazy_re, indent_re = nil
  eob_found = false
  nested_list_found = false
  last_is_blank = false
  while !@src.eos?
    start_line_number = @src.current_line_number
    if last_is_blank && @src.check(HR_START)
      break
    elsif @src.scan(EOB_MARKER)
      eob_found = true
      break
    elsif @src.scan(list_start_re)
      item = Element.new(:li, nil, nil, :location => start_line_number, :raw_text => @src.matched.dup)
      list.options[:raw_text] += @src[0]
      item.value, indentation, content_re, lazy_re, indent_re = parse_first_list_line(@src[1].length, @src[2])
      list.children << item

      item.value.sub!(self.class::LIST_ITEM_IAL) do |match|
        parse_attribute_list($1, item.options[:ial] ||= {})
        ''
      end

      list_start_re = (type == :ul ? /^( {0,#{[3, indentation - 1].min}}[+*-])([\t| ].*?\n)/ :
                         /^( {0,#{[3, indentation - 1].min}}\d+\.)([\t| ].*?\n)/)
      nested_list_found = (item.value =~ LIST_START)
      last_is_blank = false
      item.value = [item.value]
    elsif (result = @src.scan(content_re)) || (!last_is_blank && (result = @src.scan(lazy_re)))
      result.sub!(/^(\t+)/) { " " * 4 * $1.length }
      indentation_found = result.sub!(indent_re, '')
      if !nested_list_found && indentation_found && result =~ LIST_START
        item.value << ''
        nested_list_found = true
      elsif nested_list_found && !indentation_found && result =~ LIST_START
        result = " " * (indentation + 4) << result
      end
      item.options[:raw_text] += @src[0]
      list.options[:raw_text] += @src[0]
      item.value.last << result
      last_is_blank = false
    elsif result = @src.scan(BLANK_LINE)
      nested_list_found = true
      last_is_blank = true
      item.options[:raw_text] += @src.matched
      list.options[:raw_text] += @src.matched

      if list.children.last.type != :blank
        bl = new_block_el(:blank, [@src.matched.dup])
        bl.options[:raw_text] = @src.matched.dup
        list.children << bl
      end

      item.value.last << result
    else
      break
    end
  end

  list.options[:raw_text].gsub!(/\R{2,}\z/, "\n")
  list.children.pop if list.children.last.type == :blank
  @tree.children << list

  last = nil
  list.children.each do |it|
    temp = Element.new(:temp, nil, nil, :location => it.options[:location])

    env = save_env
    location = it.options[:location]
    it.value.each do |val|
      @src = ::Kramdown::Utils::StringScanner.new(val, location)
      parse_blocks(temp)
      location = @src.current_line_number
    end
    restore_env(env)

    it.children = temp.children
    it.value = nil
    next if it.children.size == 0

    # Handle the case where an EOB marker is inserted by a block IAL for the first paragraph
    it.children.delete_at(1) if it.children.first.type == :p &&
      it.children.length >= 2 && it.children[1].type == :eob && it.children.first.options[:ial]

    if it.children.first.type == :p &&
      (it.children.length < 2 || it.children[1].type != :blank ||
        (it == list.children.last && it.children.length == 2 && !eob_found)) &&
      (list.children.last != it || list.children.size == 1 ||
        list.children[0..-2].any? { |cit| !cit.children.first || cit.children.first.type != :p || cit.children.first.options[:transparent] })
      it.children.first.children.first.value << "\n" if it.children.size > 1 && it.children[1].type != :blank
      it.children.first.options[:transparent] = true
    end

    if it.children.last.type == :blank
      last = it.children.pop
    else
      last = nil
    end
  end

  @tree.children << last if !last.nil? && !eob_found

  true
end
parse_paragraph() click to toggle source

Parse the paragraph at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/paragraph.rb, line 6
def parse_paragraph
  start_line_number = @src.current_line_number
  result = @src.scan(PARAGRAPH_MATCH)
  while !@src.match?(paragraph_end)
    result << @src.scan(PARAGRAPH_MATCH)
  end
  raw_text = result.dup
  result.rstrip!
  if @tree.children.last && @tree.children.last.type == :p
    @tree.children.last.options[:raw_text] += result
    @tree.children.last.children.first.value << "\n" << result
  else
    @tree.children << new_block_el(:p, nil, nil, :location => start_line_number, raw_text: raw_text)
    result.lstrip!
    add_text(result, @tree.children.last)
  end
  true
end
parse_setext_header() click to toggle source

Parse the Setext header at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/header.rb, line 6
def parse_setext_header
  return false if !after_block_boundary?

  start_line_number = @src.current_line_number
  @src.pos += @src.matched_size
  text, id, level = @src[1], @src[2], @src[3]
  text.strip!
  el = new_block_el(:header, nil, nil, :level => (level == '-' ? 2 : 1), :raw_text => text, :location => start_line_number, :original_text => @src[0].chomp)
  add_text(text, el)
  el.attr['id'] = id if id
  @tree.children << el
  true
end
parse_span_html() click to toggle source

Parse the HTML at the current position as span-level HTML.

# File lib/monkey_patches/kramdown/parser/kramdown/html.rb, line 5
def parse_span_html
  line = @src.current_line_number
  if result = @src.scan(HTML_COMMENT_RE)
    @tree.children << Element.new(:xml_comment, result, nil, :category => :span, :location => line)
  elsif result = @src.scan(HTML_INSTRUCTION_RE)
    @tree.children << Element.new(:xml_pi, result, nil, :category => :span, :location => line)
  elsif result = @src.scan(HTML_TAG_CLOSE_RE)
    warning("Found invalidly used HTML closing tag for '#{@src[1]}' on line #{line}")
    add_text(result)
  elsif result = @src.scan(HTML_TAG_RE)
    tag_name = @src[1]
    tag_name.downcase! if HTML_ELEMENT[tag_name.downcase]
    if HTML_BLOCK_ELEMENTS.include?(tag_name)
      warning("Found block HTML tag '#{tag_name}' in span-level text on line #{line}")
      add_text(result)
      return
    end

    attrs = parse_html_attributes(@src[2], line, HTML_ELEMENT[tag_name])
    attrs.each { |name, value| value.gsub!(/\n+/, ' ') }

    do_parsing = (HTML_CONTENT_MODEL[tag_name] == :raw || @tree.options[:content_model] == :raw ? false : @options[:parse_span_html])
    if val = HTML_MARKDOWN_ATTR_MAP[attrs.delete('markdown')]
      if val == :block
        warning("Cannot use block-level parsing in span-level HTML tag (line #{line}) - using default mode")
      elsif val == :span
        do_parsing = true
      elsif val == :default
        do_parsing = HTML_CONTENT_MODEL[tag_name] != :raw
      elsif val == :raw
        do_parsing = false
      end
    end

    el = Element.new(:html_element, tag_name, attrs, :category => :span, :location => line,
                     :content_model => (do_parsing ? :span : :raw), :is_closed => !!@src[4], :opening_tag => result)
    @tree.children << el
    stop_re = /<\/#{Regexp.escape(tag_name)}\s*>/
    stop_re = Regexp.new(stop_re.source, Regexp::IGNORECASE) if HTML_ELEMENT[tag_name]
    if !@src[4] && !HTML_ELEMENTS_WITHOUT_BODY.include?(el.value)
      if parse_spans(el, stop_re, (do_parsing ? nil : [:span_html]))
        @src.scan(stop_re)
      else
        warning("Found no end tag for '#{el.value}' (line #{line}) - auto-closing it")
        add_text(@src.rest, el)
        @src.terminate
      end
    end
    Kramdown::Parser::Html::ElementConverter.convert(@root, el) if @options[:html_to_native]
  else
    add_text(@src.getch)
  end
end
parse_typographic_syms() click to toggle source

Parse the typographic symbols at the current location.

# File lib/monkey_patches/kramdown/parser/kramdown/typographic_symbol.rb, line 6
def parse_typographic_syms
  start_line_number = @src.current_line_number
  @src.pos += @src.matched_size
  val = TYPOGRAPHIC_SYMS_SUBST[@src.matched]
  if val.kind_of?(Symbol)
    @tree.children << Element.new(:typographic_sym, val, nil, :location => start_line_number, symbol: @src.matched)
  elsif @src.matched == '\\<<'
    @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('lt'),
                                  nil, :location => start_line_number)
    @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('lt'),
                                  nil, :location => start_line_number)
  else
    @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('gt'),
                                  nil, :location => start_line_number)
    @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('gt'),
                                  nil, :location => start_line_number)
  end
end