--- deliantra/server/lib/cf/pod.pm 2007/03/06 19:02:36 1.1 +++ deliantra/server/lib/cf/pod.pm 2008/08/31 09:03:31 1.13 @@ -0,0 +1,220 @@ +package cf::pod; + +use Pod::POM; + +our $indent; +our $level; +our @result; + +package cf::pod::AsParagraphs; + +use strict; + +use base "Pod::POM::View"; + +sub asxml($) { + local $_ = $_[0]; + + s//g; + s/>/E/g; + + $_ +} + +sub flatten($) { + local $_ = $_[0]; + + s/<[^>]+>//g; + s/^\s+//; + s/\s+$//; + s/\s+/ /g; + + $_ +} + +*view_seq_file = +*view_seq_code = +*view_seq_bold = sub { "B<$_[1]>" }; +*view_seq_italic = sub { "I<$_[1]>" }; +*view_seq_zero = sub { }; +*view_seq_space = sub { my $text = $_[1]; $text =~ s/ /\xa0/g; $text }; +*view_seq_index = sub { push @{ $result[-1]{index} }, $_[1]; "" }; + +sub view_seq_text { + my $text = $_[1]; + $text =~ s/\s+/ /g; + asxml $text +} + +sub view_seq_link { + my (undef, $link) = @_; + + my $text = $link =~ s/^(.*)\|// ? $1 : $link; + + if ($link =~ /http:/) { + "U<" . (asxml $link) . ">" + } else { + () + } +} + +sub view_item { + push @result, { + type => "item", + indent => $indent * 8, + level => $level, + }; + my $title = $_[1]->title->present ($_[0]); + $result[-1]{markup} = $title if length $title; + $title = flatten $title; unshift @{ $result[-1]{index} }, $title if length $title; + local $level = $level + 1; + $_[1]->content->present ($_[0]); + () +} + +sub view_verbatim { + push @result, { + type => "verbatim", + indent => $indent * 16, + level => $level, + markup => $_[1], + }; + () +} + +sub view_textblock { + push @result, { + indent => $indent * 16, + level => $level, + markup => flatten $_[1], + }; + () +} + +sub view_head1 { + push @result, { + type => "head1", + indent => $indent * 16, + level => $level, + }; + my $title = $_[1]->title->present ($_[0]); + $result[-1]{markup} = $title if length $title; + $title = flatten $title; unshift @{ $result[-1]{index} }, $title if length $title; + local $level = $level + 1; + $_[1]->content->present ($_[0]); + () +}; + +sub view_head2 { + push @result, { + type => "head2", + indent => $indent * 16, + level => $level, + }; + my $title = $_[1]->title->present ($_[0]); + $result[-1]{markup} = $title if length $title; + $title = flatten $title; unshift @{ $result[-1]{index} }, $title if length $title; + local $level = $level + 1; + $_[1]->content->present ($_[0]); + () +}; + +sub view_head3 { + push @result, { + type => "head3", + indent => $indent * 16, + level => $level, + }; + my $title = $_[1]->title->present ($_[0]); + $result[-1]{markup} = $title if length $title; + $title = flatten $title; unshift @{ $result[-1]{index} }, $title if length $title; + local $level = $level + 1; + $_[1]->content->present ($_[0]); + () +}; + +sub view_over { + local $indent = $indent + $_[1]->indent; + push @result, { indent => $indent }; + $_[1]->content->present ($_[0]); + () +} + +sub view_for { + if ($_[1]->format eq "image") { +# push @result, { +# indent => $indent * 16, +# level => $level, +# markup => (::special image => "pod/" . $_->text), +# }; + } + () +} + +sub view_begin { + () +} + +sub view { + my ($self, $type, $item) = @_; + + $item->content->present ($self); +} + +############################################################################# + +package cf::pod; + +sub pom_as_paragraphs($) { + my ($pom) = @_; + + # we suckers use global variables, unfortunately. + my $guard = cf::lock_acquire "cf::pod::as_paragraphs"; + + local $indent = 0; + local $level = 1; + local @result = ( { } ); + + $pom->present ("cf::pod::AsParagraphs"); + + [grep $_->{index} || exists $_->{markup}, @result] +} + +sub load_pod($) { + my ($path) = @_; + + Coro::Storable::thaw cf::cache "cf::pod::as_paragraphs/$path" => [$path], + 3 => sub { + my ($src) = @_; + + cf::fork_call { + my $pod = $src->[0]; + utf8::decode $pod; + Coro::Storable::blocking_nfreeze pom_as_paragraphs +(Pod::POM->new->parse_text ($pod)) + } + }; +} + +# format as cfpod-style text +sub as_cfpod($) { + my ($pars) = @_; + + my $res; + + for my $par (@$pars) { + if ($par->{type} =~ /^head\d+$/) { + $res .= "B<$par->{markup}>\n\n"; + } elsif ($par->{type} eq "verbatim") { + $res .= "\n$par->{markup}\n\n"; + } elsif ($par->{type} eq "item") { + $res .= "\n* I<$par->{markup}>\n\n"; + } else { + $res .= "$par->{markup}\n\n"; + } + } + + $res +} + +1; +