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_auto_link()
click to toggle source
# File lib/markascend/line_unit.rb, line 48 def parse_auto_link # TODO make protocol configurable if (s = @src.scan /(https|http|ftp|mailto)\:\/\/\S+/) s.gsub! /"/, '\\"' @out << '<a href="#{s}">' @out << (::Markascend.escape_html s) @out << '</a>' true 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_link()
click to toggle source
# File lib/markascend/line_unit.rb, line 74 def parse_link pos = @src.pos return unless @src.scan(/\[/) footnote = @src.scan(/[\.\:]/) content = '' loop do if res = @src.scan(/\]/) break elsif res = parse_char(false) content << res else # failed @src.pos = pos return end end if footnote and env.sandbox scan_lexical_parens || scan_recursive_braces @out << ::Markascend.escape_html(@src.string[pos..(@src.pos)]) return true end case footnote when '.' unless explain = scan_lexical_parens || scan_recursive_braces @src.pos = pos return end footnotes = env.footnotes if content =~ /\A\s*\z/ content = footnotes.size + 1 end raise "Already defined footnote: #{content}" if footnotes.has_key?(content) footnotes[content] = explain # TODO id prefix configurable @out << %Q|<a href="#footnote-#{footnotes.size}">#{content}</a>| true when ':' footnotes = env.footnotes if content =~ /\A\s*(\d+)\s*\z/ @out << [:footnote_id_ref, $1.to_i] else content.strip! @out << [:footnote_acronym_ref, content] end true else if addr = scan_lexical_parens || scan_recursive_braces # TODO smarter addr to recognize things like a.b.com addr = ::Markascend.escape_attr addr @out << %Q|<a href="#{addr}">#{content}</a>| true else @src.pos = pos nil end 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