PPI-HTML-CodeFolder
view release on metacpan or search on metacpan
lib/PPI/HTML/CodeFolder.pm view on Meta::CPAN
or return undef;
$outfile = (ref $src) ? '' : "$src.html"
unless $outfile;
$script ||= $src
unless ref $src || (substr($src, -3) eq '.pm');
#
# expand tabs as needed (we use 4 space tabs)
# have to adjust some spans that confuse tab processing
#
my @lns = split /\n/, $html;
my $tabsz = $self->{fold}{Tabs};
foreach my $line (@lns) {
next if $line=~s/^\s*$//;
next unless $line=~tr/\t//;
my $offs = 0;
my $pad;
#
# scan for and replace tabs; adjust positions
# of extracted tags as needed
#
pos($line) = 0;
while ($line=~/\G.*?((<[^>]+>)|\t)/gc) {
$offs += length($2),
next
unless ($1 eq "\t");
$pad = $tabsz - ($-[1] - $offs) % $tabsz;
substr($line, $-[1], 1, ' ' x $pad);
pos($line) = $-[1] + $pad - 1;
}
}
$html = join("\n", @lns);
delete $self->{colors} unless $orig_colors;
my $opts = $self->{fold};
#
# extract stylesheet and replace with abbreviated version
#
my $style = $opts->{Stylesheet} ?
"<link type='text/css' rel='stylesheet' href='" .
_pathAdjust($outfile, $opts->{Stylesheet}) . "' />" :
$self->foldCSS();
$style .= $opts->{Javascript} ?
"\n<script type='text/javascript' src='" .
_pathAdjust($outfile, $opts->{Javascript}) . "'></script>\n" :
"\n<script type='text/javascript'>\n$ftjs\n</script>\n"
if $opts->{Expandable};
#
# original html may have no style, so we've got to add OR replace
#
$html=~s|</head>|$style</head>|s
unless ($html=~s|<style type="text/css">.+</style>|$style|s);
#
# force spans to end before line endings
#
$html=~s!(<br>\s*)</span>!</span>$1!g;
#
# split multiline comments into 2 spans: 1st line (in case its midline)
# and the remainder; note that the prior substitution avoids
# doing this to single line comments
#
$html=~s/(?!<br>\s+)(<span class=['"]comment['"]>[^<]+)<br>\n/$1<\/span><br>\n<span class="comment">/g;
#
# keep folded fragments here for later insertion
# as fold DIVs; key is starting line number,
# value is [ number of lines, text ]
#
my %folddivs = ( 1 => [ 0, '', 0, 0 ]);
#
# count <br> tags, and looks for any of
# comment, pod, or use/require keyword (depending on the options);
# keeps track of start and end position of foldable segments
#
my $lineno = 1;
my $lastfold = 1;
$html=~s/<br>\n/<br>/g;
#
# now process remainder
#
study $html;
pos($html) = 0;
$html=~/^.*?(<body[^>]+><pre>)/s;
my $startpos = $+[1];
#
# map linebreak positions to line numbers
#
my @lnmap = (0, $startpos);
push @lnmap, $+[1]
while ($html=~/\G.*?(<br>)/gcs);
#
# now scan for foldables
#
pos($html) = $startpos;
my @folds = _extractFolds(\$html, $startpos, \@lnmap, $opts);
#
# trim small folds;
# since its used frequently, create a sorted list of the fold DIV lines;
# isolate positions of folds and extract folded content
#
my $ln = 0;
my @ftsorted = ();
foreach (@folds) {
if ($_->[1] - $_->[0] + 1 >= $opts->{MinFoldLines}) {
$folddivs{$_->[0]} = [ $_->[1], substr($html, $lnmap[$_->[0]], $lnmap[$_->[1] + 1] - $lnmap[$_->[0]]),
$lnmap[$_->[0]], $lnmap[$_->[1] + 1] ];
push @ftsorted, $_->[0];
}
elsif ($self->{_verbose}) {
# print "*** skipping section at line $_->[0]to $_->[1]\n";
# print substr($html, $lnmap[$_->[0]], $lnmap[$_->[1] + 1] - $lnmap[$_->[0]]), "\n";
}
}
#
# now remove the folded lines; we work from bottom to top since
# we're changing the HTML as we go, which would invalidate the
# positional elements we've kept. If fold expansion is enabled, we replace
# w/ a hyperlink; otherwise we replace with a simple indication of the fold
( run in 1.132 second using v1.01-cache-2.11-cpan-71847e10f99 )