package Text::Markup::Asciidoc;
use 5.8.1;
use strict;
use File::Spec;
use constant WIN32 => $^O eq 'MSWin32';
use Symbol 'gensym';
use IPC::Open3;
use utf8;
our $VERSION = '0.23';
# Find Asciidoc.
my $ASCIIDOC;
FIND: {
my @path = (
File::Spec->path,
WIN32 ? (map { "C:\\asciidoc$_" } '', '-8.6.6') : ()
);
EXE: {
for my $exe (qw(asciidoc asciidoc.py)) {
for my $p (@path) {
my $path = File::Spec->catfile($p, $exe);
next unless -f $path && -x $path;
$ASCIIDOC = $path;
last EXE;
}
}
}
unless ($ASCIIDOC) {
use Carp;
my $sep = WIN32 ? ';' : ':';
Carp::croak(
"Cannot find asciidoc or asciidoc.py in path " . join $sep => @path
);
}
# Make sure it looks like it will work.
my $output = gensym;
my $pid = open3 undef, $output, $output, $ASCIIDOC, '--version';
waitpid $pid, 0;
if ($?) {
use Carp;
local $/;
Carp::croak(
qq{$ASCIIDOC will not execute\n},
<$output>
);
}
}
# Arguments to pass to asciidoc.
# Restore --safe if Asciidoc ever fixes it with the XHTML back end.
# https://groups.google.com/forum/#!topic/asciidoc/yEr5PqHm4-o
my @OPTIONS = qw(
--no-header-footer
--out-file -
--attribute newline=\\n
);
sub parser {
my ($file, $encoding, $opts) = @_;
my $html = do {
my $fh = _fh(
$ASCIIDOC, @OPTIONS,
'--attribute' => "encoding=$encoding",
$file
);
binmode $fh, ":encoding($encoding)";
local $/;
<$fh>;
};
# Make sure we have something.
return unless $html =~ /\S/;
utf8::encode $html;
return qq{<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
$html
</body>
</html>
};
}
# Stolen from SVN::Notify.
sub _fh {
# Ignored; looks like docutils always emits UTF-8.
if (WIN32) {
my $cmd = join join(q{" "}, @_) . q{"|};
open my $fh, $cmd or die "Cannot fork: $!\n";
return $fh;
}
my $pid = open my $fh, '-|';
die "Cannot fork: $!\n" unless defined $pid;
if ($pid) {
# Parent process, return the file handle.
return $fh;
} else {
# Child process. Execute the commands.
exec @_ or die "Cannot exec $_[0]: $!\n";
# Not reached.
}
}
1;
__END__
=head1 Name
Text::Markup::Asciidoc - Asciidoc parser for Text::Markup
=head1 Synopsis
use Text::Markup;
my $html = Text::Markup->new->parse(file => 'hello.adoc');
=head1 Description
This is the L<Asciidoc|http://www.methods.co.nz/asciidoc/> parser for
L<Text::Markup>. It depends on the C<asciidoc> command-line application, for
which there are many
L<binary distributions|http://www.methods.co.nz/asciidoc/INSTALL.html>. It
recognizes files with the following extensions as Asciidoc:
=over
=item F<.asciidoc>
=item F<.asc>
=item F<.adoc>
=back
=head1 Author
David E. Wheeler <david@justatheory.com>
=head1 Copyright and License
Copyright (c) 2012-2014 David E. Wheeler. Some Rights Reserved.
This module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
=cut