2015-07-28 22:44:53 +02:00
|
|
|
|
# Copyright (C) 2003–2015 Alex Schroeder <alex@gnu.org>
|
2004-04-25 15:17:24 +00:00
|
|
|
|
# Copyright (C) 2004 Haixing Hu <huhaixing@msn.com>
|
2005-03-15 14:50:04 +00:00
|
|
|
|
# Copyright (C) 2004, 2005 Todd Neal <tolchz@tolchz.net>
|
2004-02-13 18:34:18 +00:00
|
|
|
|
#
|
2015-03-29 14:56:52 +02:00
|
|
|
|
# This program is free software: you can redistribute it and/or modify it under
|
|
|
|
|
|
# the terms of the GNU General Public License as published by the Free Software
|
|
|
|
|
|
# Foundation, either version 3 of the License, or (at your option) any later
|
|
|
|
|
|
# version.
|
2004-02-13 18:34:18 +00:00
|
|
|
|
#
|
2015-03-29 14:56:52 +02:00
|
|
|
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
|
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
|
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
2004-02-13 18:34:18 +00:00
|
|
|
|
#
|
2015-03-29 14:56:52 +02:00
|
|
|
|
# You should have received a copy of the GNU General Public License along with
|
|
|
|
|
|
# this program. If not, see <http://www.gnu.org/licenses/>.
|
2004-10-04 21:27:14 +00:00
|
|
|
|
#
|
2004-10-04 02:58:29 +00:00
|
|
|
|
# External programs needed
|
|
|
|
|
|
# LaTeX - http://www.latex-project.org
|
|
|
|
|
|
# TeX - http://www.tug.org/teTeX/
|
2004-10-04 15:25:12 +00:00
|
|
|
|
#
|
2015-03-27 03:01:01 +02:00
|
|
|
|
# And one of :
|
2004-10-04 15:25:12 +00:00
|
|
|
|
# dvipng - http://sourceforge.net/projects/dvipng/
|
|
|
|
|
|
# convert - http://www.imagemagick.org/
|
2004-10-04 21:27:14 +00:00
|
|
|
|
#
|
|
|
|
|
|
# CSS Styles:
|
2015-03-27 03:01:01 +02:00
|
|
|
|
# span.eqCount
|
2004-10-04 21:27:14 +00:00
|
|
|
|
# img.LaTeX
|
|
|
|
|
|
# img.InlineMath
|
|
|
|
|
|
# img.DisplayMath
|
2004-10-04 02:58:29 +00:00
|
|
|
|
|
2015-03-29 14:56:52 +02:00
|
|
|
|
use strict;
|
2015-08-18 10:48:03 +02:00
|
|
|
|
use v5.10;
|
2015-03-27 03:01:01 +02:00
|
|
|
|
|
2012-07-21 00:36:33 +02:00
|
|
|
|
use File::Glob ':glob';
|
2015-03-27 03:01:01 +02:00
|
|
|
|
|
2015-04-10 13:31:28 +03:00
|
|
|
|
our ($DataDir, @MyRules);
|
|
|
|
|
|
our ($LatexDir, $LatexLinkDir, $LatexExtendPath, $LatexSingleDollars);
|
2004-02-13 18:34:18 +00:00
|
|
|
|
|
2004-10-04 15:25:12 +00:00
|
|
|
|
# One of the following options must be set correctly to the full path of
|
|
|
|
|
|
# either dvipng or convert. If both paths are set correctly, dvipng is used
|
|
|
|
|
|
# instead of convert
|
2004-10-04 03:58:22 +00:00
|
|
|
|
my $dvipngPath = "/usr/bin/dvipng";
|
2004-10-04 15:25:12 +00:00
|
|
|
|
my $convertPath = "/usr/bin/convert";
|
2004-10-04 02:58:29 +00:00
|
|
|
|
|
2005-03-15 14:50:04 +00:00
|
|
|
|
# Set $dispErrors to display LaTeX errors inline on the page.
|
|
|
|
|
|
my $dispErrors = 1;
|
|
|
|
|
|
|
2015-03-27 03:01:01 +02:00
|
|
|
|
# Set $useMD5 to 1 if you want to use MD5 hashes for filenames, set it to 0 to use
|
|
|
|
|
|
# a url-encoded hash. If $useMD5 is set and the Digest::MD5 module is not available,
|
2004-10-04 15:25:12 +00:00
|
|
|
|
# latex.pl falls back to urlencode
|
2004-10-04 03:58:22 +00:00
|
|
|
|
my $useMD5 = 0;
|
2004-02-13 18:34:18 +00:00
|
|
|
|
|
2004-10-04 02:58:29 +00:00
|
|
|
|
# PATH must be extended in order to make latex available along with
|
2004-10-04 03:58:22 +00:00
|
|
|
|
# any binaries that it may need to work
|
2004-04-25 15:17:24 +00:00
|
|
|
|
$LatexExtendPath = ':/usr/share/texmf/bin:/usr/bin:/usr/local/bin';
|
2004-02-13 18:34:18 +00:00
|
|
|
|
|
2004-10-04 04:15:18 +00:00
|
|
|
|
# Allow single dollars signs to escape LaTeX math commands
|
2004-10-04 03:58:22 +00:00
|
|
|
|
$LatexSingleDollars = 0;
|
2004-10-04 02:58:29 +00:00
|
|
|
|
|
2004-10-04 04:15:18 +00:00
|
|
|
|
# Set $allowPlainTeX to 1 to allow normal LaTeX commands inside of $[ ]$
|
|
|
|
|
|
# to be executed outside of the math environment. This should only be done
|
|
|
|
|
|
# if your wiki is not publically editable because of the possible security risk
|
2015-03-27 03:01:01 +02:00
|
|
|
|
my $allowPlainLaTeX = 0;
|
2004-10-04 04:15:18 +00:00
|
|
|
|
|
2004-02-13 18:34:18 +00:00
|
|
|
|
# $LatexDir must be accessible from the outside as $LatexLinkDir. The
|
|
|
|
|
|
# first directory is used to *save* the pictures, the second directory
|
|
|
|
|
|
# is used to produce the *link* to the pictures.
|
2004-10-04 03:58:22 +00:00
|
|
|
|
#
|
2004-02-13 18:34:18 +00:00
|
|
|
|
# Example: You store the images in /org/org.emacswiki/htdocs/test/latex.
|
|
|
|
|
|
# This directory is reachable from the outside as http://www.emacswiki.org/test/latex/.
|
|
|
|
|
|
# /org/org.emacswiki/htdocs/test is your $DataDir.
|
|
|
|
|
|
$LatexDir = "$DataDir/latex";
|
2004-04-25 15:17:24 +00:00
|
|
|
|
$LatexLinkDir= "/wiki/latex";
|
2004-02-13 18:34:18 +00:00
|
|
|
|
|
2004-10-04 21:27:14 +00:00
|
|
|
|
# Text used when referencing equations with EQ(equationLabel)
|
|
|
|
|
|
my $eqAbbrev = "Eq. ";
|
2004-10-04 03:58:22 +00:00
|
|
|
|
|
2004-02-13 18:34:18 +00:00
|
|
|
|
# You also need a template stored as $DataDir/template.latex. The
|
|
|
|
|
|
# template must contain the string <math> where the LaTeX code is
|
2004-10-03 19:56:01 +00:00
|
|
|
|
# supposed to go. It will be created on the first run.
|
2004-02-13 19:30:12 +00:00
|
|
|
|
my $LatexDefaultTemplateName = "$LatexDir/template.latex";
|
|
|
|
|
|
|
2004-10-04 03:58:22 +00:00
|
|
|
|
|
2014-08-21 22:23:23 +02:00
|
|
|
|
AddModuleDescription('latex.pl', 'LaTeX Extension');
|
2004-10-04 03:58:22 +00:00
|
|
|
|
|
2004-10-04 21:27:14 +00:00
|
|
|
|
# Internal Equation counting and referencing variables
|
|
|
|
|
|
my $eqCounter = 0;
|
|
|
|
|
|
my %eqHash;
|
2004-10-04 03:58:22 +00:00
|
|
|
|
|
2004-02-13 19:30:12 +00:00
|
|
|
|
my $LatexDefaultTemplate = << 'EOT';
|
|
|
|
|
|
\documentclass[12pt]{article}
|
|
|
|
|
|
\pagestyle{empty}
|
|
|
|
|
|
\begin{document}
|
|
|
|
|
|
<math>
|
|
|
|
|
|
\end{document}
|
|
|
|
|
|
EOT
|
|
|
|
|
|
|
2004-02-13 18:34:18 +00:00
|
|
|
|
push(@MyRules, \&LatexRule);
|
|
|
|
|
|
|
|
|
|
|
|
sub LatexRule {
|
2015-08-23 21:22:12 +03:00
|
|
|
|
if (m/\G\\\[(\(.*?\))?((.*\n)*?.*?)\\\]/cg) {
|
2004-10-04 21:27:14 +00:00
|
|
|
|
my $label = $1;
|
|
|
|
|
|
my $latex = $2;
|
|
|
|
|
|
$label =~ s#\(?\)?##g;# Remove the ()'s from the label and convert case
|
2015-03-27 03:01:01 +02:00
|
|
|
|
$label =~ tr/A-Z/a-z/;
|
2004-10-04 21:27:14 +00:00
|
|
|
|
$eqCounter++;
|
|
|
|
|
|
$eqHash{$label} = $eqCounter;
|
|
|
|
|
|
return &MakeLaTeX("\\begin{displaymath} $latex \\end{displaymath}", "display math",$label);
|
2015-08-23 21:22:12 +03:00
|
|
|
|
} elsif (m/\G\$\$((.*\n)*?.*?)\$\$/cg) {
|
2004-04-25 15:32:45 +00:00
|
|
|
|
return &MakeLaTeX("\$\$ $1 \$\$", $LatexSingleDollars ? "display math" : "inline math");
|
2015-08-23 21:22:12 +03:00
|
|
|
|
} elsif ($LatexSingleDollars and m/\G\$((.*\n)*?.*?)\$/cg) {
|
2004-04-25 15:32:45 +00:00
|
|
|
|
return &MakeLaTeX("\$ $1 \$", "inline math");
|
2015-08-23 21:22:12 +03:00
|
|
|
|
} elsif ($allowPlainLaTeX && m/\G\$\[((.*\n)*?.*?)\]\$/cg) { #Pick up plain LaTeX commands
|
2015-03-27 03:01:01 +02:00
|
|
|
|
return &MakeLaTeX(" $1 ", "LaTeX");
|
2015-08-23 21:22:12 +03:00
|
|
|
|
} elsif (m/\GEQ\((.*?)\)/cg) { # Handle references to equations
|
2004-10-04 21:27:14 +00:00
|
|
|
|
my $label = $1;
|
2015-03-27 03:01:01 +02:00
|
|
|
|
$label =~ tr/A-Z/a-z/;
|
2004-10-04 21:27:14 +00:00
|
|
|
|
if ($eqHash{$label}) {
|
2015-03-29 14:56:52 +02:00
|
|
|
|
return $eqAbbrev . "<a href=\"#$label\">". $eqHash{$label} . "</a>";
|
2004-10-04 21:27:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
else {
|
2015-03-29 14:56:52 +02:00
|
|
|
|
return "[ Equation $label not found ]";
|
2004-10-04 21:27:14 +00:00
|
|
|
|
}
|
2004-02-13 18:34:18 +00:00
|
|
|
|
}
|
2015-02-27 12:10:18 +02:00
|
|
|
|
return;
|
2004-02-13 18:34:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub MakeLaTeX {
|
2004-10-04 21:27:14 +00:00
|
|
|
|
my ($latex, $type, $label) = @_;
|
2004-02-13 18:34:18 +00:00
|
|
|
|
$ENV{PATH} .= $LatexExtendPath if $LatexExtendPath and $ENV{PATH} !~ /$LatexExtendPath/;
|
2004-10-04 02:58:29 +00:00
|
|
|
|
|
2004-10-04 15:25:12 +00:00
|
|
|
|
# Select which binary to use for conversion of dvi to images
|
2015-03-27 03:01:01 +02:00
|
|
|
|
my $useConvert = 0;
|
2016-06-15 23:21:07 +02:00
|
|
|
|
if (not IsFile($dvipngPath)) {
|
|
|
|
|
|
if (not IsFile($convertPath)) {
|
2015-03-29 14:56:52 +02:00
|
|
|
|
return "[Error: dvipng binary and convert binary not found at $dvipngPath or $convertPath ]";
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
$useConvert = 1; # Fall back on convert if dvipng is missing and convert exists
|
|
|
|
|
|
}
|
2004-10-04 02:58:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2004-02-13 18:34:18 +00:00
|
|
|
|
$latex = UnquoteHtml($latex); # Change < back to <, for example
|
2004-10-04 03:58:22 +00:00
|
|
|
|
|
|
|
|
|
|
# User selects which hash to use
|
|
|
|
|
|
my $hash;
|
|
|
|
|
|
my $hasMD5;
|
2015-05-02 04:19:09 +03:00
|
|
|
|
$hasMD5 = eval { require Digest::MD5 } if $useMD5;
|
2004-10-04 03:58:22 +00:00
|
|
|
|
if ($useMD5 && $hasMD5) {
|
2015-03-29 14:56:52 +02:00
|
|
|
|
$hash = Digest::MD5::md5_base64($latex);
|
|
|
|
|
|
$hash =~ s/\//a/g;
|
2004-10-04 03:58:22 +00:00
|
|
|
|
} else {
|
2015-03-29 14:56:52 +02:00
|
|
|
|
$hash = UrlEncode($latex);
|
|
|
|
|
|
$hash =~ s/%//g;
|
2004-10-04 03:58:22 +00:00
|
|
|
|
}
|
2004-10-04 15:25:12 +00:00
|
|
|
|
|
2004-02-13 18:34:18 +00:00
|
|
|
|
# check cache
|
2016-06-15 23:21:07 +02:00
|
|
|
|
if (not IsFile("$LatexDir/$hash.png") or ZeroSize("$LatexDir/$hash.png")) {
|
2015-03-29 14:56:52 +02:00
|
|
|
|
# Then create the image
|
|
|
|
|
|
|
|
|
|
|
|
# read template and replace <math>
|
2016-06-15 23:21:07 +02:00
|
|
|
|
CreateDir($LatexDir);
|
|
|
|
|
|
if (not IsFile($LatexDefaultTemplateName)) {
|
2016-06-22 15:37:04 +02:00
|
|
|
|
open (my $F, '>', encode_utf8($LatexDefaultTemplateName)) or return '[Unable to write template]';
|
2015-05-02 03:19:25 +03:00
|
|
|
|
print $F $LatexDefaultTemplate;
|
|
|
|
|
|
close $F;
|
2015-03-29 14:56:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
my $template = ReadFileOrDie($LatexDefaultTemplateName);
|
2015-08-23 21:22:12 +03:00
|
|
|
|
$template =~ s/<math>/$latex/gi;
|
2015-03-29 14:56:52 +02:00
|
|
|
|
#setup rendering directory
|
|
|
|
|
|
my $dir = "$LatexDir/$hash";
|
2016-06-15 23:21:07 +02:00
|
|
|
|
if (IsDir($dir)) {
|
2016-06-19 15:55:46 +02:00
|
|
|
|
Unlink((Glob("$dir/*")));
|
2015-03-29 14:56:52 +02:00
|
|
|
|
} else {
|
2016-06-15 23:21:07 +02:00
|
|
|
|
CreateDir($dir);
|
2015-03-29 14:56:52 +02:00
|
|
|
|
}
|
2016-06-15 23:21:07 +02:00
|
|
|
|
ChangeDir($dir) or return "[Unable to switch to $dir]";
|
2015-03-29 14:56:52 +02:00
|
|
|
|
WriteStringToFile ("srender.tex", $template);
|
|
|
|
|
|
my $errorText = qx(latex srender.tex);
|
|
|
|
|
|
|
|
|
|
|
|
# We should not return until we're ready to clean up!
|
|
|
|
|
|
my $error = '';
|
|
|
|
|
|
|
|
|
|
|
|
if ($? && $dispErrors) {
|
|
|
|
|
|
$error = "[Illegal LaTeX markup: <pre>$latex</pre>] <br/> Error: <pre>$errorText</pre>";
|
|
|
|
|
|
} elsif ($?) {
|
|
|
|
|
|
$error = "[Illegal LaTeX markup: <pre>$latex</pre>] <br/>";
|
|
|
|
|
|
} else {
|
2004-10-04 21:27:14 +00:00
|
|
|
|
my $output;
|
2015-03-27 03:01:01 +02:00
|
|
|
|
|
2004-10-04 21:27:14 +00:00
|
|
|
|
# Use specified binary to convert dvi to png
|
2015-03-27 03:01:01 +02:00
|
|
|
|
if ($useConvert) {
|
2015-03-29 14:56:52 +02:00
|
|
|
|
$output = qx($convertPath -antialias -crop 0x0 -density 120x120 -transparent white srender.dvi srender1.png );
|
|
|
|
|
|
$error = "[convert error $? ($output)]" if $?;
|
2004-10-04 21:27:14 +00:00
|
|
|
|
} else {
|
2015-03-29 14:56:52 +02:00
|
|
|
|
$output = qx($dvipngPath -T tight -bg Transparent srender.dvi);
|
|
|
|
|
|
$error = "[dvipng error $? ($output)]" if $?;
|
2004-10-04 21:27:14 +00:00
|
|
|
|
}
|
2015-04-17 01:43:19 +03:00
|
|
|
|
|
2016-06-15 23:21:07 +02:00
|
|
|
|
if (not $error and IsFile('srender1.png') and not ZeroSize('srender1.png')) {
|
2015-03-29 14:56:52 +02:00
|
|
|
|
my $png = ReadFileOrDie("srender1.png");
|
|
|
|
|
|
WriteStringToFile ("$LatexDir/$hash.png", $png);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$error = "[Error retrieving image for $latex]";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-06-15 23:21:07 +02:00
|
|
|
|
Unlink(glob('*'));
|
|
|
|
|
|
ChangeDir($LatexDir);
|
|
|
|
|
|
RemoveDir($dir);
|
2015-03-27 03:01:01 +02:00
|
|
|
|
|
2015-03-29 14:56:52 +02:00
|
|
|
|
return $error if $error;
|
|
|
|
|
|
}
|
|
|
|
|
|
# Finally print the html for the image
|
|
|
|
|
|
if ($type eq "inline math") { # inline math
|
|
|
|
|
|
return ("<img class='InlineMath' "
|
|
|
|
|
|
."src='$LatexLinkDir/$hash.png' alt='$latex'\/>");
|
|
|
|
|
|
} elsif ($type eq "display math") { # display math
|
|
|
|
|
|
my $ret;
|
|
|
|
|
|
if ($label) { $ret = "<a name='$label'>"; }
|
|
|
|
|
|
$ret .= "<center><img class='DisplayMath' "
|
|
|
|
|
|
."src='$LatexLinkDir/$hash.png' alt='$latex'> <span class=\'eqCount\'>($eqCounter)</span><\/center>";
|
|
|
|
|
|
return($ret);
|
|
|
|
|
|
} else { # latex format
|
|
|
|
|
|
return ("<img class='LaTeX' "
|
|
|
|
|
|
."src='$LatexLinkDir/$hash.png' alt='$latex' \/>");
|
2015-03-27 03:01:01 +02:00
|
|
|
|
}
|
2004-02-13 18:34:18 +00:00
|
|
|
|
}
|