2012-05-13 08:22:42 +07:00
|
|
|
require 'cgi'
|
2012-05-09 11:59:21 +07:00
|
|
|
require 'nokogiri'
|
|
|
|
|
|
|
|
module DText
|
|
|
|
def parse(str)
|
2012-05-13 08:22:42 +07:00
|
|
|
state = [:newline]
|
|
|
|
result = ""
|
2012-05-09 11:59:21 +07:00
|
|
|
|
|
|
|
# Normalize newlines
|
2012-05-13 08:22:42 +07:00
|
|
|
str.strip
|
|
|
|
str.gsub!(/(\r?\n)/, "\n")
|
|
|
|
str.gsub!(/\n{3,}/, "\n\n")
|
2012-05-09 11:59:21 +07:00
|
|
|
|
2012-05-10 12:35:11 +07:00
|
|
|
# Keep newline, use carriage return for split
|
2012-05-13 08:22:42 +07:00
|
|
|
str.gsub!(/(\n+)/, '\1' + "\r")
|
2012-05-10 12:35:11 +07:00
|
|
|
data = str.split("\r")
|
2012-05-09 11:59:21 +07:00
|
|
|
|
|
|
|
data.each do |d|
|
2012-05-13 08:22:42 +07:00
|
|
|
result << parseline(d, state)
|
2012-05-09 11:59:21 +07:00
|
|
|
end
|
|
|
|
|
2012-05-13 08:22:42 +07:00
|
|
|
Nokogiri::HTML::DocumentFragment.parse(result).to_html
|
|
|
|
end
|
|
|
|
|
|
|
|
def parseinline(str)
|
|
|
|
str = CGI.escapeHTML str
|
2012-05-13 09:30:00 +07:00
|
|
|
parseurl str
|
2012-05-13 14:33:00 +07:00
|
|
|
str.gsub! /\[(\/)?b\]/, '<\1strong>'
|
2012-05-13 08:22:42 +07:00
|
|
|
str.gsub! /\[(\/)?i\]/, '<\1em>'
|
|
|
|
str.gsub! /[Pp]ost #(\d+)/, '<a href="/post/show/\1">post #\1</a>'
|
|
|
|
str.gsub! /[Ff]orum #(\d+)/, '<a href="/forum/show/\1">forum #\1</a>'
|
|
|
|
str.gsub! /[Cc]omment #(\d+)/, '<a href="/comment/show/\1">comment #\1</a>'
|
|
|
|
str.gsub! /[Pp]ool #(\d+)/, '<a href="/pool/show/\1">pool #\1</a>'
|
2012-05-13 09:30:00 +07:00
|
|
|
str.gsub! /\[spoilers?\]/, '<span href="#" class="spoiler" onclick="Comment.spoiler(this); return false;"><span class="spoilerwarning">spoiler</span></span><span class="spoilertext" style="display: none">'
|
|
|
|
str.gsub! /\[spoilers?=(.+)\]/, '<span href="#" class="spoiler" onclick="Comment.spoiler(this); return false;"><span class="spoilerwarning">\1</span></span><span class="spoilertext" style="display: none">'
|
|
|
|
str.gsub! /\[\/spoilers?\]/, '</span>'
|
2012-05-13 08:22:42 +07:00
|
|
|
str.gsub! /\n/, '<br>'
|
2012-05-13 09:30:00 +07:00
|
|
|
str
|
2012-05-13 08:22:42 +07:00
|
|
|
end
|
|
|
|
|
|
|
|
def parseline(str, state)
|
2012-05-13 14:30:44 +07:00
|
|
|
if state.last.to_s =~ /\d/ or str =~ /^\*+\s+/
|
2012-05-13 08:22:42 +07:00
|
|
|
parselist str, state
|
|
|
|
elsif str =~ /^(h[1-6])\.\s*(.+)\n*/
|
|
|
|
tag = $1 if $1
|
|
|
|
str = "<#{tag}>#{parseinline($2)}</#{tag}>"
|
|
|
|
else
|
|
|
|
parseparagraph str, state
|
|
|
|
end
|
2012-05-09 11:59:21 +07:00
|
|
|
end
|
|
|
|
|
2012-05-13 08:22:42 +07:00
|
|
|
def parselist(str, state)
|
|
|
|
parseinline str
|
|
|
|
html = ""
|
|
|
|
if state.last == :newline
|
|
|
|
state.push "1"
|
|
|
|
html << "<ul>"
|
|
|
|
else
|
|
|
|
n = str.split()[0].count("*")
|
|
|
|
if n < state.last.to_i
|
|
|
|
html << '</ul></li>' * (state.last.to_i - n - 1)
|
|
|
|
state[-1] = n.to_s
|
|
|
|
elsif n > state.last.to_i
|
|
|
|
html << '<li><ul>'
|
|
|
|
state[-1] = (state.last.to_i + 1).to_s
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if str =~ /^[^\*]/
|
|
|
|
state.pop
|
|
|
|
html << "</ul>"
|
|
|
|
return html + parseline(str, state)
|
|
|
|
end
|
2012-05-13 09:30:00 +07:00
|
|
|
html << str.gsub(/\*+\s+(.+)\n*/) do
|
|
|
|
"<li>#{parseinline($1)}</li>"
|
|
|
|
end
|
2012-05-13 08:22:42 +07:00
|
|
|
end
|
2012-05-09 11:59:21 +07:00
|
|
|
|
2012-05-13 08:22:42 +07:00
|
|
|
def parseparagraph(str, state)
|
|
|
|
html = ""
|
|
|
|
if state.last == :newline
|
|
|
|
state.push :p
|
|
|
|
html << "<p>"
|
|
|
|
end
|
|
|
|
html << str.gsub(/(.+)\n*$/) do
|
|
|
|
parseinline($1)
|
|
|
|
end
|
|
|
|
if state.last == :p and str =~ /\n\n$/
|
|
|
|
state.pop
|
|
|
|
html << "</p>"
|
|
|
|
end
|
|
|
|
html
|
2012-05-09 11:59:21 +07:00
|
|
|
end
|
|
|
|
|
2012-05-13 08:22:42 +07:00
|
|
|
def parseurl(str)
|
|
|
|
str
|
|
|
|
end
|
2012-05-09 11:59:21 +07:00
|
|
|
end
|