--- deliantra/server/lib/cf/pod.pm 2007/03/06 19:02:36 1.1
+++ deliantra/server/lib/cf/pod.pm 2007/07/03 01:10:38 1.8
@@ -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/>/>/g;
+ s/</g;
+
+ $_
+}
+
+sub flatten($) {
+ local $_ = $_[0];
+
+ s/<[^>]+>//g;
+ s/^\s+//;
+ s/\s+$//;
+ s/\s+/ /g;
+
+ $_
+}
+
+*view_seq_file =
+*view_seq_code =
+*view_seq_bold = sub { "$_[1]" };
+*view_seq_italic = sub { "$_[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:/) {
+ "" . (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 => asxml $_[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],
+ 1 => sub {
+ my ($src) = @_;
+ cf::fork_call {
+ my $pod = $src->[0];
+ utf8::decode $pod;
+ Coro::Storable::freeze pom_as_paragraphs +(Pod::POM->new->parse_text ($pod))
+ }
+ };
+}
+
+# format as cfpod-style text
+sub as_text($) {
+ 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;
+