use Digest::MD5 qw(md5_hex);
use File::Temp qw(tempdir);
use HTML::Entities;
-use IkiWiki 2.00;
-
-sub import { #{{{
+use Encode;
+use IkiWiki 3.00;
+
+my $default_prefix = <<EOPREFIX;
+\\documentclass{article}
+\\usepackage{amsmath}
+\\usepackage{amsfonts}
+\\usepackage{amssymb}
+\\pagestyle{empty}
+\\begin{document}
+EOPREFIX
+
+my $default_postfix = '\\end{document}';
+
+sub import {
+ hook(type => "getsetup", id => "teximg", call => \&getsetup);
hook(type => "preprocess", id => "teximg", call => \&preprocess);
-} #}}}
-
-sub preprocess (@) { #{{{
+}
+
+sub getsetup () {
+ return
+ plugin => {
+ safe => 1,
+ rebuild => undef,
+ section => "widget",
+ },
+ teximg_dvipng => {
+ type => "boolean",
+ description => "Should teximg use dvipng to render, or dvips and convert?",
+ safe => 0,
+ rebuild => undef,
+ },
+ teximg_prefix => {
+ type => "string",
+ example => $default_prefix,
+ description => "LaTeX prefix for teximg plugin",
+ safe => 0, # Not sure how secure LaTeX is...
+ rebuild => 1,
+ },
+ teximg_postfix => {
+ type => "string",
+ example => $default_postfix,
+ description => "LaTeX postfix for teximg plugin",
+ safe => 0, # Not sure how secure LaTeX is...
+ rebuild => 1,
+ },
+}
+
+sub preprocess (@) {
my %params = @_;
my $height = $params{height};
my $code = $params{code};
if (! defined $code && ! length $code) {
- return "[[teximg ".gettext("missing tex code"). "]]";
- }
-
- if (check($code)) {
- return create($code, check_height($height), \%params);
- }
- else {
- return "[[teximg ".gettext("code includes disallowed latex commands"). "]]";
+ error gettext("missing tex code");
}
-} #}}}
+ return create($code, check_height($height), \%params);
+}
-sub check_height ($) { #{{{
+sub check_height ($) {
# Since latex doesn't support unlimited scaling this function
# returns the closest supported size.
my $height =shift;
}
}
return $ret;
-} #}}}
+}
-sub create ($$$) { #{{{
+sub create ($$$) {
# This function calls the image generating function and returns
# the <img .. /> for the generated image.
my $code = shift;
$height = 12;
}
- my $digest = md5_hex($code, $height);
+ my $digest = md5_hex(Encode::encode_utf8($code), $height);
- my $teximgdir = "/teximg";
- my $imglink = "$teximgdir/$digest.png";
- my $imglog = "$teximgdir/$digest.log";
- will_render($params->{destpage}, $imglink);
- will_render($params->{destpage}, $imglog);
+ my $imglink= $params->{page} . "/$digest.png";
+ my $imglog = $params->{page} . "/$digest.log";
+ will_render($params->{page}, $imglink);
+ will_render($params->{page}, $imglog);
- my $imgurl;
- my $logurl;
- if (! $params->{preview}) {
- $imgurl = urlto($imglink, $params->{destpage});
- $logurl = urlto($imglog, $params->{destpage});
- }
- else {
- $imgurl="$config{url}/$teximgdir/$digest.png";
- $logurl="$config{url}/$teximgdir/$digest.log";
- }
+ my $imgurl=urlto($imglink, $params->{destpage});
+ my $logurl=urlto($imglog, $params->{destpage});
if (-e "$config{destdir}/$imglink" ||
- gen_image($code, $height, $digest, $teximgdir)) {
+ gen_image($code, $height, $digest, $params->{page})) {
return qq{<img src="$imgurl" alt="}
.(exists $params->{alt} ? $params->{alt} : encode_entities($code))
.qq{" class="teximg" />};
}
else {
- return qq{[[teximg <a href="$logurl">}.gettext("failed to generate image from code")."</a>]]";
+ error qq{<a href="$logurl">}.gettext("failed to generate image from code")."</a>";
}
-} #}}}
+}
-sub gen_image ($$$$) { #{{{
+sub gen_image ($$$$) {
# Actually creates the image.
my $code = shift;
my $height = shift;
my $digest = shift;
my $imagedir = shift;
- #TODO This should move into the setup file.
- my $tex = '\documentclass['.$height.'pt]{scrartcl}';
- $tex .= '\usepackage[version=3]{mhchem}';
- $tex .= '\usepackage{amsmath}';
- $tex .= '\usepackage{amsfonts}';
- $tex .= '\usepackage{amssymb}';
- $tex .= '\pagestyle{empty}';
- $tex .= '\begin{document}';
+ if (!defined $config{teximg_prefix}) {
+ $config{teximg_prefix} = $default_prefix;
+ }
+ if (!defined $config{teximg_postfix}) {
+ $config{teximg_postfix} = $default_postfix;
+ }
+ if (!defined $config{teximg_dvipng}) {
+ $config{teximg_dvipng} = length `which dvipng 2>/dev/null`;
+ }
+
+ my $tex = $config{teximg_prefix};
$tex .= '$$'.$code.'$$';
- $tex .= '\end{document}';
+ $tex .= $config{teximg_postfix};
+ $tex =~ s!\\documentclass{article}!\\documentclass[${height}pt]{article}!g;
+ $tex =~ s!\\documentclass{scrartcl}!\\documentclass[${height}pt]{scrartcl}!g;
my $tmp = eval { create_tmp_dir($digest) };
if (! $@ &&
writefile("$digest.tex", $tmp, $tex) &&
- system("cd $tmp; latex --interaction=nonstopmode $tmp/$digest.tex > /dev/null") == 0 &&
- system("dvips -E $tmp/$digest.dvi -o $tmp/$digest.ps 2> $tmp/$digest.log") == 0 &&
+ system("cd $tmp; shell_escape=f openout_any=p openin_any=p latex --interaction=nonstopmode $digest.tex < /dev/null > /dev/null") == 0 &&
# ensure destination directory exists
writefile("$imagedir/$digest.png", $config{destdir}, "") &&
- system("convert -density 120 -trim -transparent \"#FFFFFF\" $tmp/$digest.ps $config{destdir}/$imagedir/$digest.png > $tmp/$digest.log") == 0) {
+ (($config{teximg_dvipng} &&
+ system("dvipng -D 120 -bg Transparent -T tight -o $config{destdir}/$imagedir/$digest.png $tmp/$digest.dvi > $tmp/$digest.log") == 0
+ ) || (!$config{teximg_dvipng} &&
+ system("dvips -E $tmp/$digest.dvi -o $tmp/$digest.ps 2> $tmp/$digest.log") == 0 &&
+ system("convert -density 120 -trim -transparent \"#FFFFFF\" $tmp/$digest.ps $config{destdir}/$imagedir/$digest.png > $tmp/$digest.log") == 0
+ ))) {
return 1;
}
else {
# store failure log
- my $log;
+ my $log="";
{
- open(my $f, '<', "$tmp/$digest.log");
- local $/=undef;
- $log = <$f>;
- close($f);
+ if (open(my $f, '<', "$tmp/$digest.log")) {
+ local $/=undef;
+ $log = <$f>;
+ close($f);
+ }
}
writefile("$digest.log", "$config{destdir}/$imagedir", $log);
return 0;
}
-} #}}}
+}
-sub create_tmp_dir ($) { #{{{
+sub create_tmp_dir ($) {
# Create a temp directory, it will be removed when ikiwiki exits.
my $base = shift;
my $template = $base.".XXXXXXXXXX";
my $tmpdir = tempdir($template, TMPDIR => 1, CLEANUP => 1);
return $tmpdir;
-} #}}}
-
-sub check ($) { #{{{
- # Check if the code is ok
- my $code = shift;
-
- my @badthings = (
- qr/\$\$/,
- qr/\\include/,
- qr/\\includegraphic/,
- qr/\\usepackage/,
- qr/\\newcommand/,
- qr/\\renewcommand/,
- qr/\\def/,
- qr/\\input/,
- qr/\\open/,
- qr/\\loop/,
- qr/\\errorstopmode/,
- qr/\\scrollmode/,
- qr/\\batchmode/,
- qr/\\read/,
- qr/\\write/,
- );
-
- foreach my $thing (@badthings) {
- if ($code =~ m/$thing/ ) {
- return 0;
- }
- }
- return 1;
-} #}}}
+}
1