class Rabbit::Parser::Markdown::Converter

Public Class Methods

new(canvas) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 36
def initialize(canvas)
  @canvas = canvas
  @slides = []
  @slide = nil
  @slide_property_mode = false
end

Public Instance Methods

convert(element, context=nil) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 43
def convert(element, context=nil)
  method_name = "convert_#{element.type}"
  method_name << "_#{context}" if context
  __send__(method_name, element)
end

Private Instance Methods

apply_class(children, klass) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 187
def apply_class(children, klass)
  return children if klass.nil?
  classes = klass.split
  classes.inject(children) do |nested_children, klass|
    CustomTag.new(klass, nested_children)
  end
end
convert_a(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 392
def convert_a(element)
  ref = ReferText.new(convert_container(element))
  ref.to = element.attr["href"]
  ref
end
convert_blank(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 128
def convert_blank(element)
  :no_element
end
convert_blockquote(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 349
def convert_blockquote(element)
  BlockQuote.new(convert_container(element))
end
convert_br(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 398
def convert_br(element)
  Text.new("\n")
end
convert_codeblock(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 307
def convert_codeblock(element)
  content = element.value.chomp
  language = detect_codeblock_language(element)
  if language
    converted = convert_codeblock_language(element, language, content)
  end
  converted || PreformattedBlock.new(PreformattedText.new(text(content)))
end
convert_codeblock_language(element, language, content) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 331
def convert_codeblock_language(element, language, content)
  case language
  when "blockdiag"
    make_image_from_file(element, content) do |src_file, prop|
      Ext::BlockDiag.make_image(src_file.path, prop, @canvas)
    end
  when "mermaid"
    make_image_from_file(element,
                         content,
                         extension: ".mmd") do |src_file, prop|
      src_file
    end
  else
    logger = @canvas.logger
    Ext::Rouge.highlight(language, content, logger)
  end
end
convert_codespan(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 402
def convert_codespan(element)
  Code.new(text(element.value))
end
convert_comment(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 303
def convert_comment(element)
  :no_element
end
convert_container(element, context=nil) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 50
def convert_container(element, context=nil)
  elements = []
  element.children.each do |child|
    element = convert(child, context)
    case element
    when nil, :no_element
      # ignore
    else
      elements << element
    end
  end
  elements
end
convert_dd(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 159
def convert_dd(element)
  DescriptionContent.new(convert_container(element))
end
convert_dl(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 132
def convert_dl(element)
  list = DescriptionList.new
  term = nil
  content = nil
  convert_container(element).each do |item|
    case item
    when DescriptionTerm
      list << DescriptionListItem.new(term, content) if term
      term = item
    when DescriptionContent
      content = item
    end
  end
  list << DescriptionListItem.new(term, content) if term
  list
end
convert_dt(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 155
def convert_dt(element)
  DescriptionTerm.new(create_paragraph(convert_container(element)))
end
convert_em(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 367
def convert_em(element)
  Emphasis.new(Emphasis.new(convert_container(element)))
end
convert_header(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 96
def convert_header(element)
  slide, @slide = @slide, nil
  contents = convert_container(element)
  case element.options[:level]
  when 1
    if @slides.empty?
      @slide = TitleSlide.new(Title.new(contents))
    else
      @slide = Element::Slide.new(HeadLine.new(contents))
      @slide << Body.new
    end
    @slides << @slide
    @slide
  when 2
    if /\Anote\z/i =~ contents.first.text
      NoteSetter.new(@slides.last)
    else
      SlidePropertySetter.new(@slides.last)
    end
  else
    nil
  end
end
convert_hr(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 299
def convert_hr(element)
  raise ParseError, _("horizontal rule isn't supported.")
end
convert_html_element(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 431
def convert_html_element(element)
  raise ParseError, _("HTML isn't supported.")
end
convert_img(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 353
def convert_img(element)
  options = element.attr.dup
  uri = options.delete("src")
  title = options.delete("title")
  alt = options.delete("alt")
  caption = title || alt
  options["caption"] ||= caption if caption
  image = Ext::Image.make_image(@canvas,
                                uri,
                                options,
                                body: @slides.last.body)
  image || text(alt || src)
end
convert_li_ol(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 246
def convert_li_ol(element)
  create_list_item(EnumListItem, convert_container(element))
end
convert_li_ul(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 234
def convert_li_ul(element)
  create_list_item(ItemListItem, convert_container(element))
end
convert_math(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 386
def convert_math(element)
  make_image_from_file(element, element.value) do |src_file, prop|
    Ext::TeX.make_image_by_LaTeX(src_file.path, prop, @canvas)
  end
end
convert_note(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 410
def convert_note(element)
  # TODO: Should we validate element.options[:category] == "span"?
  Ext::Inline.note(convert_container(element))
end
convert_ol(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 238
def convert_ol(element)
  i = 1
  create_list(EnumList, convert_container(element, "ol")) do |list, item|
    item.order = i
    i += 1
  end
end
convert_p(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 163
def convert_p(element)
  child_types = element.children.collect {|child| child.type}
  if child_types == [:img]
    convert_container(element)[0]
  else
    if child_types.count(:img) > 1
      raise ParseError,
            _("multiple ![alt]{image}s in a paragraph isn't supported.")
    end
    if child_types.include?(:img)
      message =
        _("![alt]{image} and other contents in a paragraph " \
          "isn't supported: %{types}")
      raise ParseError, message % {types: child_types}
    end
    if element.options[:transparent] and child_types == [:text]
      element.children.first.value.chomp!
    end
    converted_children = apply_class(convert_container(element),
                                     element.attr["class"])
    create_paragraph(converted_children)
  end
end
convert_root(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 64
def convert_root(element)
  target = nil
  mode = :ignore
  convert_container(element).each do |content|
    case content
    when :no_element
      next
    when nil
      mode = :ignore
    when Element::Slide
      target = content.body
      @canvas << content
      mode = :display
    when TitleSlide
      target = content
      @canvas << content
      mode = :display
    when SlidePropertySetter, NoteSetter
      target = content
      mode = :property
    else
      case mode
      when :display
        target << content
      when :property
        target.apply(content)
      end
    end
  end
  burn_out_pause_targets
end
convert_smart_quote(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 250
def convert_smart_quote(element)
  Text.new(Parser::Ext::Entity::TABLE[element.value.to_s])
end
convert_strikethrough(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 427
def convert_strikethrough(element)
  DeletedText.new(text(element.value))
end
convert_strong(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 371
def convert_strong(element)
  Emphasis.new(Emphasis.new(convert_container(element)))
end
convert_table(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 258
def convert_table(element)
  table = Table.new
  convert_container(element).each do |item|
    table << item
  end
  table
end
convert_tag(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 415
def convert_tag(element)
  name = element.attr["name"]
  if name.nil?
    raise ParseError, _("tag name is missing.")
  end
  if element.children.empty?
    CustomTag.new(name)
  else
    CustomTag.new(name, convert_container(element))
  end
end
convert_tbody(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 279
def convert_tbody(element)
  TableBody.new(convert_container(element))
end
convert_td(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 287
def convert_td(element)
  if @in_table_header
    header = TableHeader.new(convert_container(element))
    def header.default_align
      Pango::Alignment::CENTER
    end
    header
  else
    TableCell.new(convert_container(element))
  end
end
convert_text(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 124
def convert_text(element)
  text(element.value)
end
convert_thead(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 266
def convert_thead(element)
  in_table_header do
    TableHead.new(convert_container(element))
  end
end
convert_tr(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 283
def convert_tr(element)
  TableRow.new(convert_container(element))
end
convert_typographic_sym(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 254
def convert_typographic_sym(element)
  Text.new(Parser::Ext::Entity::TABLE[element.value.to_s])
end
convert_ul(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 230
def convert_ul(element)
  create_list(ItemList, convert_container(element, "ul"))
end
convert_wait(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 406
def convert_wait(element)
  WaitTag.new
end
create_list(list_class, contents) { |list, content| ... } click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 195
def create_list(list_class, contents)
  list = list_class.new
  contents.each do |content|
    list << content
    if block_given?
      yield(list, content)
    end
  end
  list
end
create_list_item(list_item_class, contents) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 206
def create_list_item(list_item_class, contents)
  list_item = list_item_class.new(contents)

  waited_paragraphs = list_item.elements.find_all do |element|
    element.is_a?(Paragraph) and element.have_wait_tag?
  end
  if waited_paragraphs.empty?
    list_item.default_visible = true
    list_item.clear_theme
  else
    waited_paragraphs.each do |paragraph|
      paragraph.default_visible = true
      paragraph.clear_theme
      unregister_pause(paragraph)
    end

    list_item.default_visible = false
    list_item.clear_theme
    register_pause(list_item)
  end

  list_item
end
create_paragraph(elements) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 149
def create_paragraph(elements)
  paragraph = Paragraph.new(elements)
  register_pause(paragraph) if paragraph.have_wait_tag?
  paragraph
end
detect_codeblock_language(element) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 316
def detect_codeblock_language(element)
  lang = element.attr["lang"]
  return lang if lang

  language = element.attr["language"]
  return language if language

  klass = element.attr["class"]
  if klass and /\Alanguage-/ =~ klass
    return $POSTMATCH
  end

  nil
end
in_table_header() { || ... } click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 272
def in_table_header
  in_table_header, @in_table_header = @in_table_header, true
  yield
ensure
  @in_table_header = in_table_header
end
make_image_from_file(element, source, **options) { |src_file, prop| ... } click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 375
def make_image_from_file(element, source, **options)
  Ext::Image.make_image_from_file(@canvas,
                                  source,
                                  body: @slides.last.body,
                                  **options) do |src_file|
    prop = element.attr
    image = yield(src_file, prop)
    [image, prop]
  end
end
text(content) click to toggle source
# File lib/rabbit/parser/markdown/converter.rb, line 120
def text(content)
  Text.new(Parser::Ext::Escape.escape_meta_character(content))
end