module Schizm::Parse

Public Class Methods

hash() click to toggle source

Markup hash accessor.

# File lib/schizm/parse.rb, line 46
def self.hash
  return @@hash
end
highlight(filename, input, table) click to toggle source

Highlight source.

# File lib/schizm/parse.rb, line 462
def self.highlight filename, input, table
  elems = Markup.new
  sscan = StringScanner.new input
  until sscan.eos?
    if sscan.skip /\p{Space}+/um
      elems.add_elems(String.new(sscan[0]).html)
      next
    end
    if sscan.skip CHUNK_LABEL
      label = String.new(sscan[1]).unescape("]")
      elems.add_elems(
        Markup.new("a")
        .add_attrs("class" => "chunk")
        .add_attrs("href" => ChunkRef.new(filename, label))
        .add_elems(line_elems(filename, label)))
      next
    end
    table.each do |entry|
      if sscan.skip entry[1]
        if entry[0] == nil
          elems.add_elems(String.new(sscan[0]).html)
        else
          elems.add_elems(
            Markup.new("span")
            .add_attrs("class" => entry[0])
            .add_elems(String.new(sscan[0]).html))
        end
        break
      end
    end
  end
  return elems
end
images() click to toggle source

Image hash accessor.

# File lib/schizm/parse.rb, line 74
def self.images
  return @@images
end
line_elems(filename, input) click to toggle source

Parse line elements.

# File lib/schizm/parse.rb, line 120
def self.line_elems filename, input
  elems = Markup.new
  sscan = StringScanner.new input.strip
  max_glyph = nil
  max_glyph_len = 0
  max_glyph_match = lambda do
    max_glyph = nil
    max_glyph_len = 0
    for glyph in GLYPH
      glyph_len = sscan.match? glyph[0]
      if glyph_len and
         glyph_len > max_glyph_len
        max_glyph_len = glyph_len
        max_glyph = glyph
      end
    end
    sscan.pointer =
    sscan.pointer + max_glyph_len
    return false if max_glyph_len == 0
    return true
  end
  until sscan.eos?
    elems.add_elems(
    case
    when sscan.skip(SPACE) then " "
    when sscan.skip(HTML_ENTITY) then sscan[0]
    when sscan.skip(HTML_ESCAPE) then sscan[0].codepoints[0]
    when sscan.skip(CHAR_ESCAPE) then sscan[0].codepoints[0]
    when sscan.skip(LINK_REF_PARENS)
      text = String.new(sscan[1]).unescape("]")
      info = String.new(sscan[2]).unescape(")")
      sscan2 = StringScanner.new(info)
      attrs = Hash.new
      attrs["target"] = "_blank"
      until sscan2.eos?
        case
        when sscan2.skip(/'((?:[^\\']*(?:\\.)*)*)'/u) then attrs["title"] = sscan2[1]
        when sscan2.skip(/"((?:[^\\"]*(?:\\.)*)*)"/u) then attrs["title"] = sscan2[1]
        when sscan2.skip(/\p{Graph}+/u) then attrs["href"] = sscan2[0]
        when sscan2.skip(/\p{Space}+/u) then nil
        end
      end
      Markup.new("a")
      .add_attrs(attrs)
      .add_elems(line_elems(filename, text))
    when sscan.skip(LINK_REF_BRACKS)
      text =
      name = String.new(sscan[1]).unescape("]")
      name = String.new(sscan[2]).unescape("]") if sscan[2]
      attrs = Hash.new
      attrs["target"] = "_blank"
      attrs["title"] = HashAttr.new @@links[filename][name], "title"
      attrs["href"] = HashAttr.new @@links[filename][name], "href"
      Markup.new("a")
      .add_attrs(attrs)
      .add_elems(line_elems(filename, text))
    when sscan.skip(CENTER_MATH)
      Markup.new("script")
      .add_attrs(CENTER_MATH_ATTRS)
      .add_elems(String.new(sscan[1]).slim)
    when sscan.skip(INLINE_MATH)
      Markup.new("script")
      .add_attrs(INLINE_MATH_ATTRS)
      .add_elems(String.new(sscan[1]).slim)
    when sscan.skip(INLINE_EMPH)
      depth = sscan[1].size
      inner = line_elems(filename, sscan[2])
      case
      when depth <= 1
        Markup.new("em").add_elems(inner)
      when depth == 2
        Markup.new("strong").add_elems(inner)
      when depth >= 3
        Markup.new("strong").add_elems(
            Markup.new("em").add_elems(inner))
      end
    when sscan.skip(INLINE_CODE)
      Markup.new("code")
      .add_elems(String.new(sscan[1]).unescape("`").html)
    when sscan.skip(INLINE_SUP)
      Markup.new("sup").add_elems(line_elems(filename, sscan[1]))
    when sscan.skip(INLINE_SUB)
      Markup.new("sub").add_elems(line_elems(filename, sscan[1]))
    when sscan.skip(INLINE_INS)
      Markup.new("ins").add_elems(line_elems(filename, sscan[1]))
    when sscan.skip(INLINE_DEL)
      Markup.new("del").add_elems(line_elems(filename, sscan[1]))
    when max_glyph_match.call
      max_glyph[1]
    when sscan.skip(/\w+|\S/)
      sscan[0]
    end)
  end
  return elems
