class RDoc::Markup::InlineParser

Parses inline markup in RDoc text. This parser handles em, bold, strike, tt, hard break, and tidylink. Block-level constructs are handled in RDoc::Markup::Parser.

Public Class Methods

# File lib/rdoc/markup/inline_parser.rb, line 82
def initialize(string)
  @scanner = StringScanner.new(string)
  @last_match = nil
  @scanner_negative_cache = Set.new
  @stack = []
  @delimiters = {}
end

Public Instance Methods

Return the current parsing node on @stack.

# File lib/rdoc/markup/inline_parser.rb, line 92
def current
  @stack.last
end

Parse and return an array of nodes. Node format:

{
  type: :EM | :BOLD | :BOLD_WORD | :EM_WORD | :TT | :STRIKE | :HARD_BREAK | :TIDYLINK,
  url: string # only for :TIDYLINK
  children: [string_or_node, ...]
}
# File lib/rdoc/markup/inline_parser.rb, line 104
def parse
  stack_push(:root, nil)
  while true
    type, token, value = scan_token
    close = nil
    tidylink_url = nil
    case type
    when :node
      current[:children] << value
      invalidate_open_tidylinks if value[:type] == :TIDYLINK
    when :eof
      close = :root
    when :tidylink_open
      stack_push(:tidylink, token)
    when :tidylink_close
      close = :tidylink
      if value
        tidylink_url = value
      else
        # Tidylink closing brace without URL part. Treat opening and closing braces as normal text
        # `{labelnodes}...` case.
        current[:children] << token
      end
    when :invalidated_tidylink_close
      # `{...{label}[url]...}` case. Nested tidylink invalidates outer one. The last `}` closes the invalidated tidylink.
      current[:children] << token
      close = :invalidated_tidylink
    when :text
      current[:children] << token
    when :open
      stack_push(value, token)
    when :close
      if @delimiters[value]
        close = value
      else
        # closing tag without matching opening tag. Treat as normal text.
        current[:children] << token
      end
    end

    next unless close

    while current[:delimiter] != close
      children = current[:children]
      open_token = current[:token]
      stack_pop
      current[:children] << open_token if open_token
      current[:children].concat(children)
    end

    token = current[:token]
    children = compact_string(current[:children])
    stack_pop

    return children if close == :root

    if close == :tidylink || close == :invalidated_tidylink
      if tidylink_url
        current[:children] << { type: :TIDYLINK, children: children, url: tidylink_url }
        invalidate_open_tidylinks
      else
        current[:children] << token
        current[:children].concat(children)
      end
    else
      current[:children] << { type: TAGS[close], children: children }
    end
  end
end