class Markascend::LineUnit

process a line with (maybe) a followed up indented block

Public Instance Methods

parse(out=nil) click to toggle source
# File lib/markascend/line_unit.rb, line 5
def parse out=nil
  @out = []
  @src = ::StringScanner.new line
  parsers = env.line_units
  while parsers.any?{|p| send p}
  end

  if out
    @out.each do |token|
      out << token
    end
  else
    @out.join
  end
end
parse_bold_italic(emit=true) click to toggle source
# File lib/markascend/line_unit.rb, line 136
def parse_bold_italic emit=true
  pos = @src.pos
  if s = @src.scan(/\*\*/)
    term = /\*\*/
    out = ['<b>']
    out_end = '</b>'
  elsif s = @src.scan(/\*/)
    term = /\*/
    out = ['<i>']
    out_end = '</i>'
  else
    return
  end

  loop do
    if res = @src.scan(/\\[\\\*]/)
      out << res[1]
    elsif @src.scan(term)
      out << out_end
      break
    elsif res = parse_bold_italic(false)
      out << res
    elsif res = parse_char(false)
      out << res
    else
      # failed
      @src.pos = pos
      return
    end
  end

  if emit
    @out << out.join
    true
  else
    out.join
  end
end
parse_char(emit=true) click to toggle source
# File lib/markascend/line_unit.rb, line 175
def parse_char emit=true
  # entity list generated by:
  # ruby -rregexp_optimized_union -e'puts Regexp.optimized_union($stdin.read.scan(/(?<=ENTITY )\w+/)).source' < tools/html4_entities.dtd
  # dtd from http://www.w3.org/TR/html4/sgml/entities.html
  if c = @src.scan(/
      &(?:
        n(?:bsp|ot|tilde)|i(?:excl|quest|grave|acute|circ|uml)|c(?:e(?:nt|dil)|urren|opy|cedil)|p(?:ound|lusmn|ara)|y(?:en|acute|uml)|brvbar|s(?:ect|hy|up[123]|zlig)|u(?:ml|grave|acute|circ|uml)|o(?:rd[fm]|grave|acute|circ|tilde|uml|slash)|laquo|r(?:eg|aquo)|m(?:acr|i(?:cro|ddot))|d(?:eg|ivide)|a(?:c(?:ute|irc)|grave|acute|tilde|uml|ring|elig)|frac(?:1[24]|34)|A(?:grave|acute|circ|tilde|uml|ring|Elig)|Ccedil|E(?:grave|acute|circ|uml|TH)|I(?:grave|acute|circ|uml)|Ntilde|O(?:grave|acute|circ|tilde|uml|slash)|t(?:imes|horn)|U(?:grave|acute|circ|uml)|Yacute|THORN|e(?:grave|acute|circ|uml|th)
        |\#\d{4}
        |\#x\h{4}
      );
    /x)
  elsif c = @src.scan(/\\\W/)
    c = ::Markascend.escape_html c[1]
  elsif c = @src.scan(/\n/)
    c = :'<br>'
  elsif c = @src.scan(/./)
    c = ::Markascend.escape_html c
  else
    return
  end

  if emit
    @out << c
    true
  else
    c
  end
end
parse_inline_code() click to toggle source

the same as markdown

# File lib/markascend/line_unit.rb, line 22
def parse_inline_code
  if s = @src.scan(/
      (`{1,})(\ ?)
      .*?
      \2\1
    /x)
    s =~ /^
      (`{1,})(\ ?)
      (.*?)
      \2\1
    $/x
    @out << (::Markascend.hilite $3, env.hi, true)
    true
  end
end
parse_macro() click to toggle source
# File lib/markascend/line_unit.rb, line 59
def parse_macro
  start = @src.pos
  return unless macro = @src.scan(/\\(?!\d)\w+/)
  macro = macro[1..-1]
  if block = scan_lexical_parens
    inline_content = @src.string[start..(@src.pos)]
  elsif block = scan_recursive_braces
    inline_content = @src.string[start..(@src.pos)]
  else
    block = self.block
  end
  @out << ::Markascend::Macro.new(env, block, inline_content).parse(macro)
  true
end
parse_math() click to toggle source

no escape chars, but \ and $ are treated as atomic parsing units

# File lib/markascend/line_unit.rb, line 39
def parse_math
  if (s = @src.scan /\$(?:\\[\\\$]|[^\$])*\$/)
    @out << '<code class="math">'
    @out << (::Markascend.escape_html s[1...-1])
    @out << '</code>'
    true
  end
end
scan_lexical_parens() click to toggle source

(…)

# File lib/markascend/line_unit.rb, line 216
def scan_lexical_parens
  if s = @src.scan(/
      \(
        (?: \\ [\\\)] | [^\)] )+  # lexical rule
      \)
    /x)
    s[1...-1].gsub(/\\[\)\\]/){|x| x[1]}
  end
end
scan_recursive_braces() click to toggle source

{…}

# File lib/markascend/line_unit.rb, line 205
def scan_recursive_braces
  if s = @src.scan(/
      (?<braces> \{
        ([^\{]+ | \g<braces>)*  # recursive rule
      \})
    /x)
    s[1...-1]
  end
end