end
page_elems(filename, input) click to toggle source

Parse page elements.

# File lib/schizm/parse.rb, line 217
def self.page_elems filename, input
  elems = Markup.new
  sscan = StringScanner.new(
          String.new(input)
                .expand_tab(4).trim_blank
                .concat("\n"))
  until sscan.eos?
    elems.add_elems(
    case
    when sscan.skip(EMPTY_LINE) then nil
    when sscan.skip(EOB_MARKER) then nil
    when sscan.skip(HRULE)
      Markup.new "hr"
    when sscan.skip(HEADING_ATX)
      type = String.new sscan[1]
      text = String.new sscan[2]
      Markup.new(
        case type.size
        when 1 then "h1"
        when 2 then "h2"
        when 3 then "h3"
        when 4 then "h4"
        when 5 then "h5"
        when 6 then "h6"
        end).add_elems(line_elems(filename, text))
    when sscan.skip(HEADING_SETEXT)
      type = String.new sscan[2]
      text = String.new sscan[1]
      slug = text.slugify
      Markup.new(
        case type[0]
        when "=" then "h1"
        when "-" then "h2"
        end).add_attrs("id" => slug)
            .add_attrs("class" => "title")
            .add_elems(line_elems(filename, text))
    when sscan.skip(LINK_DEF)
      name = String.new(sscan[1]).unescape("]")
      sscan2 = StringScanner.new(sscan[2])
      until sscan2.eos?
        case
        when sscan2.skip(/'((?:[^\\']*(?:\\.)*)*)'/u) then @@links[filename][name]["title"] = sscan2[1]
        when sscan2.skip(/"((?:[^\\"]*(?:\\.)*)*)"/u) then @@links[filename][name]["title"] = sscan2[1]
        when sscan2.skip(/\p{Graph}+/u) then @@links[filename][name]["href"] = sscan2[0]
        when sscan2.skip(/\p{Space}+/u) then nil
        end
      end
      nil
    when sscan.skip(IMAGE_DEF)
      name = String.new(sscan[1]).unescape("]")
      sscan2 = StringScanner.new(sscan[2])
      until sscan2.eos?
        case
        when sscan2.skip(/w=(\d+)/u) then @@images[filename][name]["width"] = sscan2[1]
        when sscan2.skip(/h=(\d+)/u) then @@images[filename][name]["height"] = sscan2[1]
        when sscan2.skip(/\p{Graph}+/u) then @@images[filename][name]["src"] = sscan2[0]
        when sscan2.skip(/\p{Space}+/u) then nil
        end
      end
    when sscan.skip(/^[ ]{0,3}#{IMAGE_REF_PARENS}$/u)
      text = String.new(sscan[1]).unescape("]")
      info = String.new(sscan[2]).unescape(")")
      sscan2 = StringScanner.new(info)
      attrs = Hash.new
      attrs["alt"] = text
      until sscan2.eos?
        case
        when sscan2.skip(/w=(\d+)/u) then attrs["width"] = sscan2[1]
        when sscan2.skip(/h=(\d+)/u) then attrs["height"] = sscan2[1]
        when sscan2.skip(/\p{Graph}+/u) then attrs["src"] = sscan2[0]
        when sscan2.skip(/\p{Space}+/u) then nil
        end
      end
      Markup.new("img").add_attrs(attrs)
    when sscan.skip(/^[ ]{0,3}#{IMAGE_REF_BRACKS}$/u)
      text = 
      name = String.new(sscan[1]).unescape("]")
      name = String.new(sscan[2]).unescape("]") if sscan[2]
      attrs = Hash.new
      attrs["alt"] = text
      attrs["src"] = HashAttr.new @@images[filename][name], "src"
      attrs["width"] = HashAttr.new @@images[filename][name], "width"
      attrs["height"] = HashAttr.new @@images[filename][name], "height"
      Markup.new("img").add_attrs(attrs)
    when sscan.skip(/^#{CHUNK_LABEL}/u)
      div = nil
      chunk = Chunk.hash[filename][String.new(sscan[1]).unescape("]")]
      case
      when sscan.skip(/[ ]*->[ ]*(.*?)\n/u)
        chunk.target = sscan[1].strip
      when sscan.skip(/[ ]*::[ ]*(.*?)\n/u)
        case sscan[1].strip
        when "Share" then chunk.share = true
        when "Local" then chunk.share = false
        else raise "Unknown attribute."
        end
      when sscan.skip(/[ ]*\+=[ ]*(?:#{CHUNK_BLOCK})?\n/u)
        label = sscan[1]
        block = sscan.scan_until(END_INDENT)
        block = String.new(block).erase(INDENT).trim
        label = String.new(label).unescape(")") if label
        chunk.push block, label
        div =
        Markup.new("div")
        .add_attrs("id" => chunk.id)
        .add_attrs("class" => "panel")
        .add_elems([
          Markup.new("div")
          .add_attrs("class" => "panel-head")
          .add_elems([
            Markup.new("div")
            .add_attrs("style" => "float: left; width: 75%;")
            .add_elems([
              Markup.new("div")
              .add_attrs("class" => "the-chunk")
              .add_elems(line_elems(filename, chunk.label)),
              case
              when label
                Markup.new("div")
                .add_attrs("class" => "the-block")
                .add_elems(line_elems(filename, label))
              else nil
              end
            ]),
            Markup.new("div")
            .add_attrs("style" => "float: right;")
            .add_elems([
              Markup.new("a").add_attrs("class" => "panel-link", "href" => BlockRef.new(chunk, chunk.blocks.size - 1)).add_elems(Markup.new("span").add_attrs("class" => "genericons-neue genericons-neue-previous")),
              Markup.new("a").add_attrs("class" => "panel-link", "href" => BlockRef.new(chunk, chunk.blocks.size + 1)).add_elems(Markup.new("span").add_attrs("class" => "genericons-neue genericons-neue-next")),
            ]),
            Markup.new("div").add_attrs("style" => "clear: both;")
          ]),
          Markup.new("div")
          .add_attrs("class" => "panel-body")
          .add_elems(Markup.new("pre").add_elems(highlight(filename, block, HICPP)))
        ])
      end
      div
    when sscan.skip(ENTER_ASIDE)
      text = sscan.scan_until END_INDENT
      text = String.new(text).erase INDENT
      Markup.new("div")
      .add_attrs("class" => "aside")
      .add_elems([
        Markup.new("div")
        .add_attrs("class" => "icon-holder")
        .add_elems(
          Markup.new("span")
          .add_attrs("class" => "genericons-neue genericons-neue-info")),
        page_elems(filename, text)
      ])
    when sscan.skip(ENTER_ALERT)
      text = sscan.scan_until END_INDENT
      text = String.new(text).erase INDENT
      Markup.new("div")
      .add_attrs("class" => "alert")
      .add_elems([
        Markup.new("div")
        .add_attrs("class" => "icon-holder")
        .add_elems(
          Markup.new("span")
          .add_attrs("class" => "genericons-neue genericons-neue-notice")),
        page_elems(filename, text)
      ])
    when sscan.skip(ENTER_BUG)
      text = sscan.scan_until END_INDENT
      text = String.new(text).erase INDENT
      Markup.new("div")
      .add_attrs("class" => "alert")
      .add_elems([
        Markup.new("div")
        .add_attrs("class" => "icon-holder")
        .add_elems(
          Markup.new("span")
          .add_attrs("class" => "genericons-neue genericons-neue-bug")),
        page_elems(filename, text)
      ])
    when sscan.skip(ENTER_QUOTE)
      text = sscan.scan_until END_INDENT
      text = String.new(text).erase INDENT
      Markup.new("blockquote")
            .add_elems(page_elems(filename, text))
    when (sscan.match? ENTER_OLIST)
      list = Markup.new "ol"
      while sscan.skip ENTER_OLIST
        text = sscan.scan_until END_INDENT
        text = String.new(text).erase INDENT
        item = Markup.new("li").add_elems(page_elems(filename, text))
        list.add_elems item
        sscan.skip EMPTY_LINES
      end
      list
    when (sscan.match? ENTER_ULIST)
      list = Markup.new "ul"
      while sscan.skip ENTER_ULIST
        text = sscan.scan_until END_INDENT
        text = String.new(text).erase INDENT
        item = Markup.new("li").add_elems(page_elems(filename, text))
        list.add_elems item
        sscan.skip EMPTY_LINES
      end
      list
    when (sscan.match? ENTER_TLIST)
      list = Markup.new "ul"
      list.add_attrs("class" => "tl")
      while sscan.skip ENTER_TLIST
        type = sscan[1]
        text = sscan.scan_until END_INDENT
        text = String.new(text).erase INDENT
        item = Markup.new("li")
        item.add_attrs("class" => "li-todo") if type[0] == " "
        item.add_attrs("class" => "li-done") if type[0] != " "
        item.add_elems page_elems(filename, text)
        list.add_elems item
        sscan.skip EMPTY_LINES
      end
      list
    when (sscan.match? ENTER_DLIST)
      list = Markup.new "dl"
      while sscan.skip ENTER_DLIST
        term = sscan[1]
        text = sscan.scan_until END_INDENT
        text = String.new(text).erase INDENT
        list.add_elems(Markup.new("dt").add_elems(line_elems(filename, term)))
        list.add_elems(Markup.new("dd").add_elems(page_elems(filename, text)))
        sscan.skip EMPTY_LINES
      end
      list
    when sscan.match?(ENTER_CODE)
      text = sscan.scan_until END_INDENT
      text = String.new(text).erase INDENT
      Markup.new("pre")
      .add_elems(
        Markup.new("code")
        .add_elems(String.new(text).trim.html))
    when sscan.match?(ENTER_TEXT)
      text = sscan.scan_until END_SIMPLE
      text = String.new(text).erase EOB_MARKER
      Markup.new("p").add_elems(line_elems(filename, text))
    end)
  end
  return elems
end