require 'cgi'
require 'uri'
require 'stringio'
%%{
machine dtext;
name_boundary = ':' | ';' | ',' | '.' | '!' | '?' | ')' | ']' | '<' | '>';
newline = '\r\n' | '\r' | '\n';
mention = '@' . graph+;
action mark_a1 {
a1 = p
}
action mark_a2 {
a2 = p
}
action mark_b1 {
b1 = p
}
action mark_b2 {
b2 = p
}
nonquote = ^'"';
nonbracket = ^']';
nonpipe = ^'|';
nonpipebracket = nonpipe & nonbracket;
noncurly = ^'}';
url = 'http' 's'? '://' graph+;
basic_textile_link = '"' nonquote+ >mark_a1 '"' >mark_a2 ':' url >mark_b1 @mark_b2;
bracketed_textile_link = '"' nonquote+ >mark_a1 '"' >mark_a2 ':[' url >mark_b1 @mark_b2 :>> ']';
basic_wiki_link = '[[' nonpipebracket+ >mark_a1 @mark_a2 ']]';
aliased_wiki_link = '[[' nonpipebracket+ >mark_a1 @mark_a2 '|' nonbracket+ >mark_b1 @mark_b2 ']]';
post_link = '{{' noncurly+ >mark_a1 @mark_a2 '}}';
post_id = 'post #' digit+ >mark_a1 @mark_a2;
forum_post_id = 'forum #' digit+ >mark_a1 @mark_a2;
forum_topic_id = 'topic #' digit+ >mark_a1 @mark_a2;
forum_topic_paged_id = 'topic #' digit+ >mark_a1 @mark_a2 '/p' digit+ >mark_b1 @mark_b2;
comment_id = 'comment #' digit+ >mark_a1 @mark_a2;
pool_id = 'pool #' digit+ >mark_a1 @mark_a2;
user_id = 'user #' digit+ >mark_a1 @mark_a2;
artist_id = 'artist #' digit+ >mark_a1 @mark_a2;
github_issue_id = 'issue #' digit+ >mark_a1 @mark_a2;
pixiv_id = 'pixiv #' digit+ >mark_a1 @mark_a2;
pixiv_paged_id = 'pixiv #' digit+ >mark_a1 @mark_a2 '/p' digit+ >mark_b1 @mark_b2;
inline := |*
post_id => {
id = data[a1..a2]
output << 'post #' + id + ''
};
forum_post_id => {
id = data[a1..a2]
output << 'forum #' + id + ''
};
forum_topic_id => {
id = data[a1..a2]
output << 'topic #' + id + ''
};
forum_topic_paged_id => {
id = data[a1..a2]
page = data[b1..b2]
output << 'topic #' + id + '/p' + page + ''
};
comment_id => {
id = data[a1..a2]
output << 'comment #' + id + ''
};
pool_id => {
id = data[a1..a2]
output << 'pool #' + id + ''
};
user_id => {
id = data[a1..a2]
output << 'user #' + id + ''
};
artist_id => {
id = data[a1..a2]
output << 'artist #' + id + ''
};
github_issue_id => {
id = data[a1..a2]
output << 'issue #' + id + ''
};
pixiv_id => {
id = data[a1..a2]
output << 'pixiv #' + id + ''
};
pixiv_paged_id => {
id = data[a1..a2]
page = data[b1..b2]
output << 'pixiv #' + id + '/p' + page + ''
};
post_link => {
tags = data[a1..a2]
output << '' + h(tags) + ''
};
basic_wiki_link => {
name = data[a1..a2]
title = name.tr(" ", "_").downcase
output << '' + h(name) + ''
};
aliased_wiki_link => {
name = data[b1..b2]
title = data[a1..a2].tr(" ", "_").downcase
output << '' + h(name) + ''
};
basic_textile_link => {
text = data[a1..a2]
url = data[b1..b2]
output << '' + text + ''
};
bracketed_textile_link => {
text = data[a1..a2]
url = data[b1..b2]
output << '' + text + ''
};
url => {
url = data[ts...te]
output << '' + url + ''
};
mention name_boundary => {
name = data[ts+1...te-1]
output << '@' + h(name) + '' + data[p]
};
mention => {
name = data[ts+1...te]
output << '@' + h(name) + ''
};
'[b]' => {
dstack << :b
output << ''
};
'[/b]' => {
raise SyntaxError.new("invalid [/b] tag") unless dstack[-1] == :b
dstack.pop
output << ""
};
'[i]' => {
dstack << :i
output << ''
};
'[/i]' => {
raise ParseError.new("invalid [/i] tag") unless dstack[-1] == :i
dstack.pop
output << ""
};
'[s]' => {
dstack << :s
output << ""
};
'[/s]' => {
raise ParseError.new("invalid [/s] tag") unless dstack[-1] == :s
dstack.pop
output << ""
};
'[u]' => {
dstack << :u
output << ""
};
'[/u]' => {
raise ParseError.new("invalid [/u] tag") unless dstack[-1] == :u
dstack.pop
output << ""
};
'[tn]' => {
dstack << :tn
output << '
' }; '[/tn]' => { raise ParseError.new("invalid [/tn] tag") unless dstack[-1] == :tn dstack.pop output << "
" }; '[/quote]' => { raise ParseError.new("invalid [/quote] tag") unless dstack[-1] == :quote dstack.pop output << "" fret; }; '[spoiler]' => { dstack << :inline_spoiler output << '' }; '[/spoiler]' => { if dstack[-1] == :inline_spoiler output << "" dstack.pop elsif dstack[-1] == :block_spoiler output << "" dstack.pop fret; else raise SyntaxError.new("invalid [/spoiler] tag") end }; '[/expand]' => { if dstack[-1] == :expand output << '' dstack.pop fret; else raise SyntaxError.new("invalid [/expand] tag") end }; '&' => { output << "&" }; '<' => { output << "<" }; '>' => { output << ">" }; newline{2,} { output << close_stack(output, dstack) fret; }; newline => { output << "" dstack << :quote fcall inline; }; '[spoiler]' => { output << '' dstack << :block_spoiler fcall inline; }; '[code]' => { output << '' dstack << :block_code fcall code; }; '[expand]' => { output << '