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 14:57:31 +07:00
|
|
|
state = ['newline']
|
2012-05-13 08:22:42 +07:00
|
|
|
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)
|
2012-05-13 14:53:33 +07:00
|
|
|
str = CGI.escapeHTML str
|
2012-05-14 04:31:12 +07:00
|
|
|
str.gsub!(/\[\[(.+?)\|(.+?)\]\]/) do
|
|
|
|
"<a href=\"/wiki/show?title=#{CGI.escape(CGI.unescapeHTML($1.tr(" ", "_")))}\">#{$2}</a>"
|
|
|
|
end
|
|
|
|
str.gsub!(/\[\[(.+?)\]\]/) do
|
|
|
|
t = $1 if $1
|
|
|
|
"<a href=\"/wiki/show?title=#{CGI.escape(CGI.unescapeHTML(t.tr(" ", "_")))}\">#{t}</a>"
|
|
|
|
end
|
|
|
|
str.gsub!(/\{\{(.+?)\}\}/) do
|
|
|
|
t = $1 if $1
|
|
|
|
"<a href=\"/post/index?tags=#{CGI.escape(CGI.unescapeHTML(t))}\">#{t}</a>"
|
|
|
|
end
|
2012-05-13 14:40:39 +07:00
|
|
|
str.gsub! /\[b\](.+)\[\/b\]/, '<strong>\1</strong>'
|
|
|
|
str.gsub! /\[i\](.+)\[\/i\]/, '<em>\1</em>'
|
2012-05-14 04:31:12 +07:00
|
|
|
str.gsub! /(^|\s+)[Pp]ost #(\d+)(\s+|$)/, '\1<a href="/post/show/\2">post #\2</a>\3'
|
|
|
|
str.gsub! /(^|\s+)[Ff]orum #(\d+)(\s+|$)/, '\1<a href="/forum/show/\2">forum #\2</a>\3'
|
|
|
|
str.gsub! /(^|\s+)[Cc]omment #(\d+)(\s+|$)/, '\1<a href="/comment/show/\2">comment #\2</a>\3'
|
|
|
|
str.gsub! /(^|\s+)[Pp]ool #(\d+)(\s+|$)/, '\1<a href="/pool/show/\2">pool #\2</a>\3'
|
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">'
|
2012-05-13 22:38:58 +07:00
|
|
|
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">'
|
2012-05-13 09:30:00 +07:00
|
|
|
str.gsub! /\[\/spoilers?\]/, '</span>'
|
2012-05-14 04:31:12 +07:00
|
|
|
str.gsub! /\[quote\]/, '<blockquote><div>'
|
|
|
|
str.gsub! /\[\/quote\]/, '</div></blockquote>'
|
2012-05-13 08:22:42 +07:00
|
|
|
str.gsub! /\n/, '<br>'
|
2012-05-16 00:32:02 +07:00
|
|
|
str = parseurl(CGI.unescapeHTML(str))
|
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:57:31 +07:00
|
|
|
if state.last =~ /\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
|
2012-05-13 16:32:12 +07:00
|
|
|
parseinline str
|
2012-05-13 08:22:42 +07:00
|
|
|
end
|
2012-05-09 11:59:21 +07:00
|
|
|
end
|
|
|
|
|
2012-05-13 08:22:42 +07:00
|
|
|
def parselist(str, state)
|
|
|
|
html = ""
|
2012-05-13 15:17:17 +07:00
|
|
|
if not state.last =~ /\d/
|
2012-05-13 08:22:42 +07:00
|
|
|
state.push "1"
|
|
|
|
html << "<ul>"
|
|
|
|
else
|
|
|
|
n = str.split()[0].count("*")
|
|
|
|
if n < state.last.to_i
|
2012-05-13 18:20:15 +07:00
|
|
|
html << '</ul></li>' * (state.last.to_i - n)
|
2012-05-13 08:22:42 +07:00
|
|
|
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
|
2012-05-16 01:26:30 +07:00
|
|
|
if not str =~ /^\*+\s+/
|
2012-05-13 08:22:42 +07:00
|
|
|
state.pop
|
2012-05-13 16:15:04 +07:00
|
|
|
html << "</ul>"
|
2012-05-13 08:22:42 +07:00
|
|
|
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 parseurl(str)
|
2012-05-16 01:26:30 +07:00
|
|
|
url_pattern = /(h?ttps?:\/\/([\w\-_]+)(\.[\w\-_]+)*(:\d+)*(\/[^\s]*)*)/
|
2012-05-16 01:01:23 +07:00
|
|
|
str = str.gsub(/\s+<<\s*(.+?)\s*\|\s*(.+?)\s*>>\s+/) do |match|
|
2012-05-16 00:32:02 +07:00
|
|
|
link = $1 if $1
|
|
|
|
name = $2 if $2
|
|
|
|
if link =~ url_pattern
|
|
|
|
" <a href=\"#{$1}\">#{name}</a> "
|
|
|
|
end
|
|
|
|
end
|
|
|
|
str = str.gsub(/\s+"(.+?)":#{url_pattern}/, ' <a href="\2">\1</a>')
|
|
|
|
str = str.gsub(/\s+<<\s*#{url_pattern}\s*>>\s+/, ' <a href="\1">\1</a> ')
|
|
|
|
str = str.gsub(/\s+#{url_pattern}/, ' <a href="\1">\1</a>')
|
2012-05-13 08:22:42 +07:00
|
|
|
str
|
|
|
|
end
|
2012-05-16 01:26:30 +07:00
|
|
|
|
|
|
|
module_function :parse, :parseline, :parseinline, :parselist, :parseurl
|
2012-05-09 11:59:21 +07:00
|
|
|
end
|