diff options
-rw-r--r-- | data/style.css | 1 | ||||
-rw-r--r-- | lib/VNDB/BBCode.pm | 59 | ||||
-rwxr-xr-x | util/bbcode-test.pl | 16 |
3 files changed, 63 insertions, 13 deletions
diff --git a/data/style.css b/data/style.css index 99394404..dedeeedf 100644 --- a/data/style.css +++ b/data/style.css @@ -104,6 +104,7 @@ p.locked { float: right; color: $standout$; font-style: italic; margin: 0!i .grayedout { color: $grayedout$ } b.grayedout { font-weight: normal } i.grayedout { font-style: normal } +.underline { text-decoration: underline } #maincontent h2 b { font: 13px "Tahoma", "Arial", sans-serif; font-weight: normal; } p.description { margin: 10px 100px!important; } b.done { font-weight: normal; color: $statok$ } diff --git a/lib/VNDB/BBCode.pm b/lib/VNDB/BBCode.pm index d11171c5..f6ab93d9 100644 --- a/lib/VNDB/BBCode.pm +++ b/lib/VNDB/BBCode.pm @@ -8,6 +8,10 @@ use TUWF::XML 'xml_escape'; our @EXPORT = qw/bb2html bb2text bb_subst_links/; # Supported BBCode: +# [b] .. [/b] +# [i] .. [/i] +# [u] .. [/u] +# [s] .. [/s] # [spoiler] .. [/spoiler] # [quote] .. [/quote] # [code] .. [/code] @@ -17,7 +21,8 @@ our @EXPORT = qw/bb2html bb2text bb_subst_links/; # dblink: v+, v+.+, d+#+, d+#+.+ # # Permitted nesting of formatting codes: -# spoiler -> url, raw, link, dblink +# inline = b,i,u,s,spoiler +# inline -> inline, url, raw, link, dblink # quote -> anything # code -> nothing # url -> raw @@ -29,10 +34,18 @@ our @EXPORT = qw/bb2html bb2text bb_subst_links/; # Returns: ($token, @arg) on successful parse, () otherwise. # Trivial open and close actions +sub _b_start { if(lc$_[1] eq '[b]') { push @{$_[0]}, 'b'; ('b_start') } else { () } } +sub _i_start { if(lc$_[1] eq '[i]') { push @{$_[0]}, 'i'; ('i_start') } else { () } } +sub _u_start { if(lc$_[1] eq '[u]') { push @{$_[0]}, 'u'; ('u_start') } else { () } } +sub _s_start { if(lc$_[1] eq '[s]') { push @{$_[0]}, 's'; ('s_start') } else { () } } sub _spoiler_start { if(lc$_[1] eq '[spoiler]') { push @{$_[0]}, 'spoiler'; ('spoiler_start') } else { () } } sub _quote_start { if(lc$_[1] eq '[quote]') { push @{$_[0]}, 'quote'; ('quote_start') } else { () } } sub _code_start { if(lc$_[1] eq '[code]') { push @{$_[0]}, 'code'; ('code_start') } else { () } } sub _raw_start { if(lc$_[1] eq '[raw]') { push @{$_[0]}, 'raw'; ('raw_start') } else { () } } +sub _b_end { if(lc$_[1] eq '[/b]') { pop @{$_[0]}; ('b_end' ) } else { () } } +sub _i_end { if(lc$_[1] eq '[/i]') { pop @{$_[0]}; ('i_end' ) } else { () } } +sub _u_end { if(lc$_[1] eq '[/u]') { pop @{$_[0]}; ('u_end' ) } else { () } } +sub _s_end { if(lc$_[1] eq '[/s]') { pop @{$_[0]}; ('s_end' ) } else { () } } sub _spoiler_end { if(lc$_[1] eq '[/spoiler]') { pop @{$_[0]}; ('spoiler_end') } else { () } } sub _quote_end { if(lc$_[1] eq '[/quote]' ) { pop @{$_[0]}; ('quote_end' ) } else { () } } sub _code_end { if(lc$_[1] eq '[/code]' ) { pop @{$_[0]}; ('code_end' ) } else { () } } @@ -65,10 +78,15 @@ sub _link { # Permitted actions to take in each state. The actions are run in order, if # none succeed then the token is passed through as text. # The "current state" is the most recent tag in the stack, or '' if no tags are open. +my @INLINE = (\&_link, \&_url_start, \&_raw_start, \&_b_start, \&_i_start, \&_u_start, \&_s_start, \&_spoiler_start); my %STATE = ( - '' => [ \&_link, \&_url_start, \&_raw_start, \&_spoiler_start, \&_quote_start, \&_code_start], - spoiler => [\&_spoiler_end, \&_link, \&_url_start, \&_raw_start], - quote => [\&_quote_end, \&_link, \&_url_start, \&_raw_start, \&_spoiler_start, \&_quote_start, \&_code_start], + '' => [ @INLINE, \&_quote_start, \&_code_start], + b => [\&_b_end, @INLINE], + i => [\&_i_end, @INLINE], + u => [\&_u_end, @INLINE], + s => [\&_s_end, @INLINE], + spoiler => [\&_spoiler_end, @INLINE], + quote => [\&_quote_end, @INLINE, \&_quote_start, \&_code_start], code => [\&_code_end ], url => [\&_url_end, \&_raw_start], raw => [\&_raw_end ], @@ -88,6 +106,14 @@ my %STATE = ( # # Tags: # text -> literal text, $raw is the text to display +# b_start -> start bold +# b_end -> end +# i_start -> start italic +# i_end -> end +# u_start -> start underline +# u_end -> end +# s_start -> start strike +# s_end -> end # spoiler_start -> start a spoiler # spoiler_end -> end # quote_start -> start a quote @@ -111,11 +137,11 @@ sub parse { my @stack; while($raw =~ m{(?: - \[ \/? (?i: spoiler|quote|code|url|raw ) [^\s\]]* \] | # tag - d[1-9][0-9]* \# [1-9][0-9]* (?: \.[1-9][0-9]* )? | # d+#+[.+] - [tdvprcs][1-9][0-9]*\.[1-9][0-9]* | # v+.+ - [tdvprcsugi][1-9][0-9]* | # v+ - (?:https?|ftp)://[^><"\n\s\]\[]+[\d\w=/-] # link + \[ \/? (?i: b|i|u|s|spoiler|quote|code|url|raw ) [^\s\]]* \] | # tag + d[1-9][0-9]* \# [1-9][0-9]* (?: \.[1-9][0-9]* )? | # d+#+[.+] + [tdvprcs][1-9][0-9]*\.[1-9][0-9]* | # v+.+ + [tdvprcsugi][1-9][0-9]* | # v+ + (?:https?|ftp)://[^><"\n\s\]\[]+[\d\w=/-] # link )}xg) { my $token = $&; my $pre = substr $raw, $last, $-[0]-$last; @@ -149,7 +175,7 @@ FINAL: # charspoil: # 0/undef/missing: Output <b class="spoiler">.. -# 1: Output 'charspoil_*' classes +# 1: Deprecated # 2: Just output 'hidden by spoiler setting' message # 3: Just output the spoilers, unmarked sub bb2html { @@ -190,13 +216,20 @@ sub bb2html { if($tag eq 'text') { $ret .= $e->($raw); + } elsif($tag eq 'b_start') { $ret .= '<b>'; + } elsif($tag eq 'b_end') { $ret .= '</b>'; + } elsif($tag eq 'i_start') { $ret .= '<em>'; + } elsif($tag eq 'i_end') { $ret .= '</em>'; + } elsif($tag eq 'u_start') { $ret .= '<span class="underline">'; + } elsif($tag eq 'u_end') { $ret .= '</span>'; + } elsif($tag eq 's_start') { $ret .= '<s>'; + } elsif($tag eq 's_end') { $ret .= '</s>'; + } elsif($tag eq 'spoiler_start') { $ret .= !$charspoil ? '<b class="spoiler">' : - $charspoil == 1 ? '<b class="grayedout charspoil charspoil_-1"><hidden by spoiler settings></b><span class="charspoil charspoil_2">' : - $charspoil == 2 ? '<b class="grayedout charspoil charspoil_-1"><hidden by spoiler settings></b><!--' : ''; + $charspoil == 2 ? '<b class="grayedout"><hidden by spoiler settings></b><!--' : ''; } elsif($tag eq 'spoiler_end') { $ret .= !$charspoil ? '</b>' : - $charspoil == 1 ? '</span>' : $charspoil == 2 ? '-->' : ''; } elsif($tag eq 'quote_start') { diff --git a/util/bbcode-test.pl b/util/bbcode-test.pl index 0ad0f3ea..d08f70c9 100755 --- a/util/bbcode-test.pl +++ b/util/bbcode-test.pl @@ -40,6 +40,10 @@ my @tests = ( '<b class="spoiler">some spoiler</b>', '', + '[b][i][u][s]Formatting![/s][/u][/i][/b]', + '<b><em><span class="underline"><s>Formatting!</s></span></em></b>', + 'Formatting!', + "[raw][quote]not parsed\n[url=https://vndb.org/]valid url[/url]\n[url=asdf]invalid url[/url][/quote][/raw]", "[quote]not parsed<br>[url=https://vndb.org/]valid url[/url]<br>[url=asdf]invalid url[/url][/quote]", "[quote]not parsed\n[url=https://vndb.org/]valid url[/url]\n[url=asdf]invalid url[/url][/quote]", @@ -48,6 +52,18 @@ my @tests = ( '<div class="quote">basic <b class="spoiler">single</b>-line <b class="spoiler"><a href="/g" rel="nofollow">tag</a> nesting (without [url=/v3333]special[/url] cases)</b></div>', 'basic -line ', + '[quote][b]more [spoiler]nesting [code]mkay?', + '<div class="quote"><b>more <b class="spoiler">nesting [code]mkay?</b></b></div>', + 'more ', + + '[url=/v][b]does not work here[/b][/url]', + '<a href="/v" rel="nofollow">[b]does not work here[/b]</a>', + '[b]does not work here[/b]', + + '[s] v5 [url=/p1]x[/url] [/s]', + '<s> <a href="/v5">v5</a> <a href="/p1" rel="nofollow">x</a> </s>', + ' v5 x ', + "[quote]rmnewline after closing tag[/quote]\n", '<div class="quote">rmnewline after closing tag</div>', "rmnewline after closing tag\n", |