package Display::Markup;
|
|
|
|
use base qw(Exporter);
|
|
our @EXPORT_OK = qw(line_parse);
|
|
|
|
use Display::Image qw(image_size);
|
|
use Text::Textile;
|
|
|
|
# some useful defaults.
|
|
|
|
my %tags = ( retcon => q{div class="retcon"},
|
|
freeverse => 'p',
|
|
list => "ul>\n<li" );
|
|
|
|
my %end_tags = ( retcon => 'div',
|
|
freeverse => 'p',
|
|
list => "li>\n</ul" );
|
|
|
|
my %blank_lines = ( freeverse => "</p>\n\n<p>",
|
|
list => "</li>\n\n<li>" );
|
|
|
|
my %newlines = ( freeverse => "<br />\n" );
|
|
|
|
my %dashes = ( freeverse => ' — ' );
|
|
|
|
=item line_parse
|
|
|
|
Performs substitutions on lines called by fragment_slurp, at least. Calls
|
|
image_markup, Text::Textile, Wala::wiki_page_to_html, eval_perl. Returns
|
|
string.
|
|
|
|
Parses some special markup, specifically:
|
|
|
|
<perl>embedded perl</perl>
|
|
${variable} interpolation from %DISPLAY_CONF
|
|
<textile></textile> - Text::Textile to HTML
|
|
<wala></wala> - Wala::wikify();
|
|
<freeverse></freeverse>
|
|
<retcon></retcon>
|
|
<list></list>
|
|
|
|
<image>filename.ext
|
|
optional alt tag</image>
|
|
|
|
=cut
|
|
|
|
sub line_parse {
|
|
my ($everything, $file) = (@_);
|
|
|
|
# take care of wala markup
|
|
$everything =~ s/<wala>(.*?)<\/wala>/Wala::wikify($1)/seg;
|
|
|
|
# take care of textile markup, if we've got any
|
|
textile_process($everything);
|
|
|
|
# evaluate <image> tags.
|
|
$everything =~ s!<image>(.*?)</image>!image_markup($file, $1)!seg;
|
|
|
|
foreach my $key (keys %tags) {
|
|
# Set some replacements, unless they've been explicitly set already.
|
|
$end_tags{$key} = $tags{$key} unless $end_tags{$key};
|
|
$blank_lines{$key} = "\n\n" unless $blank_lines{$key};
|
|
$newlines{$key} = "\n" unless $newlines{$key};
|
|
$dashes{$key} = " -- " unless $dashes{$key};
|
|
|
|
while ($everything =~ m/(<$key>.*?<\/$key>)/s) {
|
|
my $block = $1;
|
|
|
|
# save the bits between instances of the block --
|
|
my (@interstice_array) = split /\Q$block\E/s, $everything;
|
|
|
|
# now, transform the contents of the block we've found:
|
|
|
|
# tags that surround the block
|
|
$block =~ s/\n?<$key>\n?/<$tags{$key}>/gs;
|
|
$block =~ s!\n?</$key>\n?!</$end_tags{$key}>!gs;
|
|
|
|
# dashes
|
|
$block = dashes($dashes{$key}, $block);
|
|
|
|
# blank lines within the block
|
|
$block =~ s/\n\n/$blank_lines{$key}/gs;
|
|
|
|
$block = newlines($newlines{$key}, $block);
|
|
|
|
# and slap it all back together as $everything
|
|
$everything = join $block, @interstice_array;
|
|
|
|
}
|
|
}
|
|
|
|
return $everything;
|
|
}
|
|
|
|
sub newlines {
|
|
my ($replacement, $block) = @_;
|
|
|
|
# single newlines (i.e., line ends) within the block
|
|
# except those preceded by a double-quote, which probably
|
|
# indicates a still-open tag:
|
|
|
|
$block =~ s/(?<=[^"\n]) # not a double-quote or newline
|
|
# don't capture
|
|
|
|
\n # end-of-line
|
|
|
|
(?=[^\n]) # not a newline
|
|
# don't capture
|
|
/$replacement/xgs;
|
|
|
|
return $block;
|
|
|
|
}
|
|
|
|
# might need a rewrite.
|
|
sub dashes {
|
|
my ($replacement, $block) =@_;
|
|
|
|
$block =~ s/(\s+) # whitespace - no capture
|
|
\-{2} # two dashes
|
|
(\n|\s+|$) # newline, whitespace, or eol
|
|
/$1${replacement}$2/xgs;
|
|
|
|
return $block;
|
|
|
|
}
|
|
|
|
=item textile_process
|
|
|
|
Inline replace <textile> markup in a string.
|
|
|
|
Trying to implement some caching here, though it's questionable whether
|
|
this makes any sense. There's also a closure which should retain the
|
|
Text::Textile object between invocations, potentially saving some time at
|
|
the expense of a little memory.
|
|
|
|
=cut
|
|
|
|
{ my %cache;
|
|
my $textile;
|
|
|
|
sub textile_process {
|
|
my $replacement;
|
|
|
|
unless (defined $textile) {
|
|
# head_offset: use h1., h2. in Textile formatting:
|
|
$textile = Text::Textile->new( head_offset => 2 );
|
|
}
|
|
|
|
while ( $_[0] =~ m/<textile>(.*?)<\/textile>/sx ) {
|
|
my $block = $1;
|
|
|
|
if (exists $cache{$block}) {
|
|
$replacement = $cache{$block};
|
|
} else {
|
|
$replacement = $textile->process($block);
|
|
$cache{$block} = $replacement;
|
|
}
|
|
|
|
$_[0] =~ s/<textile>\Q$block\E<\/textile>/$replacement/sg;
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
=item image markup
|
|
|
|
Parse out an image tag and return the appropriate html.
|
|
|
|
Relies on image_size from Display::Image.
|
|
|
|
=cut
|
|
|
|
sub image_markup {
|
|
my ($file, $block) = @_;
|
|
my %DISPLAY_CONF = %Display::DISPLAY_CONF;
|
|
|
|
# get a directory for the file we're working with
|
|
$file =~ s'[^/]* # everything not a /
|
|
$ # up to end of string
|
|
''x;
|
|
|
|
# truncated file date that just includes date + sub docs
|
|
my ($file_date) = $file =~ m{([0-9]{4}/ # year
|
|
[0-9]{1,2}/ # month
|
|
[0-9]{1,2}/ # day
|
|
([a-z]*/)*)$ # sub-entries
|
|
}x;
|
|
|
|
my ($image_name, $alt_text, $title_text) = split /\n/, $block;
|
|
$title_text = $alt_text unless $title_text;
|
|
|
|
my $image_file;
|
|
if (-e "$file/$image_name" ) {
|
|
$image_file = "$file/$image_name";
|
|
$image_name = "${file_date}${image_name}";
|
|
} elsif (-e "$DISPLAY_CONF{ROOT_DIR}/$image_name") {
|
|
$image_file = "$DISPLAY_CONF{ROOT_DIR}/$image_name";
|
|
}
|
|
|
|
# get width & height in pixels for known filetypes
|
|
my ($width, $height) = image_size($image_file);
|
|
|
|
# this relies on mod_rewrite working:
|
|
return<<"IMG";
|
|
<img src="$DISPLAY_CONF{IMAGE_URL_ROOT}$image_name"
|
|
height="$height"
|
|
width="$width"
|
|
alt="$alt_text"
|
|
title="$title_text" />
|
|
IMG
|
|
}
|
|
|
|
1;
|