| 1 |
<?php
|
| 2 |
// $Id$
|
| 3 |
|
| 4 |
$LATEX_VERBATIM_START_MAGIC = "!!!!!BEGIN_PRE!!!!!:";
|
| 5 |
$LATEX_VERBATIM_END_MAGIC = ":!!!!!END_PRE!!!!!";
|
| 6 |
|
| 7 |
function latex_help($section) {
|
| 8 |
switch ($section) {
|
| 9 |
case "admin/modules#description":
|
| 10 |
$output = "Enables users to submit TeX/LaTeX-formatted texts.";
|
| 11 |
break;
|
| 12 |
case "admin/latex/help":
|
| 13 |
$output = "<p>Very primitive filter lets your users use some of TeX/LaTeX commands in their postings.</p>";
|
| 14 |
break;
|
| 15 |
}
|
| 16 |
return t($output);
|
| 17 |
}
|
| 18 |
|
| 19 |
/**
|
| 20 |
* Implementation of filter_filter().
|
| 21 |
*/
|
| 22 |
function latex_filter($op, $delta = 0, $format = -1, $text = '') {
|
| 23 |
switch ($op) {
|
| 24 |
case 'list':
|
| 25 |
return array(t('TeX/LaTeX'));
|
| 26 |
case 'description':
|
| 27 |
return t("Allows to use some elements of TeX/LaTeX.");
|
| 28 |
case 'settings':
|
| 29 |
$output = form_select(t("Recognize TeX/LaTeX commands"), "latex_filter_link", variable_get("latex_filter_link", 0), array(t("Show unknown commands"), t("Strip unknown commands")), t('Enable usage of TeX/LaTeX commands in user-distributed content. If option set to "Strip unknown commands", then unrecognized TeX/LaTeX commands are not showed in output. If option set to "Show unknown commands", then arguments of all unrecognized commands are showed in HTML-output.'));
|
| 30 |
$output .= form_textarea(t("Extend LaTeX filter with your custom commands"), "latex_custom_commands", variable_get("latex_custom_commands", ""), 70, 7, t('Define your custom regexps (one per line) like this example:<code> \link{(.*)}{(.*)} <a href="$1">$2</a> </code>- separate pattern part from replace parts with one space character. For inserting space in pattern part use numeric code "\040". '));
|
| 31 |
return form_group(t('LaTeX filter'), $output);
|
| 32 |
case 'process':
|
| 33 |
return _latex_filter_process($text);
|
| 34 |
default:
|
| 35 |
return $text;
|
| 36 |
}
|
| 37 |
}
|
| 38 |
|
| 39 |
function _latex_filter_process($text) {
|
| 40 |
// Save verbatims from conversions:
|
| 41 |
$text = str_replace("\begin{verbatim}", "<pre>", $text);
|
| 42 |
$text = str_replace("\end{verbatim}", "</pre>", $text);
|
| 43 |
$text = preg_replace_callback("|<pre>(.*)</pre>|smU", "_latex_hash_verbatim", $text);
|
| 44 |
|
| 45 |
// Convert some special characters:
|
| 46 |
$text = str_replace("\TeX", "T<small>E</small>X", $text);
|
| 47 |
$text = str_replace("\LaTeX", "L<sup><small>A</small></sup>T<small>E</small>X", $text);
|
| 48 |
$text = str_replace("\copyright", "©", $text);
|
| 49 |
$text = str_replace("\dots", "…", $text);
|
| 50 |
$text = str_replace("\ldots", "…", $text);
|
| 51 |
$text = str_replace("\cdots", "…", $text);
|
| 52 |
$text = str_replace("\pm", "±", $text);
|
| 53 |
$text = str_replace("\div", "÷", $text);
|
| 54 |
$text = str_replace("\le", "≤", $text);
|
| 55 |
$text = str_replace("\ge", "≥", $text);
|
| 56 |
$text = str_replace("\lt", "<", $text);
|
| 57 |
$text = str_replace("\gt", ">", $text);
|
| 58 |
$text = str_replace("``", '“', $text);
|
| 59 |
$text = str_replace("''", '”', $text);
|
| 60 |
$text = str_replace("\;", " ", $text);
|
| 61 |
// BUG: next two lines never pass to filter if Drupal HTML filtering ON and strip unknown tags
|
| 62 |
$text = str_replace("<<", '«', $text);
|
| 63 |
$text = str_replace(">>", '»', $text);
|
| 64 |
$text = str_replace("~---", " —", $text); // I not sure for TeX standards for dash conversion, but Latex on my system eat such things and produce appropriate longdashes
|
| 65 |
$text = str_replace(" ---", " —", $text);
|
| 66 |
$text = str_replace(" --", " —", $text);
|
| 67 |
$text = str_replace("-{}-", "--", $text);
|
| 68 |
$text = str_replace("\ ", " ", $text);
|
| 69 |
|
| 70 |
// Custom commands (from `latex_custom_commands` site variable):
|
| 71 |
if ($lines = explode("\n", variable_get("latex_custom_commands", ""))) {
|
| 72 |
foreach ($lines as $line) {
|
| 73 |
if (! trim($line))
|
| 74 |
continue;
|
| 75 |
list($pattern, $command) = split(' ', $line, 2);
|
| 76 |
$text = preg_replace($pattern, $command, $text);
|
| 77 |
}
|
| 78 |
}
|
| 79 |
|
| 80 |
// TeX comments -> HTML comments
|
| 81 |
$text = preg_replace("/[^\\\]?%(.*)/iS", "<!-- $1 -->", $text);
|
| 82 |
|
| 83 |
// Text blocks:
|
| 84 |
$text = str_replace("\begin{itemize}", "<ul>", $text);
|
| 85 |
$text = str_replace("\begin{list}", "<ul>", $text);
|
| 86 |
$text = str_replace("\begin{enumerate}", "<ol>", $text);
|
| 87 |
$text = str_replace("\begin{description}", "<dl>", $text);
|
| 88 |
$text = str_replace("\item", "<li>", $text);
|
| 89 |
$text = preg_replace("/\\\item{(.*)}/U", "<li> $1", $text);
|
| 90 |
$text = str_replace("\end{description}", "</dl>", $text);
|
| 91 |
$text = str_replace("\end{enumerate}", "</ol>", $text);
|
| 92 |
$text = str_replace("\end{list}", "</ul>", $text);
|
| 93 |
$text = str_replace("\end{itemize}", "</ul>", $text);
|
| 94 |
$text = preg_replace("/\\\begin{flush(left|right)}/U", '<div align="$1">', $text);
|
| 95 |
$text = preg_replace("/\\\end{flush(left|right)}/U", '</div>', $text);
|
| 96 |
|
| 97 |
// Skip these commands:
|
| 98 |
$text = str_replace("\\\(begin|end){document}", "", $text);
|
| 99 |
$text = str_replace("\\\documentclass.*{.*})", "", $text);
|
| 100 |
$text = str_replace("\\\usepackage{.*}", "", $text);
|
| 101 |
$text = str_replace("\\\thispagestyle{.*}", "", $text);
|
| 102 |
$text = str_replace("\\\pagestyle{.*}", "", $text);
|
| 103 |
|
| 104 |
// Captions:
|
| 105 |
$text = preg_replace("/\\\section{(.*)}/U", "<h2>$1</h2>", $text);
|
| 106 |
$text = preg_replace("/\\\subsection{(.*)}/U", "<h3>$1</h3>", $text);
|
| 107 |
$text = preg_replace("/\\\subsubsection{(.*)}/U", "<h4>$1</h4>", $text);
|
| 108 |
$text = preg_replace("/\\\subsubsubsection{(.*)}/U", "<h5>$1</h5>", $text);
|
| 109 |
|
| 110 |
// Font styles:
|
| 111 |
$text = preg_replace("/{\\\(em|it) (.*)}/U", "<i>$2</i>", $text);
|
| 112 |
$text = preg_replace("/\\\\(emph|textit|textsl){(.*)}/U", "<i>$2</i>", $text);
|
| 113 |
$text = preg_replace("/{\\\\tt (.*)}/U", "<code>$1</code>", $text);
|
| 114 |
$text = preg_replace("/\\\\texttt{(.*)}/U", "<code>$1</code>", $text);
|
| 115 |
$text = preg_replace("/{\\\bf (.*)}/U", "<b>$1</b>", $text);
|
| 116 |
$text = preg_replace("/\\\\textbf{(.*)}/U", "<b>$1</b>", $text);
|
| 117 |
$text = preg_replace("/{\\\textsc (.*)}/U", "<small>$1</small>", $text);
|
| 118 |
|
| 119 |
// Footnotes:
|
| 120 |
preg_match_all("/\\\footnote{((.)(.*))}/uUms", $text, $footnotes);
|
| 121 |
if ($footnotes) {
|
| 122 |
$text = preg_replace_callback("/\\\footnote{((.)(.*))}/uUms", "_latex_hash_name", $text);
|
| 123 |
}
|
| 124 |
|
| 125 |
// Unknown commands visibility:
|
| 126 |
if (variable_get("latex_filter_link", 0) == 1) {
|
| 127 |
// ignore unknown commands:
|
| 128 |
$text = preg_replace("/\\\[a-z0-9\[\]]+{(.*)}/Ui", "", $text);
|
| 129 |
}
|
| 130 |
else {
|
| 131 |
// show unknown commands
|
| 132 |
$text = preg_replace("/\\\([a-z0-9\[\]]+){(.*)}/Ui", "\$1\{$2}", $text);
|
| 133 |
}
|
| 134 |
|
| 135 |
// Finally some miscellaneous conversions:
|
| 136 |
// $text = preg_replace("/(<br \/>|<\/h[1-9]>|<\/[uo]l>)\s*$^\s*/ms", "$1", $text); // new paragraph if command on next line (need testing)
|
| 137 |
//$text = preg_replace("/(.*)^\s*$/msU", "$1<br /><br />", $text); // new paragraph in other cases
|
| 138 |
// $text = preg_replace("/\\\(.){}/U", "$1", $text); // any single char escaped with \{}
|
| 139 |
// $text = preg_replace("/\\\([#$%&_ ])/U", "$1", $text); // and other special chars
|
| 140 |
// BR-conversions commented out, because it now dealed with HTML-filter
|
| 141 |
$text = str_replace("\\", "<br />", $text); // EOL
|
| 142 |
$text = str_replace("\backslash", "\\", $text);
|
| 143 |
|
| 144 |
|
| 145 |
// Return to text previously saved verbatims:
|
| 146 |
foreach (_latex_hash_verbatim() as $key => $value) {
|
| 147 |
$text = str_replace($LATEX_VERBATIM_START_MAGIC. $key. $LATEX_VERBATIM_END_MAGIC, "<pre>". $value. "</pre>", $text);
|
| 148 |
}
|
| 149 |
|
| 150 |
if($footnotes) {
|
| 151 |
$footnote = "<hr><a class=\"footnotes\" name=\"node_footnotes\">";
|
| 152 |
for ($i=0; $i< count($footnotes[1]); $i++) {
|
| 153 |
$footnote .= "<a class=\"footnote\" href=\"". $_GET["q"]. "#". md5($footnotes[1][$i]). "\">[". $footnotes[2][$i]. "]</a> — ". $footnotes[1][$i]. "<br />";
|
| 154 |
}
|
| 155 |
$footnote .= "</a>\n";
|
| 156 |
}
|
| 157 |
return $text . $footnote;
|
| 158 |
}
|
| 159 |
|
| 160 |
function _latex_hash_verbatim($matches = NULL) {
|
| 161 |
static $verbatim = array();
|
| 162 |
if ($matches) {
|
| 163 |
$verbatim = array(md5($matches[1]) => $matches[1]);
|
| 164 |
return $LATEX_VERBATIM_START_MAGIC. md5($matches[1]). $LATEX_VERBATIM_END_MAGIC;
|
| 165 |
} else {
|
| 166 |
return $verbatim;
|
| 167 |
}
|
| 168 |
}
|
| 169 |
|
| 170 |
function _latex_hash_name($matches) {
|
| 171 |
return "<a class=\"footnote_link\" name=\"". md5($matches[1]). "\" href=\"". $_GET["q"]. "#node_footnotes\"><sup><small>[". $matches[2]. "]</small></sup></a>";
|
| 172 |
}
|
| 173 |
|
| 174 |
?>
|