no
warnings
'uninitialized'
;
our
$VERSION
=
'1.05'
;
my
@ignore_toc_dirs
=
qw/auto unicore/
;
my
$server_root
=
eval
{Apache2::ServerUtil::server_root()} ||
""
;
our
@search_dirs
=
grep
{
$_
ne
'.'
&&
$_
ne
$server_root
}
@INC
;
my
@podfilters
= (
?
sub
{
$_
[0] = AnnoCPAN::Perldoc::Filter->new->filter(
$_
[0])}
: (),
sub
{
$_
[0] =~ s/\A\s*// },
);
sub
server {
my
(
$class
,
$port
) =
@_
;
$port
||= 8080;
my
$d
= HTTP::Daemon->new(
LocalPort
=>
$port
,
ReuseAddr
=> 1)
or
die
"could not start daemon on port $port"
;
print
STDERR
"Please contact me at: <URL:"
,
$d
->url,
">\n"
;
while
(
my
$c
=
$d
->
accept
) {
while
(
my
$req
=
$c
->get_request) {
print
STDERR
"URL : "
,
$req
->url,
"\n"
;
$c
->force_last_request;
my
$response
= HTTP::Response->new;
$class
->handler(
$req
,
$response
);
$c
->send_response(
$response
);
}
$c
->
close
;
undef
(
$c
);
}
}
sub
handler : method {
my
(
$class
,
$request
,
$response
) =
@_
;
my
$self
=
$class
->new(
$request
,
$response
);
eval
{
$self
->dispatch_request(); 1}
or
$self
->send_content({
content
=> $@,
code
=> 500});
return
0;
}
sub
new {
my
(
$class
,
$request
,
$response
) =
@_
;
my
$self
;
if
(!
$no_indexer
&&
$class
eq __PACKAGE__) {
$class
=
"Pod::POM::Web::Indexer"
;
}
for
(
ref
$request
) {
/^Apache/ and
do
{
my
$path
=
$request
->path_info;
my
$q
= URI->new;
$q
->query(
$request
->args);
my
$params
=
$q
->query_form_hash;
(
my
$uri
=
$request
->uri) =~ s/
$path
$//;
$self
= {
response
=>
$request
,
root_url
=>
$uri
,
path
=>
$path
,
params
=>
$params
,
};
last
;
};
/^HTTP/ and
do
{
$self
= {
response
=>
$response
,
root_url
=>
""
,
path
=>
$request
->url->path,
params
=>
$request
->url->query_form_hash,
};
last
;
};
my
$q
= URI->new;
$q
->query(
$ENV
{QUERY_STRING});
my
$params
=
$q
->query_form_hash;
$self
= {
response
=>
undef
,
root_url
=>
$ENV
{SCRIPT_NAME},
path
=>
$ENV
{PATH_INFO},
params
=>
$params
,
};
}
bless
$self
,
$class
;
}
sub
dispatch_request {
my
(
$self
) =
@_
;
my
$path_info
=
$self
->{path};
$path_info
=~ m[(\.\.|//|\\|:)] and
die
"illegal path: $path_info"
;
$path_info
=~ s[^/][] or
return
$self
->redirect_index;
for
(
$path_info
) {
/^$/ and
return
$self
->redirect_index;
/^
index
$/ and
return
$self
->index_frameset;
/^toc$/ and
return
$self
->main_toc;
/^toc\/(.*)$/ and
return
$self
->toc_for($1);
/^lib\/(.*)$/ and
return
$self
->lib_file($1);
/^search$/ and
return
$self
->dispatch_search;
/^source\/(.*)$/ and
return
$self
->serve_source($1);
/^_dirs$/ and
return
$self
->send_html(
join
"<br>"
,
@search_dirs
);
return
$self
->serve_pod(
$path_info
);
}
}
sub
redirect_index {
my
(
$self
) =
@_
;
return
$self
->send_html(
"<script>location='$self->{root_url}/index'</script>"
);
}
sub
index_frameset {
my
(
$self
) =
@_
;
return
$self
->send_html(
<<__EOHTML__);
<html>
<head><title>Perl documentation</title></head>
<frameset cols="25%, 75%">
<frame name="tocFrame" src="toc"></frame>
<frame name="contentFrame" src="perlintro"></frame>
</frameset>
</html>
__EOHTML__
}
sub
serve_source {
my
(
$self
,
$path
) =
@_
;
my
$params
=
$self
->{params};
$params
->{
print
} or
$params
->{lines} =
$params
->{coloring} = 1;
my
@files
=
$self
->find_source(
$path
) or
die
"No file for '$path'"
;
my
$display_text
;
foreach
my
$file
(
@files
) {
my
$text
=
$self
->slurp_file(
$file
);
my
$view
= Pod::POM::View::HTML::_PerlDoc->new(
root_url
=>
$self
->{root_url},
syntax_coloring
=>
$params
->{coloring} ?
$coloring_package
:
""
,
line_numbering
=>
$params
->{lines},
);
$text
=
$view
->view_verbatim(
$text
);
$display_text
.=
"<p/><h2>$file</h2><p/><pre>$text</pre>"
;
}
my
$offer_print
=
$params
->{
print
} ?
""
:
<<__EOHTML__;
<form method="get" target="_blank">
<input type="submit" name="print" value="Print"> with<br>
<input type="checkbox" name="lines" checked>line numbers<br>
<input type="checkbox" name="coloring" checked>syntax coloring
</form>
__EOHTML__
my
$script
=
$params
->{
print
} ?
<<__EOHTML__ : "";
<script>
window.onload = function () {window.print()};
</script>
__EOHTML__
my
$doc_link
=
$params
->{
print
} ?
""
:
<<__EOHTML__;
<a href="$self->{root_url}/$path" style="float:right">Doc</a>
__EOHTML__
my
$lib
=
"$self->{root_url}/lib"
;
return
$self
->send_html(
<<__EOHTML__);
<html>
<head>
<title>Source of $path</title>
<link href="$lib/GvaScript.css" rel="stylesheet" type="text/css">
<link href="$lib/PodPomWeb.css" rel="stylesheet" type="text/css">
<style>
PRE {border: none; background: none}
FORM {float: right; font-size: 70%; border: 1px solid}
</style>
</head>
<body>
$doc_link
<h1>Source of $path</h1>
$offer_print
$display_text
</body>
</html>
__EOHTML__
}
sub
serve_pod {
my
(
$self
,
$path
) =
@_
;
$path
=~ s[::][/]g;
my
@sources
=
$self
->find_source(
$path
) or
die
"No file for '$path'"
;
my
$content
=
$self
->slurp_file(
$sources
[0]);
my
$version
=
@sources
> 1
?
$self
->parse_version(
$self
->slurp_file(
$sources
[-1]))
:
$self
->parse_version(
$content
);
$version
&&=
" <small>$version</small>"
;
for
my
$filter
(
@podfilters
) {
$filter
->(
$content
);
}
if
(
$path
eq
'perlfunc'
) {
sub
C_to_L {
my
$txt
=
shift
;
$txt
=~ s[C<(.*?)>][C<L</$1>>]g;
$txt
}
$content
=~ s[(Perl Functions by Category)(.*?)(Alphabetical Listing)]
[$1 . C_to_L($2) . $3]es;
}
my
$parser
= Pod::POM->new;
my
$pom
=
$parser
->parse_text(
$content
) or
die
$parser
->error;
(
my
$mod_name
=
$path
) =~ s[/][::]g;
my
$view
= Pod::POM::View::HTML::_PerlDoc->new(
version
=>
$version
,
root_url
=>
$self
->{root_url},
path
=>
$path
,
mod_name
=>
$mod_name
,
syntax_coloring
=>
$coloring_package
,
);
my
$html
=
$view
->
print
(
$pom
);
$html
=~ s/li id=
"(.*?)_.*?"
/li id=
"$1"
/g
if
$path
eq
'perlfunc'
;
return
$self
->send_html(
$html
);
}
sub
find_source {
my
(
$self
,
$path
) =
@_
;
foreach
my
$prefix
(
@search_dirs
) {
my
@found
=
grep
{-f} (
"$prefix/$path.pod"
,
"$prefix/$path.pm"
,
"$prefix/pod/$path.pod"
,
"$prefix/pods/$path.pod"
);
return
@found
if
@found
;
}
return
undef
;
}
sub
pod2pom {
my
(
$self
,
$sourcefile
) =
@_
;
my
$content
=
$self
->slurp_file(
$sourcefile
);
for
my
$filter
(
@podfilters
) {
$filter
->(
$content
);
}
my
$parser
= Pod::POM->new;
my
$pom
=
$parser
->parse_text(
$content
) or
die
$parser
->error;
return
$pom
;
}
sub
toc_for {
my
(
$self
,
$prefix
) =
@_
;
my
$entries
=
$self
->find_entries_for(
$prefix
);
if
(
$prefix
eq
'Pod'
) {
foreach
my
$k
(
keys
%$entries
) {
delete
$entries
->{
$k
}
if
$k
=~ /^perl/;
}
}
return
$self
->send_html(
$self
->htmlize_entries(
$entries
));
}
sub
main_toc {
my
(
$self
) =
@_
;
my
$perldocs
=
$self
->find_entries_for(
"pod"
);
my
$entries
=
$self
->find_entries_for(
""
);
delete
$entries
->{
$_
}
foreach
@ignore_toc_dirs
;
my
(
%pragmas
,
%modules
);
foreach
my
$k
(
keys
%$entries
) {
my
$which
=
$k
=~ /^perl/ ?
$perldocs
:
$k
=~ /^[[:lower:]]/ ? \
%pragmas
: \
%modules
;
$which
->{
$k
} =
delete
$entries
->{
$k
};
}
foreach
my
$k
(
keys
%$perldocs
) {
if
(
$k
=~ /^perl/) {
$perldocs
->{
$k
}{node} =~ s[^[pP]od/][];
}
else
{
delete
$perldocs
->{
$k
};
}
}
return
$self
->wrap_main_toc(
$self
->htmlize_perldocs(
$perldocs
),
$self
->htmlize_entries(\
%pragmas
),
$self
->htmlize_entries(\
%modules
));
}
sub
find_entries_for {
my
(
$self
,
$prefix
) =
@_
;
my
%entries
;
foreach
my
$root_dir
(
@search_dirs
) {
my
$dirname
=
$prefix
?
"$root_dir/$prefix"
:
$root_dir
;
opendir
my
$dh
,
$dirname
or
next
;
foreach
my
$name
(
readdir
$dh
) {
next
if
$name
=~ /^\./;
my
$is_dir
= -d
"$dirname/$name"
;
my
$has_pod
=
$name
=~ s/\.(pm|pod)$//;
next
if
$is_dir
and
grep
{m[^\Q
$dirname
/
$name
\E]}
@search_dirs
;
if
(
$is_dir
||
$has_pod
) {
$entries
{
$name
}{node} =
$prefix
?
"$prefix/$name"
:
$name
;
$entries
{
$name
}{dir} = 1
if
$is_dir
;
$entries
{
$name
}{pod} = 1
if
$has_pod
;
}
}
}
return
\
%entries
;
}
sub
htmlize_perldocs {
my
(
$self
,
$perldocs
) =
@_
;
my
$parser
= Pod::POM->new;
my
$source
=
$self
->slurp_file(
$self
->find_source(
"perl"
));
my
$perlpom
=
$parser
->parse_text(
$source
) or
die
$parser
->error;
my
(
$synopsis
) =
grep
{
$_
->title eq
'SYNOPSIS'
}
$perlpom
->head1();
my
$html
=
""
;
foreach
my
$h2
(
$synopsis
->head2) {
my
$title
=
$h2
->title;
my
$content
=
$h2
->verbatim;
my
@refs
= (
$content
=~ /^\s*(perl\S*?)\s*\t/gm);
my
$leaves
=
""
;
foreach
my
$ref
(
@refs
) {
my
$entry
=
delete
$perldocs
->{
$ref
} or
next
;
$leaves
.= leaf(
label
=>
$ref
,
href
=>
$entry
->{node});
}
$html
.= closed_node(
label
=>
"<b>$title</b>"
,
content
=>
$leaves
);
}
if
(
keys
%$perldocs
) {
$html
.= closed_node(
label
=>
'<b>Unclassified</b>'
,
content
=> htmlize_entries(
$perldocs
));
}
return
$html
;
}
sub
htmlize_entries {
my
(
$self
,
$entries
) =
@_
;
my
$html
=
""
;
foreach
my
$name
(
sort
{
uc
(
$a
) cmp
uc
(
$b
)}
keys
%$entries
) {
my
$entry
=
$entries
->{
$name
};
my
%args
= (
class
=>
'TN_leaf'
,
label
=>
$name
);
if
(
$entry
->{dir}) {
$args
{class} =
'TN_node TN_closed'
;
$args
{attrs} =
qq{TN:contentURL='toc/$entry->{node}
'};
}
if
(
$entry
->{pod}) {
$args
{href} =
$entry
->{node};
$args
{abstract} =
$self
->get_abstract(
$entry
->{node});
}
$html
.= generic_node(
%args
);
}
return
$html
;
}
sub
get_abstract {
}
sub
wrap_main_toc {
my
(
$self
,
$perldocs
,
$pragmas
,
$modules
) =
@_
;
$perldocs
= generic_node(
label
=>
"Perl docs"
,
label_class
=>
"TN_label small_title"
,
content
=>
$perldocs
);
$pragmas
= closed_node (
label
=>
"Pragmas"
,
label_class
=>
"TN_label small_title"
,
content
=>
$pragmas
);
$modules
= closed_node (
label
=>
"Modules"
,
label_class
=>
"TN_label small_title"
,
content
=>
$modules
);
my
@funcs
=
map
{
$_
->title}
grep
{
$_
->content =~ /\S/}
$self
->perlfunc_items;
s|[/\s(].*||s
foreach
@funcs
;
my
$json_funcs
=
"["
.
join
(
","
,
map
{
qq{"$_"}
} uniq
@funcs
) .
"]"
;
my
$js_no_indexer
=
$no_indexer
?
'true'
:
'false'
;
return
$self
->send_html(
<<__EOHTML__);
<html>
<head>
<base target="contentFrame">
<link href="lib/GvaScript.css" rel="stylesheet" type="text/css">
<link href="lib/PodPomWeb.css" rel="stylesheet" type="text/css">
<script src="lib/prototype.js"></script>
<script src="lib/GvaScript.js"></script>
<script>
var perlfuncs = $json_funcs;
var treeNavigator;
var completers = {};
var no_indexer = $js_no_indexer;
function setup() {
treeNavigator
= new GvaScript.TreeNavigator('TN_tree', {tabIndex:0});
completers.perlfunc = new GvaScript.AutoCompleter(
perlfuncs,
{minimumChars: 1, minWidth: 100, offsetX: -20});
if (!no_indexer)
completers.modlist = new GvaScript.AutoCompleter(
"search?source=modlist&search=",
{minimumChars: 2, minWidth: 100, offsetX: -20, typeAhead: false});
}
window.onload = setup;
function maybe_complete(input) {
if (input._autocompleter)
input._autocompleter.detach(input);
switch (input.form.source.selectedIndex) {
case 0: completers.perlfunc.autocomplete(input); break;
case 2: if (!no_indexer)
completers.modlist.autocomplete(input);
break;
}
}
function displayContent(event) {
var label = event.controller.label(event.target);
if (label && label.tagName == "A") {
label.focus();
return Event.stopNone;
}
}
</script>
<style>
.small_title {color: midnightblue; font-weight: bold; padding: 0 3 0 3}
FORM {margin:0px}
BODY {margin:0px; font-size: 70%; overflow-x: hidden}
#TN_tree {height: 80%;
overflow-y:scroll;
overflow-x: hidden}
</style>
</head>
<body>
<div class="small_title"
style="width:100%; text-align:center;border-bottom: 1px solid">
Perl Documentation
</div>
<div style="width:100%; text-align:right">
<a href="Pod/POM/Web/Help" class="small_title">Help</a>
</div>
<form action="search" method="get">
<span class="small_title">Search in</span>
<select name="source">
<option>perlfunc</option>
<option>perlfaq</option>
<option>modules</option>
<option>fulltext</option>
</select><br>
<span class="small_title"> for</span><input
name="search" size="15"
autocomplete="off"
onfocus="maybe_complete(this)">
</form>
<br>
<div class="small_title"
style="width:100%; border-bottom: 1px solid">Browse
</div>
<div id='TN_tree' onPing='displayContent'>
$perldocs
$pragmas
$modules
</div>
</body>
</html>
__EOHTML__
}
sub
dispatch_search {
my
(
$self
) =
@_
;
my
$params
=
$self
->{params};
my
$source
=
$params
->{source};
my
$method
= {
perlfunc
=>
'perlfunc'
,
perlfaq
=>
'perlfaq'
,
modules
=>
'serve_pod'
,
fulltext
=>
'fulltext'
,
modlist
=>
'modlist'
,
}->{
$source
} or
die
"cannot search in '$source'"
;
if
(
$method
=~ /fulltext|modlist/ and
$no_indexer
) {
die
"<p>this method requires <b>Search::Indexer</b></p>"
.
"<p>please ask your system administrator to install it</p>"
.
"(<small>error message : $no_indexer</small>)"
;
}
return
$self
->
$method
(
$params
->{search});
}
my
@_perlfunc_items
;
sub
perlfunc_items {
my
(
$self
) =
@_
;
unless
(
@_perlfunc_items
) {
my
$funcpom
=
$self
->pod2pom(
$self
->find_source(
"perlfunc"
));
my
(
$description
) =
grep
{
$_
->title eq
'DESCRIPTION'
}
$funcpom
->head1;
my
(
$alphalist
)
=
grep
{
$_
->title =~ /^Alphabetical Listing/i}
$description
->head2;
@_perlfunc_items
=
$alphalist
->over->[0]->item;
};
return
@_perlfunc_items
;
}
sub
perlfunc {
my
(
$self
,
$func
) =
@_
;
my
@items
=
grep
{
$_
->title =~ /^
$func
\b/}
$self
->perlfunc_items
or
return
print
(
"No documentation found for perl function '$func'"
);
my
$view
= Pod::POM::View::HTML::_PerlDoc->new(
root_url
=>
$self
->{root_url},
path
=>
"perlfunc/$func"
,
);
my
@li_items
=
map
{
$_
->present(
$view
)}
@items
;
my
$lib
=
"$self->{root_url}/lib"
;
return
$self
->send_html(
<<__EOHTML__);
<html>
<head>
<link href="$lib/PodPomWeb.css" rel="stylesheet" type="text/css">
</head>
<body>
<h2>Extract from <a href="$self->{root_url}/perlfunc">perlfunc</a></h2>
<ul>@li_items</ul>
</body>
__EOHTML__
}
sub
perlfaq {
my
(
$self
,
$faq_entry
) =
@_
;
my
$regex
=
qr/\b\Q$faq_entry\E\b/
i;
my
$answers
=
""
;
my
$n_answers
= 0;
my
$view
= Pod::POM::View::HTML::_PerlDoc->new(
root_url
=>
$self
->{root_url},
path
=>
"perlfaq/$faq_entry"
,
);
FAQ:
for
my
$num
(1..9) {
my
$faqpom
=
$self
->pod2pom(
$self
->find_source(
"perlfaq$num"
));
my
@questions
=
map
{
grep
{
$_
->title =~
$regex
}
$_
->head2}
$faqpom
->head1
or
next
FAQ;
my
@nodes
=
map
{
$view
->
print
(
$_
)}
@questions
;
$answers
.= generic_node(
label
=>
"Found in perlfaq$num"
,
label_tag
=>
"h2"
,
content
=>
join
(
""
,
@nodes
));
$n_answers
+=
@nodes
;
}
my
$lib
=
"$self->{root_url}/lib"
;
return
$self
->send_html(
<<__EOHTML__);
<html>
<head>
<link href="$lib/GvaScript.css" rel="stylesheet" type="text/css">
<link href="$lib/PodPomWeb.css" rel="stylesheet" type="text/css">
<script src="$lib/prototype.js"></script>
<script src="$lib/GvaScript.js"></script>
<script>
var treeNavigator;
function setup() {
treeNavigator = new GvaScript.TreeNavigator('TN_tree');
}
window.onload = setup;
</script>
</head>
<body>
<h1>Extracts from <a href="$self->{root_url}/perlfaq">perlfaq</a></h1><br>
<em>searching for '$faq_entry' : $n_answers answers</em><br><br>
<div id='TN_tree'>
$answers
</div>
</body>
__EOHTML__
}
sub
lib_file {
my
(
$self
,
$filename
) =
@_
;
my
$dir
= Alien::GvaScript->path;
if
(
$filename
eq
'PodPomWeb.css'
) {
(
$dir
= __FILE__) =~ s[\.pm$][/lib];
}
(
my
$extension
=
$filename
) =~ s/.*\.//;
my
$mime_type
= {
html
=>
'text/html'
,
css
=>
'text/css'
,
js
=>
'application/x-javascript'
,
gif
=>
'image/gif'
}->{
$extension
}
or
die
"lib_file($filename): unexpected extension"
;
my
$content
=
$self
->slurp_file(
"$dir/$filename"
);
my
$mtime
= (
stat
"$dir/$filename"
)[9];
$self
->send_content({
content
=>
$content
,
mtime
=>
$mtime
,
mime_type
=>
$mime_type
});
}
sub
send_html {
my
(
$self
,
$html
) =
@_
;
$self
->send_content({
content
=>
$_
[1],
code
=> 200});
}
sub
send_content {
my
(
$self
,
$args
) =
@_
;
my
$encoding
= guess_encoding(
$args
->{content},
qw/ascii utf8 latin1/
);
my
$charset
=
ref
$encoding
?
$encoding
->name :
""
;
my
$length
=
length
$args
->{content};
my
$mime_type
=
$args
->{mime_type} ||
"text/html"
;
$mime_type
.=
"; charset=$charset"
if
$charset
;
my
$modified
=
gmtime
$args
->{mtime};
my
$code
=
$args
->{code} || 200;
my
$r
=
$self
->{response};
for
(
ref
$r
) {
/^Apache/ and
do
{
$r
->content_type(
$mime_type
);
$r
->set_content_length(
$length
);
$r
->set_last_modified(
$args
->{mtime})
if
$args
->{mtime};
$r
->
print
(
$args
->{content});
return
;
};
/^HTTP::Response/ and
do
{
$r
->code(
$code
);
$r
->header(
Content_type
=>
$mime_type
,
Content_length
=>
$length
);
$r
->header(
Last_modified
=>
$modified
)
if
$args
->{mtime};
$r
->add_content(
$args
->{content});
return
;
};
my
$headers
=
"Content-type: $mime_type\nContent-length: $length\n"
;
$headers
.=
"Last-modified: $modified\n"
if
$args
->{mtime};
binmode
(STDOUT);
print
"$headers\n$args->{content}"
;
return
;
}
}
my
%escape_entity
= (
'&'
=>
'&'
,
'<'
=>
'<'
,
'>'
=>
'>'
,
'"'
=>
'"'
);
sub
generic_node {
my
%args
=
@_
;
$args
{class} ||=
"TN_node"
;
$args
{attrs} &&=
" $args{attrs}"
;
$args
{content} ||=
""
;
$args
{content} &&=
qq{<div class="TN_content">$args{content}
</div>};
my
(
$default_label_tag
,
$label_attrs
)
=
$args
{href} ? (
"a"
,
qq{ href='$args{href}
'})
: (
"span"
,
""
);
$args
{label_tag} ||=
$default_label_tag
;
$args
{label_class} ||=
"TN_label"
;
if
(
$args
{abstract}) {
$args
{abstract} =~ s/([&<>"])/
$escape_entity
{$1}/g;
$label_attrs
.=
qq{ title="$args{abstract}
"};
}
return
qq{<div class="$args{class}
"
$args
{attrs}>}
.
qq{<$args{label_tag}
class=
"$args{label_class}"
$label_attrs
>}
.
$args
{label}
.
qq{</$args{label_tag}
>}
.
$args
{content}
.
qq{</div>}
;
}
sub
closed_node {
return
generic_node(
@_
,
class
=>
"TN_node TN_closed"
);
}
sub
leaf {
return
generic_node(
@_
,
class
=>
"TN_leaf"
);
}
sub
slurp_file {
my
(
$self
,
$file
) =
@_
;
open
my
$fh
,
$file
or
die
"open $file: $!"
;
binmode
(
$fh
,
":crlf"
);
local
$/ =
undef
;
return
<
$fh
>;
}
my
$VARNAME_REGEXP
=
qr/ # match fully-qualified VERSION name
([\$*]) # sigil - $ or *
(
( # optional leading package name
(?:::|\')? # possibly starting like just :: (ala $::VERSION)
(?:\w+(?:::|\'))* # Foo::Bar:: ...
)?
VERSION
)\b
/
x;
my
$VERS_REGEXP
=
qr/ # match a VERSION definition
(?:
\(\s*$VARNAME_REGEXP\s*\) # with parens
|
$VARNAME_REGEXP # without parens
)
\s*
=[^=~] # = but not ==, nor =~
/
x;
sub
parse_version {
my
$result
;
my
$in_pod
= 0;
while
(
$_
[1] =~ /^.*$/mg) {
my
$line
= $&;
chomp
$line
;
next
if
$line
=~ /^\s*
$in_pod
=
$line
=~ /^=(?!cut)/ ? 1 :
$line
=~ /^=cut/ ? 0 :
$in_pod
;
last
if
!
$in_pod
&&
$line
=~ /^__(?:DATA|END)__$/;
next
unless
$line
=~
$VERS_REGEXP
;
my
(
$sigil
,
$var
,
$pkg
) = $2 ? ( $1, $2, $3 ) : ( $4, $5, $6 );
$line
=~ s/\bour\b//;
my
$eval
=
qq{q# Hide from _packages_inside()
#; package Pod::POM::Web::_version;
no strict;
local $sigil$var;
\$$var=undef; do { $line }
; \
$$var
};
no
warnings;
$result
=
eval
(
$eval
) ||
""
;
}
return
$result
;
}
1;
no
warnings
'uninitialized'
;
sub
view_seq_link_transform_path {
my
(
$self
,
$page
) =
@_
;
$page
=~ s[::][/]g;
return
"$self->{root_url}/$page"
;
}
sub
view_seq_link {
my
(
$self
,
$link
) =
@_
;
my
$linked
=
$self
->SUPER::view_seq_link(
$link
);
my
(
$u
,
$t
) =
my
(
$url
,
$title
) = (
$linked
=~ m[^<a href=
"(.*?)"
>(.*)</a>]);
$url
=~ s[
$title
=~ s[^(.*?)/(.*)$][$1 ?
"$2 in $1"
: $2]e
unless
(
$title
=~ m{^\w+://}s);
return
qq{<a href="$url">$title</a>}
;
}
sub
view_over {
my
(
$self
,
$over
) =
@_
;
my
$content
=
$self
->SUPER::view_over(
$over
);
if
(
$content
eq
""
) {
my
$overs
=
$over
->over();
if
(
@$overs
) {
$content
=
join
''
,
map
{
$self
->view_over(
$_
)}
@$overs
;
if
(
$content
=~ /AnnoCPAN/) {
$content
=
"<div class='AnnoCPAN'>$content</div>"
;
}
}
}
return
$content
;
}
sub
view_item {
my
(
$self
,
$item
) =
@_
;
my
$title
=
eval
{
$item
->title->present(
$self
)} ||
""
;
$title
=
""
if
$title
=~ /^\s*\*\s*$/;
my
$id
= _title_to_id(
$title
);
my
$li
=
$id
?
qq{<li id="$id">}
:
qq{<li>}
;
my
$content
=
$item
->content->present(
$self
);
$title
=
qq{<b>$title</b>}
if
$title
;
return
qq{$li$title\n$content</li>\n}
;
}
sub
_title_to_id {
my
$title
=
shift
;
$title
=~ s/<.*?>//g;
$title
=~ s/[,(].*//;
$title
=~ s/\s*$//;
$title
=~ s/[^A-Za-z0-9_]/_/g;
return
$title
;
}
sub
view_pod {
my
(
$self
,
$pom
) =
@_
;
my
(
$name_h1
) =
grep
{
$_
->title =~ /^NAME\b/}
$pom
->head1();
my
$doc_title
=
$name_h1
?
$name_h1
->content :
'Untitled'
;
$doc_title
=~ s/<.*?>//g;
my
(
$name
,
$description
) = (
$doc_title
=~ /^\s*(.*?)\s+-+\s+(.*)/);
$name
||=
$doc_title
;
my
$core_release
= Module::CoreList->first_release(
$self
->{mod_name}) ||
""
;
my
$orig_version
=
$Module::CoreList::version
{
$core_release
}{
$self
->{mod_name}} ||
""
;
$orig_version
&&=
"version $orig_version "
;
$core_release
&&=
"<small>(${orig_version}entered Perl core in $core_release)</small>"
;
my
$content
=
$pom
->content->present(
$self
);
my
$toc
=
$self
->make_toc(
$pom
, 0);
my
$lib
=
"$self->{root_url}/lib"
;
return
<<__EOHTML__
<html>
<head>
<title>$name</title>
<link href="$lib/GvaScript.css" rel="stylesheet" type="text/css">
<link href="$lib/PodPomWeb.css" rel="stylesheet" type="text/css">
<script src="$lib/prototype.js"></script>
<script src="$lib/GvaScript.js"></script>
<script>
var treeNavigator;
function setup() {
new GvaScript.TreeNavigator(
'TN_tree',
{selectFirstNode: location.hash ? false : true}
);
}
window.onload = setup;
function jumpto_href(event) {
var label = event.controller.label(event.target);
if (label && label.tagName == "A") {
label.focus();
return Event.stopNone;
}
}
</script>
<style>
#TOC .TN_content .TN_label {font-size: 80%; font-weight: bold}
#TOC .TN_leaf .TN_label {font-weight: normal}
#ref_box {
clear: right;
float: right;
text-align: right;
font-size: 80%;
}
#title_descr {
clear: right;
float: right;
font-style: italic;
margin-top: 8px;
margin-bottom: 8px;
padding: 5px;
text-align: center;
border: 3px double #888;
}
</style>
</head>
<body>
<div id='TN_tree'>
<div class="TN_node">
<h1 class="TN_label">$name$self->{version}</h1>
$core_release
<span id="title_descr">$description</span>
<span id="ref_box">
<a href="$self->{root_url}/source/$self->{path}">Source</a><br>
CPAN
target="_blank">Anno</a> |
target="_blank">Forum</a> |
target="_blank">Kobes</a>
</span>
<div class="TN_content">
<div class="TN_node" onPing="jumpto_href" id="TOC">
<h3 class="TN_label">Table of contents</h3>
<div class="TN_content">
$toc
</div>
</div>
<hr/>
</div>
</div>
$content
</div>
</body>
</html>
__EOHTML__
}
BEGIN {
for
my
$num
(1..6) {
no
strict
'refs'
;
*{
"view_head$num"
} =
sub
{
my
(
$self
,
$item
) =
@_
;
my
$title
=
$item
->title->present(
$self
);
my
$id
= _title_to_id(
$title
);
my
$content
=
$item
->content->present(
$self
);
my
$h_num
=
$num
+ 1;
return
<<EOHTML
<div class="TN_node" id="$id">
<h$h_num class="TN_label">$title</h$h_num>
<div class="TN_content">
$content
</div>
</div>
EOHTML
}
}
}
sub
view_seq_index {
my
(
$self
,
$item
) =
@_
;
return
""
;
}
sub
view_verbatim {
my
(
$self
,
$text
) =
@_
;
my
$coloring
=
$self
->{syntax_coloring};
if
(
$coloring
) {
my
$method
=
"${coloring}_coloring"
;
$text
=
$self
->
$method
(
$text
);
}
$text
=~ s{(\buse\b(?:</span>)\s+(?:<span.*?>))([\w:]+)}
{
my
$url
=
$self
->view_seq_link_transform_path($2);
qq{$1<a href="$url">$2</a>}
}eg;
if
(
$self
->{line_numbering}) {
my
$line
= 1;
$text
=~ s/^/
sprintf
"%6d\t"
,
$line
++/egm;
}
return
qq{<pre class="$coloring">$text</pre>}
;
}
sub
PPI_coloring {
my
(
$self
,
$text
) =
@_
;
my
$ppi
= PPI::HTML->new();
$text
=
$ppi
->html(\
$text
);
$text
=~ s/<br>//g;
return
$text
;
}
sub
SCINEPLEX_coloring {
my
(
$self
,
$text
) =
@_
;
eval
{
$text
= ActiveState::Scineplex::Annotate(
$text
,
'perl'
,
outputFormat
=>
'html'
);
};
return
$text
;
}
sub
make_toc {
my
(
$self
,
$item
,
$level
) =
@_
;
my
$html
=
""
;
my
$method
=
"head"
. (
$level
+ 1);
my
$sub_items
=
$item
->
$method
;
foreach
my
$sub_item
(
@$sub_items
) {
my
$title
=
$sub_item
->title->present(
$self
);
my
$id
= _title_to_id(
$title
);
my
$node_content
=
$self
->make_toc(
$sub_item
,
$level
+ 1);
my
$class
=
$node_content
?
"TN_node"
:
"TN_leaf"
;
$node_content
&&=
qq{<div class="TN_content">$node_content</div>}
;
$html
.=
qq{<div class="$class">}
.
qq{<a class="TN_label" href="#$id">$title</a>}
.
$node_content
.
qq{</div>}
;
}
return
$html
;
}
sub
DESTROY {}
1;