r85706 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r85705‎ | r85706 | r85707 >
Date:00:39, 9 April 2011
Author:brion
Status:resolved (Comments)
Tags:config 
Comment:
Initial stab at breaking math/texvc out to Math extension.

* (bug 14202) $wgUseTeX has been superseded by the Math extension. To re-enable
math conversion after upgrading, obtain the Math extension from SVN or from
http://www.mediawiki.org/wiki/Extension:Math and add to LocalSettings.php:
require_once "$IP/extensions/Math/Math.php";

This is an initial stab, and a few things remain to be cleaned up:
* messages need to be moved from core to extension
* MW_MATH_* constants should be moved to the extension from core
* old back-compat math names interfaces using those constants should be removed from message files
* classic edit toolbar's math button should be added from the extension (or else dropped) -- currently there's not a clean hook, but could do it by JS
* couple of things like the 'armourMath' function on Language & LanguageConverter may want to be redone just as an unconditional, if that's simpler.

Setting $wgUseTeX alone will no longer have any affect. The var's still there for the moment as a few bits still need to be fully moved out from core.
Modified paths:
  • /trunk/extensions/Math (added) (history)
  • /trunk/extensions/Math/Math.body.php (added) (history)
  • /trunk/extensions/Math/Math.hooks.php (added) (history)
  • /trunk/extensions/Math/Math.php (added) (history)
  • /trunk/extensions/Math/math (added) (history)
  • /trunk/extensions/Math/math/README (modified) (history)
  • /trunk/extensions/Math/mathParserTests.txt (added) (history)
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/Math.php (deleted) (history)
  • /trunk/phase3/includes/Preferences.php (modified) (history)
  • /trunk/phase3/includes/Setup.php (modified) (history)
  • /trunk/phase3/includes/installer/LocalSettingsGenerator.php (modified) (history)
  • /trunk/phase3/includes/parser/CoreTagHooks.php (modified) (history)
  • /trunk/phase3/includes/parser/Parser.php (modified) (history)
  • /trunk/phase3/math (deleted) (history)
  • /trunk/phase3/tests/parser/parserTest.inc (modified) (history)
  • /trunk/phase3/tests/parser/parserTests.txt (modified) (history)
  • /trunk/phase3/tests/testHelpers.inc (modified) (history)

Diff [purge]

Index: trunk/phase3/tests/testHelpers.inc
@@ -600,16 +600,6 @@
601601 continue;
602602 }
603603
604 - global $wgUseTeX;
605 -
606 - if ( preg_match( '/\\bmath\\b/i', $data['options'] ) && !$wgUseTeX ) {
607 - # don't run math tests if $wgUseTeX is set to false in LocalSettings
608 - $data = array();
609 - $section = null;
610 -
611 - continue;
612 - }
613 -
614604 $this->test = array(
615605 'test' => ParserTest::chomp( $data['test'] ),
616606 'input' => ParserTest::chomp( $data['input'] ),
Index: trunk/phase3/tests/parser/parserTest.inc
@@ -631,8 +631,6 @@
632632 'wgNoFollowDomainExceptions' => array(),
633633 'wgThumbnailScriptPath' => false,
634634 'wgUseImageResize' => false,
635 - 'wgUseTeX' => isset( $opts['math'] ),
636 - 'wgMathDirectory' => $this->uploadDir . '/math',
637635 'wgLocaltimezone' => 'UTC',
638636 'wgAllowExternalImages' => true,
639637 'wgUseTidy' => false,
Index: trunk/phase3/tests/parser/parserTests.txt
@@ -3154,16 +3154,6 @@
31553155 !!end
31563156
31573157 !! test
3158 -pre-save transform: comment containing math
3159 -!! options
3160 -pst
3161 -!! input
3162 -<!-- <math>data</math> -->
3163 -!!result
3164 -<!-- <math>data</math> -->
3165 -!!end
3166 -
3167 -!! test
31683158 pre-save transform: <noinclude> in subst (bug 3298)
31693159 !! options
31703160 pst
@@ -3662,27 +3652,6 @@
36633653
36643654 !! end
36653655
3666 -!! test
3667 -BUG 1887: A <math> with a thumbnail- we don't render math in the parsertests by default,
3668 -so math is not stripped and turns up as escaped &lt;math&gt; tags.
3669 -!! input
3670 -[[Image:foobar.jpg|thumb|<math>2+2</math>]]
3671 -!! result
3672 -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="https://www.mediawiki.org/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="https://www.mediawiki.org/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>&lt;math&gt;2+2&lt;/math&gt;</div></div></div>
3673 -
3674 -!! end
3675 -
3676 -!! test
3677 -BUG 1887, part 2: A <math> with a thumbnail- math enabled
3678 -!! options
3679 -math
3680 -!! input
3681 -[[Image:foobar.jpg|thumb|<math>2+2</math>]]
3682 -!! result
3683 -<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="https://www.mediawiki.org/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="https://www.mediawiki.org/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><span class="texhtml" dir="ltr">2 + 2</span></div></div></div>
3684 -
3685 -!! end
3686 -
36873656 # Pending resolution to bug 368
36883657 !! test
36893658 BUG 648: Frameless image caption with a link
@@ -4798,15 +4767,6 @@
47994768
48004769 !! end
48014770
4802 -!! test
4803 -Math section safety when disabled
4804 -!! input
4805 -<math><script>alert(document.cookies);</script></math>
4806 -!! result
4807 -<p>&lt;math&gt;&lt;script&gt;alert(document.cookies);&lt;/script&gt;&lt;/math&gt;
4808 -</p>
4809 -!! end
4810 -
48114771 # More MSIE fun discovered by Tom Gilder
48124772
48134773 !! test
Index: trunk/phase3/includes/Math.php
@@ -1,343 +0,0 @@
2 -<?php
3 -/**
4 - * Contain everything related to <math> </math> parsing
5 - * @file
6 - * @ingroup Parser
7 - */
8 -
9 -/**
10 - * Takes LaTeX fragments, sends them to a helper program (texvc) for rendering
11 - * to rasterized PNG and HTML and MathML approximations. An appropriate
12 - * rendering form is picked and returned.
13 - *
14 - * @author Tomasz Wegrzanowski, with additions by Brion Vibber (2003, 2004)
15 - * @ingroup Parser
16 - */
17 -class MathRenderer {
18 - var $mode = MW_MATH_MODERN;
19 - var $tex = '';
20 - var $inputhash = '';
21 - var $hash = '';
22 - var $html = '';
23 - var $mathml = '';
24 - var $conservativeness = 0;
25 -
26 - function __construct( $tex, $params=array() ) {
27 - $this->tex = $tex;
28 - $this->params = $params;
29 - }
30 -
31 - function setOutputMode( $mode ) {
32 - $this->mode = $mode;
33 - }
34 -
35 - function render() {
36 - global $wgTmpDirectory, $wgInputEncoding;
37 - global $wgTexvc, $wgMathCheckFiles, $wgTexvcBackgroundColor;
38 -
39 - if( $this->mode == MW_MATH_SOURCE ) {
40 - # No need to render or parse anything more!
41 - # New lines are replaced with spaces, which avoids confusing our parser (bugs 23190, 22818)
42 - return ('<span class="tex" dir="ltr">$ ' . str_replace( "\n", " ", htmlspecialchars( $this->tex ) ) . ' $</span>');
43 - }
44 - if( $this->tex == '' ) {
45 - return; # bug 8372
46 - }
47 -
48 - if( !$this->_recall() ) {
49 - if( $wgMathCheckFiles ) {
50 - # Ensure that the temp and output directories are available before continuing...
51 - if( !file_exists( $wgTmpDirectory ) ) {
52 - if( !wfMkdirParents( $wgTmpDirectory ) ) {
53 - return $this->_error( 'math_bad_tmpdir' );
54 - }
55 - } elseif( !is_dir( $wgTmpDirectory ) || !is_writable( $wgTmpDirectory ) ) {
56 - return $this->_error( 'math_bad_tmpdir' );
57 - }
58 - }
59 -
60 - if( !is_executable( $wgTexvc ) ) {
61 - return $this->_error( 'math_notexvc' );
62 - }
63 - $cmd = $wgTexvc . ' ' .
64 - escapeshellarg( $wgTmpDirectory ).' '.
65 - escapeshellarg( $wgTmpDirectory ).' '.
66 - escapeshellarg( $this->tex ).' '.
67 - escapeshellarg( $wgInputEncoding ).' '.
68 - escapeshellarg( $wgTexvcBackgroundColor );
69 -
70 - if ( wfIsWindows() ) {
71 - # Invoke it within cygwin sh, because texvc expects sh features in its default shell
72 - $cmd = 'sh -c ' . wfEscapeShellArg( $cmd );
73 - }
74 -
75 - wfDebug( "TeX: $cmd\n" );
76 - $contents = wfShellExec( $cmd );
77 - wfDebug( "TeX output:\n $contents\n---\n" );
78 -
79 - if (strlen($contents) == 0) {
80 - return $this->_error( 'math_unknown_error' );
81 - }
82 -
83 - $retval = substr ($contents, 0, 1);
84 - $errmsg = '';
85 - if (($retval == 'C') || ($retval == 'M') || ($retval == 'L')) {
86 - if ($retval == 'C') {
87 - $this->conservativeness = 2;
88 - } else if ($retval == 'M') {
89 - $this->conservativeness = 1;
90 - } else {
91 - $this->conservativeness = 0;
92 - }
93 - $outdata = substr ($contents, 33);
94 -
95 - $i = strpos($outdata, "\000");
96 -
97 - $this->html = substr($outdata, 0, $i);
98 - $this->mathml = substr($outdata, $i+1);
99 - } else if (($retval == 'c') || ($retval == 'm') || ($retval == 'l')) {
100 - $this->html = substr ($contents, 33);
101 - if ($retval == 'c') {
102 - $this->conservativeness = 2;
103 - } else if ($retval == 'm') {
104 - $this->conservativeness = 1;
105 - } else {
106 - $this->conservativeness = 0;
107 - }
108 - $this->mathml = null;
109 - } else if ($retval == 'X') {
110 - $this->html = null;
111 - $this->mathml = substr ($contents, 33);
112 - $this->conservativeness = 0;
113 - } else if ($retval == '+') {
114 - $this->html = null;
115 - $this->mathml = null;
116 - $this->conservativeness = 0;
117 - } else {
118 - $errbit = htmlspecialchars( substr($contents, 1) );
119 - switch( $retval ) {
120 - case 'E':
121 - $errmsg = $this->_error( 'math_lexing_error', $errbit );
122 - break;
123 - case 'S':
124 - $errmsg = $this->_error( 'math_syntax_error', $errbit );
125 - break;
126 - case 'F':
127 - $errmsg = $this->_error( 'math_unknown_function', $errbit );
128 - break;
129 - default:
130 - $errmsg = $this->_error( 'math_unknown_error', $errbit );
131 - }
132 - }
133 -
134 - if ( !$errmsg ) {
135 - $this->hash = substr ($contents, 1, 32);
136 - }
137 -
138 - wfRunHooks( 'MathAfterTexvc', array( &$this, &$errmsg ) );
139 -
140 - if ( $errmsg ) {
141 - return $errmsg;
142 - }
143 -
144 - if (!preg_match("/^[a-f0-9]{32}$/", $this->hash)) {
145 - return $this->_error( 'math_unknown_error' );
146 - }
147 -
148 - if( !file_exists( "$wgTmpDirectory/{$this->hash}.png" ) ) {
149 - return $this->_error( 'math_image_error' );
150 - }
151 -
152 - if( filesize( "$wgTmpDirectory/{$this->hash}.png" ) == 0 ) {
153 - return $this->_error( 'math_image_error' );
154 - }
155 -
156 - $hashpath = $this->_getHashPath();
157 - if( !file_exists( $hashpath ) ) {
158 - wfSuppressWarnings();
159 - $ret = wfMkdirParents( $hashpath, 0755 );
160 - wfRestoreWarnings();
161 - if( !$ret ) {
162 - return $this->_error( 'math_bad_output' );
163 - }
164 - } elseif( !is_dir( $hashpath ) || !is_writable( $hashpath ) ) {
165 - return $this->_error( 'math_bad_output' );
166 - }
167 -
168 - if( !rename( "$wgTmpDirectory/{$this->hash}.png", "$hashpath/{$this->hash}.png" ) ) {
169 - return $this->_error( 'math_output_error' );
170 - }
171 -
172 - # Now save it back to the DB:
173 - if ( !wfReadOnly() ) {
174 - $outmd5_sql = pack('H32', $this->hash);
175 -
176 - $md5_sql = pack('H32', $this->md5); # Binary packed, not hex
177 -
178 - $dbw = wfGetDB( DB_MASTER );
179 - $dbw->replace( 'math', array( 'math_inputhash' ),
180 - array(
181 - 'math_inputhash' => $dbw->encodeBlob($md5_sql),
182 - 'math_outputhash' => $dbw->encodeBlob($outmd5_sql),
183 - 'math_html_conservativeness' => $this->conservativeness,
184 - 'math_html' => $this->html,
185 - 'math_mathml' => $this->mathml,
186 - ), __METHOD__
187 - );
188 - }
189 -
190 - // If we're replacing an older version of the image, make sure it's current.
191 - global $wgUseSquid;
192 - if ( $wgUseSquid ) {
193 - $urls = array( $this->_mathImageUrl() );
194 - $u = new SquidUpdate( $urls );
195 - $u->doUpdate();
196 - }
197 - }
198 -
199 - return $this->_doRender();
200 - }
201 -
202 - function _error( $msg, $append = '' ) {
203 - $mf = htmlspecialchars( wfMsg( 'math_failure' ) );
204 - $errmsg = htmlspecialchars( wfMsg( $msg ) );
205 - $source = htmlspecialchars( str_replace( "\n", ' ', $this->tex ) );
206 - return "<strong class='error'>$mf ($errmsg$append): $source</strong>\n";
207 - }
208 -
209 - function _recall() {
210 - global $wgMathDirectory, $wgMathCheckFiles;
211 -
212 - $this->md5 = md5( $this->tex );
213 - $dbr = wfGetDB( DB_SLAVE );
214 - $rpage = $dbr->selectRow( 'math',
215 - array( 'math_outputhash','math_html_conservativeness','math_html','math_mathml' ),
216 - array( 'math_inputhash' => $dbr->encodeBlob(pack("H32", $this->md5))), # Binary packed, not hex
217 - __METHOD__
218 - );
219 -
220 - if( $rpage !== false ) {
221 - # Tailing 0x20s can get dropped by the database, add it back on if necessary:
222 - $xhash = unpack( 'H32md5', $dbr->decodeBlob($rpage->math_outputhash) . " " );
223 - $this->hash = $xhash ['md5'];
224 -
225 - $this->conservativeness = $rpage->math_html_conservativeness;
226 - $this->html = $rpage->math_html;
227 - $this->mathml = $rpage->math_mathml;
228 -
229 - $filename = $this->_getHashPath() . "/{$this->hash}.png";
230 -
231 - if( !$wgMathCheckFiles ) {
232 - // Short-circuit the file existence & migration checks
233 - return true;
234 - }
235 -
236 - if( file_exists( $filename ) ) {
237 - if( filesize( $filename ) == 0 ) {
238 - // Some horrible error corrupted stuff :(
239 - wfSuppressWarnings();
240 - unlink( $filename );
241 - wfRestoreWarnings();
242 - } else {
243 - return true;
244 - }
245 - }
246 -
247 - if( file_exists( $wgMathDirectory . "/{$this->hash}.png" ) ) {
248 - $hashpath = $this->_getHashPath();
249 -
250 - if( !file_exists( $hashpath ) ) {
251 - wfSuppressWarnings();
252 - $ret = wfMkdirParents( $hashpath, 0755 );
253 - wfRestoreWarnings();
254 - if( !$ret ) {
255 - return false;
256 - }
257 - } elseif( !is_dir( $hashpath ) || !is_writable( $hashpath ) ) {
258 - return false;
259 - }
260 - if ( function_exists( "link" ) ) {
261 - return link ( $wgMathDirectory . "/{$this->hash}.png",
262 - $hashpath . "/{$this->hash}.png" );
263 - } else {
264 - return rename ( $wgMathDirectory . "/{$this->hash}.png",
265 - $hashpath . "/{$this->hash}.png" );
266 - }
267 - }
268 -
269 - }
270 -
271 - # Missing from the database and/or the render cache
272 - return false;
273 - }
274 -
275 - /**
276 - * Select among PNG, HTML, or MathML output depending on
277 - */
278 - function _doRender() {
279 - if( $this->mode == MW_MATH_MATHML && $this->mathml != '' ) {
280 - return Xml::tags( 'math',
281 - $this->_attribs( 'math',
282 - array( 'xmlns' => 'http://www.w3.org/1998/Math/MathML' ) ),
283 - $this->mathml );
284 - }
285 - if (($this->mode == MW_MATH_PNG) || ($this->html == '') ||
286 - (($this->mode == MW_MATH_SIMPLE) && ($this->conservativeness != 2)) ||
287 - (($this->mode == MW_MATH_MODERN || $this->mode == MW_MATH_MATHML) && ($this->conservativeness == 0))) {
288 - return $this->_linkToMathImage();
289 - } else {
290 - return Xml::tags( 'span',
291 - $this->_attribs( 'span',
292 - array( 'class' => 'texhtml',
293 - 'dir' => 'ltr'
294 - ) ),
295 - $this->html );
296 - }
297 - }
298 -
299 - function _attribs( $tag, $defaults=array(), $overrides=array() ) {
300 - $attribs = Sanitizer::validateTagAttributes( $this->params, $tag );
301 - $attribs = Sanitizer::mergeAttributes( $defaults, $attribs );
302 - $attribs = Sanitizer::mergeAttributes( $attribs, $overrides );
303 - return $attribs;
304 - }
305 -
306 - function _linkToMathImage() {
307 - $url = $this->_mathImageUrl();
308 -
309 - return Xml::element( 'img',
310 - $this->_attribs(
311 - 'img',
312 - array(
313 - 'class' => 'tex',
314 - 'alt' => $this->tex ),
315 - array(
316 - 'src' => $url ) ) );
317 - }
318 -
319 - function _mathImageUrl() {
320 - global $wgMathPath;
321 - $dir = $this->_getHashSubPath();
322 - return "$wgMathPath/$dir/{$this->hash}.png";
323 - }
324 -
325 - function _getHashPath() {
326 - global $wgMathDirectory;
327 - $path = $wgMathDirectory .'/' . $this->_getHashSubPath();
328 - wfDebug( "TeX: getHashPath, hash is: $this->hash, path is: $path\n" );
329 - return $path;
330 - }
331 -
332 - function _getHashSubPath() {
333 - return substr($this->hash, 0, 1)
334 - .'/'. substr($this->hash, 1, 1)
335 - .'/'. substr($this->hash, 2, 1);
336 - }
337 -
338 - public static function renderMath( $tex, $params=array(), ParserOptions $parserOptions = null ) {
339 - $math = new MathRenderer( $tex, $params );
340 - if ( $parserOptions )
341 - $math->setOutputMode( $parserOptions->getMath() );
342 - return $math->render();
343 - }
344 -}
Index: trunk/phase3/includes/parser/Parser.php
@@ -37,7 +37,7 @@
3838 * NOT $wgArticle, $wgUser or $wgTitle. Keep them away!
3939 *
4040 * settings:
41 - * $wgUseTex*, $wgUseDynamicDates*, $wgInterwikiMagic*,
 41+ * $wgUseDynamicDates*, $wgInterwikiMagic*,
4242 * $wgNamespacesWithSubpages, $wgAllowExternalImages*,
4343 * $wgLocaltimezone, $wgAllowSpecialInclusion*,
4444 * $wgMaxArticleSize*
Index: trunk/phase3/includes/parser/CoreTagHooks.php
@@ -16,16 +16,13 @@
1717 * @return void
1818 */
1919 static function register( $parser ) {
20 - global $wgRawHtml, $wgUseTeX;
 20+ global $wgRawHtml;
2121 $parser->setHook( 'pre', array( __CLASS__, 'pre' ) );
2222 $parser->setHook( 'nowiki', array( __CLASS__, 'nowiki' ) );
2323 $parser->setHook( 'gallery', array( __CLASS__, 'gallery' ) );
2424 if ( $wgRawHtml ) {
2525 $parser->setHook( 'html', array( __CLASS__, 'html' ) );
2626 }
27 - if ( $wgUseTeX ) {
28 - $parser->setHook( 'math', array( __CLASS__, 'math' ) );
29 - }
3027 }
3128
3229 static function pre( $text, $attribs, $parser ) {
@@ -59,18 +56,6 @@
6057 * @param $parser Parser
6158 * @return
6259 */
63 - static function math( $content, $attributes, $parser ) {
64 - global $wgContLang;
65 - return $wgContLang->armourMath( MathRenderer::renderMath( $content, $attributes, $parser->getOptions() ) );
66 - }
67 -
68 - /**
69 - * @static
70 - * @param $content
71 - * @param $attributes
72 - * @param $parser Parser
73 - * @return
74 - */
7560 static function gallery( $content, $attributes, $parser ) {
7661 return $parser->renderImageGallery( $content, $attributes );
7762 }
Index: trunk/phase3/includes/Setup.php
@@ -51,8 +51,6 @@
5252 if ( $wgUploadPath === false ) $wgUploadPath = "$wgScriptPath/images";
5353 if ( $wgUploadDirectory === false ) $wgUploadDirectory = "$IP/images";
5454
55 -if ( $wgMathPath === false ) $wgMathPath = "{$wgUploadPath}/math";
56 -if ( $wgMathDirectory === false ) $wgMathDirectory = "{$wgUploadDirectory}/math";
5755 if ( $wgTmpDirectory === false ) $wgTmpDirectory = "{$wgUploadDirectory}/tmp";
5856
5957 if ( $wgReadOnlyFile === false ) $wgReadOnlyFile = "{$wgUploadDirectory}/lock_yBgMBwiR";
Index: trunk/phase3/includes/installer/LocalSettingsGenerator.php
@@ -277,10 +277,6 @@
278278 ## this, if it's not already uncommented:
279279 {$hashedUploads}\$wgHashedUploadDirectory = false;
280280
281 -## If you have the appropriate support software installed
282 -## you can enable inline LaTeX equations:
283 -\$wgUseTeX = false;
284 -
285281 ## Set \$wgCacheDirectory to a writable directory on the web server
286282 ## to make your wiki go slightly faster. The directory should not
287283 ## be publically accessible from the web.
Index: trunk/phase3/includes/AutoLoader.php
@@ -159,7 +159,6 @@
160160 'MagicWordArray' => 'includes/MagicWord.php',
161161 'MagicWord' => 'includes/MagicWord.php',
162162 'MailAddress' => 'includes/UserMailer.php',
163 - 'MathRenderer' => 'includes/Math.php',
164163 'MediaWiki_I18N' => 'includes/SkinTemplate.php',
165164 'MediaWiki' => 'includes/Wiki.php',
166165 'Message' => 'includes/Message.php',
Index: trunk/phase3/includes/DefaultSettings.php
@@ -235,23 +235,6 @@
236236 $wgAppleTouchIcon = false;
237237
238238 /**
239 - * The URL path of the math directory. Defaults to "{$wgUploadPath}/math".
240 - *
241 - * See http://www.mediawiki.org/wiki/Manual:Enable_TeX for details about how to
242 - * set up mathematical formula display.
243 - */
244 -$wgMathPath = false;
245 -
246 -/**
247 - * The filesystem path of the math directory.
248 - * Defaults to "{$wgUploadDirectory}/math".
249 - *
250 - * See http://www.mediawiki.org/wiki/Manual:Enable_TeX for details about how to
251 - * set up mathematical formula display.
252 - */
253 -$wgMathDirectory = false;
254 -
255 -/**
256239 * The local filesystem path to a temporary directory. This is not required to
257240 * be web accessible.
258241 *
@@ -3800,29 +3783,7 @@
38013784 * Please see math/README for more information.
38023785 */
38033786 $wgUseTeX = false;
3804 -/** Location of the texvc binary */
3805 -$wgTexvc = $IP . '/math/texvc';
3806 -/**
3807 - * Texvc background color
3808 - * use LaTeX color format as used in \special function
3809 - * for transparent background use value 'Transparent' for alpha transparency or
3810 - * 'transparent' for binary transparency.
3811 - */
3812 -$wgTexvcBackgroundColor = 'transparent';
38133787
3814 -/**
3815 - * Normally when generating math images, we double-check that the
3816 - * directories we want to write to exist, and that files that have
3817 - * been generated still exist when we need to bring them up again.
3818 - *
3819 - * This lets us give useful error messages in case of permission
3820 - * problems, and automatically rebuild images that have been lost.
3821 - *
3822 - * On a big site with heavy NFS traffic this can be slow and flaky,
3823 - * so sometimes we want to short-circuit it by setting this to false.
3824 - */
3825 -$wgMathCheckFiles = true;
3826 -
38273788 /* @} */ # end LaTeX }
38283789
38293790 /************************************************************************//**
Index: trunk/phase3/includes/Preferences.php
@@ -45,7 +45,6 @@
4646 self::profilePreferences( $user, $defaultPreferences );
4747 self::skinPreferences( $user, $defaultPreferences );
4848 self::filesPreferences( $user, $defaultPreferences );
49 - self::mathPreferences( $user, $defaultPreferences );
5049 self::datetimePreferences( $user, $defaultPreferences );
5150 self::renderingPreferences( $user, $defaultPreferences );
5251 self::editingPreferences( $user, $defaultPreferences );
@@ -495,19 +494,6 @@
496495 }
497496 }
498497
499 - static function mathPreferences( $user, &$defaultPreferences ) {
500 - ## Math #####################################
501 - global $wgUseTeX, $wgLang;
502 - if ( $wgUseTeX ) {
503 - $defaultPreferences['math'] = array(
504 - 'type' => 'radio',
505 - 'options' => array_flip( array_map( 'wfMsgHtml', $wgLang->getMathNames() ) ),
506 - 'label' => '&#160;',
507 - 'section' => 'rendering/math',
508 - );
509 - }
510 - }
511 -
512498 static function filesPreferences( $user, &$defaultPreferences ) {
513499 ## Files #####################################
514500 $defaultPreferences['imagesize'] = array(
Index: trunk/phase3/RELEASE-NOTES
@@ -61,6 +61,10 @@
6262 * (bug 17009) the hiddenStructure CSS class, a highly hackish way of at least *appearing*
6363 to hide article elements, has been removed. Use the ParserFunctions extension to
6464 actually remove unwanted elements from the output.
 65+* (bug 14202) $wgUseTeX has been superseded by the Math extension. To re-enable
 66+ math conversion after upgrading, obtain the Math extension from SVN or from
 67+ http://www.mediawiki.org/wiki/Extension:Math and add to LocalSettings.php:
 68+ require_once "$IP/extensions/Math/Math.php";
6569
6670 === New features in 1.18 ===
6771 * Added a special page, disabled by default, that allows users with the
Index: trunk/extensions/Math/Math.php
@@ -0,0 +1,64 @@
 2+<?php
 3+/**
 4+ * MediaWiki math extension
 5+ *
 6+ * (c) 2002-2011 various MediaWiki contributors
 7+ * GPLv2 license; info in main package.
 8+ */
 9+
 10+/** For back-compat */
 11+$wgUseTeX = true;
 12+
 13+/** Location of the texvc binary */
 14+$wgTexvc = dirname( __FILE__ ) . '/math/texvc';
 15+/**
 16+ * Texvc background color
 17+ * use LaTeX color format as used in \special function
 18+ * for transparent background use value 'Transparent' for alpha transparency or
 19+ * 'transparent' for binary transparency.
 20+ */
 21+$wgTexvcBackgroundColor = 'transparent';
 22+
 23+/**
 24+ * Normally when generating math images, we double-check that the
 25+ * directories we want to write to exist, and that files that have
 26+ * been generated still exist when we need to bring them up again.
 27+ *
 28+ * This lets us give useful error messages in case of permission
 29+ * problems, and automatically rebuild images that have been lost.
 30+ *
 31+ * On a big site with heavy NFS traffic this can be slow and flaky,
 32+ * so sometimes we want to short-circuit it by setting this to false.
 33+ */
 34+$wgMathCheckFiles = true;
 35+
 36+
 37+/**
 38+ * The URL path of the math directory. Defaults to "{$wgUploadPath}/math".
 39+ *
 40+ * See http://www.mediawiki.org/wiki/Manual:Enable_TeX for details about how to
 41+ * set up mathematical formula display.
 42+ */
 43+$wgMathPath = false;
 44+
 45+/**
 46+ * The filesystem path of the math directory.
 47+ * Defaults to "{$wgUploadDirectory}/math".
 48+ *
 49+ * See http://www.mediawiki.org/wiki/Manual:Enable_TeX for details about how to
 50+ * set up mathematical formula display.
 51+ */
 52+$wgMathDirectory = false;
 53+
 54+
 55+////////// end of config settings.
 56+
 57+
 58+$wgExtensionFunctions[] = 'MathHooks::setup';
 59+$wgHooks['ParserFirstCallInit'][] = 'MathHooks::onParserFirstCallInit';
 60+$wgHooks['GetPreferences'][] = 'MathHooks::onGetPreferences';
 61+
 62+$wgAutoloadClasses['MathHooks'] = dirname( __FILE__ ) . '/Math.hooks.php';
 63+$wgAutoloadClasses['MathRenderer'] = dirname( __FILE__ ) . '/Math.body.php';
 64+
 65+$wgParserTestFiles[] = dirname( __FILE__ ) . "/mathParserTests.txt";
Index: trunk/extensions/Math/Math.hooks.php
@@ -0,0 +1,44 @@
 2+<?php
 3+/**
 4+ * MediaWiki math extension
 5+ *
 6+ * (c) 2002-2011 various MediaWiki contributors
 7+ * GPLv2 license; info in main package.
 8+ */
 9+
 10+class MathHooks {
 11+ static function setup() {
 12+ global $wgMathPath, $wgMathDirectory;
 13+ global $wgUploadPath, $wgUploadDirectory;
 14+ if ( $wgMathPath === false ) $wgMathPath = "{$wgUploadPath}/math";
 15+ if ( $wgMathDirectory === false ) $wgMathDirectory = "{$wgUploadDirectory}/math";
 16+ }
 17+
 18+ static function onParserFirstCallInit($parser)
 19+ {
 20+ $parser->setHook( 'math', array( 'MathHooks', 'mathTagHook' ) );
 21+ return true;
 22+ }
 23+
 24+ /**
 25+ * @param $content
 26+ * @param $attributes
 27+ * @param $parser Parser
 28+ * @return
 29+ */
 30+ static function mathTagHook( $content, $attributes, $parser ) {
 31+ global $wgContLang;
 32+ return $wgContLang->armourMath( MathRenderer::renderMath( $content, $attributes, $parser->getOptions() ) );
 33+ }
 34+
 35+ static function onGetPreferences( $user, &$defaultPreferences ) {
 36+ global $wgLang;
 37+ $defaultPreferences['math'] = array(
 38+ 'type' => 'radio',
 39+ 'options' => array_flip( array_map( 'wfMsgHtml', $wgLang->getMathNames() ) ),
 40+ 'label' => '&#160;',
 41+ 'section' => 'rendering/math',
 42+ );
 43+ return true;
 44+ }
 45+}
Index: trunk/extensions/Math/mathParserTests.txt
@@ -0,0 +1,41 @@
 2+
 3+!! test
 4+pre-save transform: comment containing math
 5+!! options
 6+pst
 7+!! input
 8+<!-- <math>data</math> -->
 9+!!result
 10+<!-- <math>data</math> -->
 11+!!end
 12+
 13+#!! test
 14+#BUG 1887: A <math> with a thumbnail- we don't render math in the parsertests by default,
 15+#so math is not stripped and turns up as escaped &lt;math&gt; tags.
 16+#!! input
 17+#[[Image:foobar.jpg|thumb|<math>2+2</math>]]
 18+#!! result
 19+#<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="https://www.mediawiki.org/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="https://www.mediawiki.org/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>&lt;math&gt;2+2&lt;/math&gt;</div></div></div>
 20+#
 21+#!! end
 22+
 23+!! test
 24+BUG 1887, part 2: A <math> with a thumbnail- math enabled
 25+!! options
 26+math
 27+!! input
 28+[[Image:foobar.jpg|thumb|<math>2+2</math>]]
 29+!! result
 30+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="https://www.mediawiki.org/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="180" height="20" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="https://www.mediawiki.org/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><span class="texhtml" dir="ltr">2 + 2</span></div></div></div>
 31+
 32+!! end
 33+
 34+#!! test
 35+#Math section safety when disabled
 36+#!! input
 37+#<math><script>alert(document.cookies);</script></math>
 38+#!! result
 39+#<p>&lt;math&gt;&lt;script&gt;alert(document.cookies);&lt;/script&gt;&lt;/math&gt;
 40+#</p>
 41+#!! end
 42+
Index: trunk/extensions/Math/math/texvc_tex.ml
@@ -0,0 +1,3 @@
 2+Texutil.set_encoding (try Sys.argv.(2) with _ -> "UTF-8");
 3+try print_string (Util.mapjoin Texutil.render_tex (Parser.tex_expr Lexer.token (Lexing.from_string Sys.argv.(1))))
 4+with _ -> ()
Property changes on: trunk/extensions/Math/math/texvc_tex.ml
___________________________________________________________________
Added: svn:keywords
15 + Author Date Id Revision
Added: svn:eol-style
26 + native
Index: trunk/extensions/Math/math/tex.mli
@@ -0,0 +1,23 @@
 2+type t =
 3+ TEX_LITERAL of Render_info.t
 4+ | TEX_CURLY of t list
 5+ | TEX_FQ of t * t * t
 6+ | TEX_DQ of t * t
 7+ | TEX_UQ of t * t
 8+ | TEX_FQN of t * t
 9+ | TEX_DQN of t
 10+ | TEX_UQN of t
 11+ | TEX_LR of Render_info.t * Render_info.t * t list
 12+ | TEX_BOX of string * string
 13+ | TEX_BIG of string * Render_info.t
 14+ | TEX_FUN1 of string * t
 15+ | TEX_FUN2 of string * t * t
 16+ | TEX_FUN2nb of string * t * t
 17+ | TEX_INFIX of string * t list * t list
 18+ | TEX_FUN2sq of string * t * t
 19+ | TEX_FUN1hl of string * (string * string) * t
 20+ | TEX_FUN1hf of string * Render_info.font_force * t
 21+ | TEX_FUN2h of string * (t -> t -> string * string * string) * t * t
 22+ | TEX_INFIXh of string * (t list -> t list -> string * string * string) * t list * t list
 23+ | TEX_MATRIX of string * t list list list
 24+ | TEX_DECLh of string * Render_info.font_force * t list
Property changes on: trunk/extensions/Math/math/tex.mli
___________________________________________________________________
Added: svn:keywords
125 + Author Date Id Revision
Added: svn:eol-style
226 + native
Index: trunk/extensions/Math/math/texvc_cgi.ml
@@ -0,0 +1,62 @@
 2+open Netcgi;;
 3+open Netcgi_types;;
 4+open Netcgi_env;;
 5+open Netchannels;;
 6+
 7+let cgi = new Netcgi.std_activation ()
 8+let out = cgi # output # output_string
 9+let math = cgi # argument_value ~default:"" "math"
 10+let tmppath = "/home/taw/public_html/wiki/tmp/"
 11+let finalpath = "/home/taw/public_html/wiki/math/"
 12+let finalurl = "http://wroclaw.taw.pl.eu.org/~taw/wiki/math/"
 13+;;
 14+
 15+let h_header = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\""^
 16+ " \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"^
 17+ "<html><head><title>texvc</title></head><body>"^
 18+ "<form method=post action=\"http://wroclaw.taw.pl.eu.org/~taw/cgi-bin/newcodebase/math/texvc_cgi\">"^
 19+ "<textarea name='math' rows=10 cols=80>"
 20+let h_middle = "</textarea><br /><input type=submit value=\"Preview\" name='preview'></form>"
 21+let h_footer = "</body></html>\n"
 22+
 23+let render tmppath finalpath tree =
 24+ let outtex = Texutil.mapjoin Texutil.print tree in
 25+ let md5 = Digest.to_hex (Digest.string outtex) in
 26+ begin
 27+ out "<h3>TeX</h3>";
 28+ out outtex; (* <, & and > should be protected *)
 29+ (try out ("<h3>HTML</h3>" ^ (Texutil.html_render tree))
 30+ with _ -> out "<h3>HTML could not be rendered</h3>");
 31+ try Render.render tmppath finalpath outtex md5;
 32+ out ("<h3>Image:</h3><img src=\""^finalurl^md5^".png\">")
 33+ with Util.FileAlreadyExists -> out ("<h3>Image:</h3><img src=\""^finalurl^md5^".png\">")
 34+ | Failure s -> out ("<h3>Other failure: " ^ s ^ "</h3>")
 35+ | Render.ExternalCommandFailure "latex" -> out "<h3>latex failed</h3>"
 36+ | Render.ExternalCommandFailure "dvips" -> out "<h3>dvips failed</h3>"
 37+ | _ -> out "<h3>Other failure</h3>"
 38+ end
 39+;;
 40+
 41+cgi#set_header ();;
 42+
 43+out h_header;;
 44+out math;;
 45+out h_middle;;
 46+
 47+exception LexerException of string
 48+let lexer_token_safe lexbuf =
 49+ try Lexer.token lexbuf
 50+ with Failure s -> raise (LexerException s)
 51+;;
 52+if math = ""
 53+then ()
 54+else try
 55+ render tmppath finalpath (Parser.tex_expr lexer_token_safe (Lexing.from_string math))
 56+ with Parsing.Parse_error -> out "<h3>Parse error</h3>"
 57+ | LexerException s -> out "<h3>Lexing failure</h3>"
 58+ | Texutil.Illegal_tex_function s -> out ("<h3>Illegal TeX function: " ^ s ^ "</h3>")
 59+ | Failure s -> out ("<h3>Other failure: " ^ s ^ "</h3>")
 60+ | _ -> out "<h3>Other failure</h3>"
 61+;;
 62+
 63+out h_footer
Property changes on: trunk/extensions/Math/math/texvc_cgi.ml
___________________________________________________________________
Added: svn:keywords
164 + Author Date Id Revision
Added: svn:eol-style
265 + native
Index: trunk/extensions/Math/math/util.ml
@@ -0,0 +1,26 @@
 2+(* vim: set sw=8 ts=8 et: *)
 3+
 4+(* TODO document *)
 5+let mapjoin f l = (List.fold_left (fun a b -> a ^ (f b)) "" l)
 6+
 7+(* TODO document *)
 8+let mapjoine e f = function
 9+ [] -> ""
 10+ | h::t -> (List.fold_left (fun a b -> a ^ e ^ (f b)) (f h) t)
 11+
 12+(* Exception used by open_out_unless_exists below *)
 13+exception FileAlreadyExists
 14+
 15+(* Wrapper which raise an exception when output path already exist *)
 16+let open_out_unless_exists path =
 17+ if Sys.file_exists path
 18+ then raise FileAlreadyExists
 19+ else open_out path
 20+
 21+(* *)
 22+let run_in_other_directory tmppath cmd =
 23+ let prevdir = Sys.getcwd () in(
 24+ Sys.chdir tmppath;
 25+ let retval = Sys.command cmd in
 26+ (Sys.chdir prevdir; retval)
 27+ )
Property changes on: trunk/extensions/Math/math/util.ml
___________________________________________________________________
Added: svn:keywords
128 + Author Date Id Revision
Added: svn:eol-style
229 + native
Index: trunk/extensions/Math/math/html.mli
@@ -0,0 +1,5 @@
 2+val render : Tex.t list -> string option
 3+val html_render : Tex.t list -> string
 4+
 5+type conservativeness_t = CONSERVATIVE | MODERATE | LIBERAL
 6+val conservativeness : conservativeness_t ref
Property changes on: trunk/extensions/Math/math/html.mli
___________________________________________________________________
Added: svn:keywords
17 + Author Date Id Revision
Added: svn:eol-style
28 + native
Index: trunk/extensions/Math/math/render.ml
@@ -0,0 +1,58 @@
 2+(* vim: set sw=8 ts=8 et: *)
 3+
 4+let cmd_dvips tmpprefix = "dvips -q -R -E " ^ tmpprefix ^ ".dvi -f >" ^ tmpprefix ^ ".ps"
 5+let cmd_latex tmpprefix = "latex " ^ tmpprefix ^ ".tex >/dev/null"
 6+
 7+(* Putting -transparent white in converts arguments will sort-of give you transperancy *)
 8+let cmd_convert tmpprefix finalpath = "convert -quality 100 -density 120 " ^ tmpprefix ^ ".ps " ^ finalpath ^ " >/dev/null 2>/dev/null"
 9+
 10+(* Putting -bg Transparent in dvipng's arguments will give full-alpha transparency *)
 11+(* Note that IE have problems with such PNGs and need an additional javascript snippet *)
 12+(* Putting -bg transparent in dvipng's arguments will give binary transparency *)
 13+let cmd_dvipng tmpprefix finalpath backcolor = "dvipng -bg \'" ^ backcolor ^ "\' -gamma 1.5 -D 120 -T tight --strict " ^ tmpprefix ^ ".dvi -o " ^ finalpath ^ " >/dev/null 2>/dev/null"
 14+
 15+exception ExternalCommandFailure of string
 16+
 17+let render tmppath finalpath outtex md5 backcolor =
 18+ let tmpprefix0 = (string_of_int (Unix.getpid ()))^"_"^md5 in
 19+ let tmpprefix = (tmppath^"/"^tmpprefix0) in
 20+ let unlink_all () =
 21+ begin
 22+ (* Commenting this block out will aid in debugging *)
 23+ Sys.remove (tmpprefix ^ ".dvi");
 24+ Sys.remove (tmpprefix ^ ".aux");
 25+ Sys.remove (tmpprefix ^ ".log");
 26+ Sys.remove (tmpprefix ^ ".tex");
 27+ if Sys.file_exists (tmpprefix ^ ".ps")
 28+ then Sys.remove (tmpprefix ^ ".ps");
 29+ end in
 30+
 31+ let f = (Util.open_out_unless_exists (tmpprefix ^ ".tex")) in
 32+ begin
 33+ (* Assemble final output in file 'f' *)
 34+ output_string f (Texutil.get_preface ());
 35+ output_string f outtex;
 36+ output_string f (Texutil.get_footer ());
 37+ close_out f;
 38+
 39+ (* TODO: document *)
 40+ if Util.run_in_other_directory tmppath (cmd_latex tmpprefix0) != 0
 41+ then (
 42+ unlink_all (); raise (ExternalCommandFailure "latex")
 43+ ) else if (Sys.command (cmd_dvipng tmpprefix (finalpath^"/"^md5^".png") backcolor) != 0)
 44+ then (
 45+ if (Sys.command (cmd_dvips tmpprefix) != 0)
 46+ then (
 47+ unlink_all ();
 48+ raise (ExternalCommandFailure "dvips")
 49+ ) else if (Sys.command (cmd_convert tmpprefix (finalpath^"/"^md5^".png")) != 0)
 50+ then (
 51+ unlink_all ();
 52+ raise (ExternalCommandFailure "convert")
 53+ ) else (
 54+ unlink_all ()
 55+ )
 56+ ) else (
 57+ unlink_all ()
 58+ )
 59+ end
Property changes on: trunk/extensions/Math/math/render.ml
___________________________________________________________________
Added: svn:keywords
160 + Author Date Id Revision
Added: svn:eol-style
261 + native
Index: trunk/extensions/Math/math/mathml.ml
@@ -0,0 +1,20 @@
 2+open Tex
 3+open Render_info
 4+
 5+type t = TREE_MN of string | TREE_MO of string | TREE_MI of string
 6+
 7+let rec make_mathml_tree = function
 8+ TREE_MN a::otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MN,b))::itr -> make_mathml_tree(TREE_MN (a^b)::otr,itr)
 9+ | otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MN,a))::itr -> make_mathml_tree(TREE_MN a::otr,itr)
 10+ | otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MO,a))::itr -> make_mathml_tree(TREE_MO a::otr,itr)
 11+ | otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MI,a))::itr -> make_mathml_tree(TREE_MI a::otr,itr)
 12+ | otr,TEX_CURLY(crl)::itr -> make_mathml_tree(otr,crl@itr)
 13+ | otr,[] -> List.rev otr
 14+ | _ -> failwith "failed to render mathml"
 15+
 16+let render_mathml_tree = function
 17+ TREE_MN s -> "<mn>"^s^"</mn>"
 18+ | TREE_MI s -> "<mi>"^s^"</mi>"
 19+ | TREE_MO s -> "<mo>"^s^"</mo>"
 20+
 21+let render tree = try Some (Util.mapjoin render_mathml_tree (make_mathml_tree ([],tree))) with _ -> None
Property changes on: trunk/extensions/Math/math/mathml.ml
___________________________________________________________________
Added: svn:keywords
122 + Author Date Id Revision
Added: svn:eol-style
223 + native
Index: trunk/extensions/Math/math/parser.mly
@@ -0,0 +1,118 @@
 2+%{
 3+ open Tex
 4+ open Render_info
 5+
 6+ let sq_close_ri = HTMLABLEC(FONT_UFH,"]", "]")
 7+%}
 8+%token <Render_info.t> LITERAL DELIMITER
 9+%token <string> FUN_AR2 FUN_INFIX FUN_AR1 DECL FUN_AR1opt BIG FUN_AR2nb
 10+%token <string*string> BOX
 11+%token <string*(string*string)> FUN_AR1hl
 12+%token <string*Render_info.font_force> FUN_AR1hf DECLh
 13+%token <string*(Tex.t->Tex.t->string*string*string)> FUN_AR2h
 14+%token <string*(Tex.t list->Tex.t list->string*string*string)> FUN_INFIXh
 15+%token EOF CURLY_OPEN CURLY_CLOSE SUB SUP SQ_CLOSE NEXT_CELL NEXT_ROW
 16+%token BEGIN__MATRIX BEGIN_PMATRIX BEGIN_BMATRIX BEGIN_BBMATRIX BEGIN_VMATRIX BEGIN_VVMATRIX BEGIN_CASES BEGIN_ARRAY BEGIN_ALIGN BEGIN_ALIGNAT BEGIN_SMALLMATRIX
 17+%token END__MATRIX END_PMATRIX END_BMATRIX END_BBMATRIX END_VMATRIX END_VVMATRIX END_CASES END_ARRAY END_ALIGN END_ALIGNAT END_SMALLMATRIX
 18+%token LEFT RIGHT
 19+%type <Tex.t list> tex_expr
 20+%start tex_expr
 21+
 22+%%
 23+tex_expr:
 24+ expr EOF { $1 }
 25+ | ne_expr FUN_INFIX ne_expr EOF
 26+ { [TEX_INFIX($2,$1,$3)] }
 27+ | ne_expr FUN_INFIXh ne_expr EOF
 28+ { let t,h=$2 in [TEX_INFIXh(t,h,$1,$3)] }
 29+expr:
 30+ /* */ { [] }
 31+ | ne_expr { $1 }
 32+ne_expr:
 33+ lit_aq expr { $1 :: $2 }
 34+ | litsq_aq expr { $1 :: $2 }
 35+ | DECLh expr { let t,h = $1 in [TEX_DECLh(t,h,$2)] }
 36+litsq_aq:
 37+ litsq_zq { $1 }
 38+ | litsq_dq { let base,downi = $1 in TEX_DQ(base,downi) }
 39+ | litsq_uq { let base,upi = $1 in TEX_UQ(base,upi)}
 40+ | litsq_fq { $1 }
 41+litsq_fq:
 42+ litsq_dq SUP lit { let base,downi = $1 in TEX_FQ(base,downi,$3) }
 43+ | litsq_uq SUB lit { let base,upi = $1 in TEX_FQ(base,$3,upi) }
 44+litsq_uq:
 45+ litsq_zq SUP lit { $1,$3 }
 46+litsq_dq:
 47+ litsq_zq SUB lit { $1,$3 }
 48+litsq_zq:
 49+ | SQ_CLOSE { TEX_LITERAL sq_close_ri }
 50+expr_nosqc:
 51+ /* */ { [] }
 52+ | lit_aq expr_nosqc { $1 :: $2 }
 53+lit_aq:
 54+ lit { $1 }
 55+ | lit_dq { let base,downi = $1 in TEX_DQ(base,downi) }
 56+ | lit_uq { let base,upi = $1 in TEX_UQ(base,upi)}
 57+ | lit_dqn { TEX_DQN($1) }
 58+ | lit_uqn { TEX_UQN($1) }
 59+ | lit_fq { $1 }
 60+
 61+lit_fq:
 62+ lit_dq SUP lit { let base,downi = $1 in TEX_FQ(base,downi,$3) }
 63+ | lit_uq SUB lit { let base,upi = $1 in TEX_FQ(base,$3,upi) }
 64+ | lit_dqn SUP lit { TEX_FQN($1, $3) }
 65+
 66+lit_uq:
 67+ lit SUP lit { $1,$3 }
 68+lit_dq:
 69+ lit SUB lit { $1,$3 }
 70+lit_uqn:
 71+ SUP lit { $2 }
 72+lit_dqn:
 73+ SUB lit { $2 }
 74+
 75+
 76+left:
 77+ LEFT DELIMITER { $2 }
 78+ | LEFT SQ_CLOSE { sq_close_ri }
 79+right:
 80+ RIGHT DELIMITER { $2 }
 81+ | RIGHT SQ_CLOSE { sq_close_ri }
 82+lit:
 83+ LITERAL { TEX_LITERAL $1 }
 84+ | DELIMITER { TEX_LITERAL $1 }
 85+ | BIG DELIMITER { TEX_BIG ($1,$2) }
 86+ | BIG SQ_CLOSE { TEX_BIG ($1,sq_close_ri) }
 87+ | left expr right { TEX_LR ($1,$3,$2) }
 88+ | FUN_AR1 lit { TEX_FUN1($1,$2) }
 89+ | FUN_AR1hl lit { let t,h=$1 in TEX_FUN1hl(t,h,$2) }
 90+ | FUN_AR1hf lit { let t,h=$1 in TEX_FUN1hf(t,h,$2) }
 91+ | FUN_AR1opt expr_nosqc SQ_CLOSE lit { TEX_FUN2sq($1,TEX_CURLY $2,$4) }
 92+ | FUN_AR2 lit lit { TEX_FUN2($1,$2,$3) }
 93+ | FUN_AR2nb lit lit { TEX_FUN2nb($1,$2,$3) }
 94+ | FUN_AR2h lit lit { let t,h=$1 in TEX_FUN2h(t,h,$2,$3) }
 95+ | BOX { let bt,s = $1 in TEX_BOX (bt,s) }
 96+ | CURLY_OPEN expr CURLY_CLOSE
 97+ { TEX_CURLY $2 }
 98+ | CURLY_OPEN ne_expr FUN_INFIX ne_expr CURLY_CLOSE
 99+ { TEX_INFIX($3,$2,$4) }
 100+ | CURLY_OPEN ne_expr FUN_INFIXh ne_expr CURLY_CLOSE
 101+ { let t,h=$3 in TEX_INFIXh(t,h,$2,$4) }
 102+ | BEGIN__MATRIX matrix END__MATRIX { TEX_MATRIX ("matrix", $2) }
 103+ | BEGIN_PMATRIX matrix END_PMATRIX { TEX_MATRIX ("pmatrix", $2) }
 104+ | BEGIN_BMATRIX matrix END_BMATRIX { TEX_MATRIX ("bmatrix", $2) }
 105+ | BEGIN_BBMATRIX matrix END_BBMATRIX { TEX_MATRIX ("Bmatrix", $2) }
 106+ | BEGIN_VMATRIX matrix END_VMATRIX { TEX_MATRIX ("vmatrix", $2) }
 107+ | BEGIN_VVMATRIX matrix END_VVMATRIX { TEX_MATRIX ("Vmatrix", $2) }
 108+ | BEGIN_ARRAY matrix END_ARRAY { TEX_MATRIX ("array", $2) }
 109+ | BEGIN_ALIGN matrix END_ALIGN { TEX_MATRIX ("aligned", $2) }
 110+ | BEGIN_ALIGNAT matrix END_ALIGNAT { TEX_MATRIX ("alignedat", $2) }
 111+ | BEGIN_SMALLMATRIX matrix END_SMALLMATRIX { TEX_MATRIX ("smallmatrix", $2) }
 112+ | BEGIN_CASES matrix END_CASES { TEX_MATRIX ("cases", $2) }
 113+matrix:
 114+ line { [$1] }
 115+ | line NEXT_ROW matrix { $1::$3 }
 116+line:
 117+ expr { [$1] }
 118+ | expr NEXT_CELL line { $1::$3 }
 119+;;
Property changes on: trunk/extensions/Math/math/parser.mly
___________________________________________________________________
Added: svn:keywords
1120 + Author Date Id Revision
Added: svn:eol-style
2121 + native
Index: trunk/extensions/Math/math/README
@@ -0,0 +1,119 @@
 2+== About texvc ==
 3+
 4+texvc takes LaTeX-compatible equations and produces formatted output in HTML,
 5+MathML, and (via LaTeX/dvipng) rasterized PNG images.
 6+Input data is parsed and scrutinized for safety, and the output includes an
 7+estimate of whether the code is simple enough that HTML rendering will look
 8+acceptable.
 9+
 10+The program was written by Tomasz Wegrzanowski for use with MediaWiki; it's
 11+included as part of the MediaWiki package (http://www.mediawiki.org) and is
 12+under the GPL license.
 13+
 14+Please report bugs at: https://bugzilla.wikimedia.org/
 15+with "MediaWiki extensions" as product and "texvc" as component.
 16+
 17+== Setup ==
 18+
 19+=== Requirements ===
 20+
 21+OCaml 3.06 or later is required to compile texvc; this can be acquired from
 22+http://caml.inria.fr/ if your system doesn't have it available.
 23+
 24+The makefile requires GNU make.
 25+
 26+Rasterization is done via LaTeX, dvipng. These need to be installed and in
 27+the PATH: latex, dvipng
 28+
 29+AMS* packages for LaTeX also need to be installed. Without AMS* some equations
 30+will render correctly while others won't render. Most distributions of TeX
 31+already contain AMS*. In Debian/Ubuntu you need to install tetex-extra.
 32+
 33+To work properly with rendering non-ASCII Unicode characters, a supplemental TeX
 34+package is needed (cjk-latex in Debian)
 35+
 36+=== Installation ===
 37+
 38+Run 'make' (or 'gmake' if GNU make is not your default make). This should
 39+produce the texvc executable.
 40+
 41+Then you'll need to set $wgUseTeX to true in your LocalSettings.php. By default,
 42+MediaWiki will search in this directory for texvc, if you moved it elsewhere,
 43+you'll have to modify $wgTexvc and set it to the path of the texvc executable.
 44+
 45+== Usage ==
 46+
 47+Normally texvc is called from MediaWiki's Math.php modules and everything
 48+Just Works. It can be run manually for testing or for use in another app.
 49+
 50+=== Command-line parameters ===
 51+
 52+ texvc <temp directory> <output directory> <TeX code> <encoding> <color>
 53+
 54+Be sure to properly quote the TeX code!
 55+
 56+Example:
 57+
 58+ texvc /home/wiki/tmp /home/wiki/math "y=x+2" iso-8859-1 "rgb 1.0 1.0 1.0"
 59+
 60+=== Output format ===
 61+
 62+Status codes and HTML/MathML transformations are returned on stdout.
 63+A rasterized PNG file will be written to the output directory, named
 64+for the MD5 hash code.
 65+
 66+texvc output format is like this:
 67+ +%5 ok, but not html or mathml
 68+ c%5%h ok, conservative html, no mathml
 69+ m%5%h ok, moderate html, no mathml
 70+ l%5%h ok, liberal html, no mathml
 71+ C%5%h\0%m ok, conservative html, with mathml
 72+ M%5%h\0%m ok, moderate html, with mathml
 73+ L%5%h\0%m ok, liberal html, with mathml
 74+ X%5%m ok, no html, with mathml
 75+ S syntax error
 76+ E lexing error
 77+ F%s unknown function %s
 78+ - other error
 79+
 80+ \0 - null character
 81+ %5 - md5, 32 hex characters
 82+ %h - html code, without \0 characters
 83+ %m - mathml code, without \0 characters
 84+
 85+
 86+== Troubleshooting ==
 87+
 88+Unfortunately, many error conditions with rasterization are not well reported.
 89+texvc will return as though everything is successful, and the only obvious
 90+sign of problems for the user is a big X on a wiki page where an equation
 91+should be.
 92+
 93+Try running texvc from the command line to ensure that the software it relies
 94+upon is all set up.
 95+
 96+Ensure that the temporary and math directories exist and can be written to by
 97+the user account the web server runs under; if you don't control the server,
 98+you may have to make them world-writable.
 99+
 100+If some equations render correctly while others don't, you probably don't have
 101+AMS* packages for LaTeX installed. Most distributions of TeX come with AMS*.
 102+In Debian/Ubuntu AMS* is in tetex-extra package.
 103+To check if that is the problem you can try those two equations:
 104+ x + y
 105+ x \implies y
 106+The first uses only standard LaTeX, while the second uses symbol \implies from AMS*.
 107+If the first renders, but the second doesn't, you need to install AMS*.
 108+
 109+== Hacking ==
 110+
 111+Before you start hacking on the math package its good to know the workflow,
 112+which is basically:
 113+
 114+1. texvc gets called by Math/Math.body.php (check out the line begining with "$cmd")
 115+2. texvc does its magic, which is basically to check for invalid latex code.
 116+3. texvc takes the user input if valid and creates a latex file containing it, see
 117+ get_preface in texutil.ml
 118+4. dvipng(1) gets called to create a .png file
 119+ See render.ml for this process (commenting out the removal of
 120+ the temporary file is useful for debugging).
Property changes on: trunk/extensions/Math/math/README
___________________________________________________________________
Added: svn:keywords
1121 + Author Date Id Revision
Added: svn:eol-style
2122 + native
Index: trunk/extensions/Math/math/texvc_test.ml
@@ -0,0 +1,24 @@
 2+exception LexerException of string
 3+let lexer_token_safe lexbuf =
 4+ try Lexer.token lexbuf
 5+ with Failure s -> raise (LexerException s)
 6+
 7+let rec foo () =
 8+ try
 9+ let line = input_line stdin in
 10+ (try
 11+ let tree = Parser.tex_expr lexer_token_safe (Lexing.from_string line) in
 12+ (match Html.render tree with
 13+ Some _ -> print_string "$^\n"
 14+ | None -> print_string "$_\n";
 15+ )
 16+ with
 17+ Texutil.Illegal_tex_function s -> print_string ("$T" ^ s ^ " " ^ line ^ "\n")
 18+ | LexerException s -> print_string ("$L" ^ line ^ "\n")
 19+ | _ -> print_string ("$ " ^ line ^ "\n"));
 20+ flush stdout;
 21+ foo ();
 22+ with
 23+ End_of_file -> ()
 24+;;
 25+foo ();;
Property changes on: trunk/extensions/Math/math/texvc_test.ml
___________________________________________________________________
Added: svn:keywords
126 + Author Date Id Revision
Added: svn:eol-style
227 + native
Index: trunk/extensions/Math/math/texvc.ml
@@ -0,0 +1,58 @@
 2+(* vim: set sw=8 ts=8 et: *)
 3+exception LexerException of string
 4+
 5+(* *)
 6+let lexer_token_safe lexbuf =
 7+ try Lexer.token lexbuf
 8+ with Failure s -> raise (LexerException s)
 9+
 10+(* *)
 11+let render tmppath finalpath tree backcolor =
 12+ let outtex = Util.mapjoin Texutil.render_tex tree in
 13+ let md5 = Digest.to_hex (Digest.string outtex) in
 14+ begin
 15+ let mathml = Mathml.render tree
 16+ and html = Html.render tree
 17+ in print_string (match (html,!Html.conservativeness,mathml) with
 18+ None,_,None -> "+" ^ md5
 19+ | Some h,Html.CONSERVATIVE,None -> "c" ^ md5 ^ h
 20+ | Some h,Html.MODERATE,None -> "m" ^ md5 ^ h
 21+ | Some h,Html.LIBERAL,None -> "l" ^ md5 ^ h
 22+ | Some h,Html.CONSERVATIVE,Some m -> "C" ^ md5 ^ h ^ "\000" ^ m
 23+ | Some h,Html.MODERATE,Some m -> "M" ^ md5 ^ h ^ "\000" ^ m
 24+ | Some h,Html.LIBERAL,Some m -> "L" ^ md5 ^ h ^ "\000" ^ m
 25+ | None,_,Some m -> "X" ^ md5 ^ m
 26+ );
 27+ Render.render tmppath finalpath outtex md5 backcolor
 28+ end
 29+
 30+(* TODO: document
 31+ * Arguments:
 32+ * 1st :
 33+ * 2nd :
 34+ * 3rd :
 35+ * 4th : encoding (Default: UTF-8)
 36+ * 5th : color (Default: rgb 1.0 1.0 1.0)
 37+ *
 38+ * Output one character:
 39+ * S : Parsing error
 40+ * E : Lexer exception raised
 41+ * F : TeX function not recognized
 42+ * - : Generic/Default failure code. Might be an invalid argument,
 43+ * output file already exist, a problem with an external
 44+ * command ...
 45+ * *)
 46+let _ =
 47+ Texutil.set_encoding (try Sys.argv.(4) with _ -> "UTF-8");
 48+ try render Sys.argv.(1) Sys.argv.(2) (
 49+ Parser.tex_expr lexer_token_safe (
 50+ Lexing.from_string Sys.argv.(3))
 51+ ) (try Sys.argv.(5) with _ -> "rgb 1.0 1.0 1.0")
 52+ with Parsing.Parse_error -> print_string "S"
 53+ | LexerException _ -> print_string "E"
 54+ | Texutil.Illegal_tex_function s -> print_string ("F" ^ s)
 55+ | Util.FileAlreadyExists -> print_string "-"
 56+ | Invalid_argument _ -> print_string "-"
 57+ | Failure _ -> print_string "-"
 58+ | Render.ExternalCommandFailure s -> ()
 59+ | _ -> print_string "-"
Property changes on: trunk/extensions/Math/math/texvc.ml
___________________________________________________________________
Added: svn:keywords
160 + Author Date Id Revision
Added: svn:eol-style
261 + native
Index: trunk/extensions/Math/math/lexer.mll
@@ -0,0 +1,108 @@
 2+{
 3+ open Parser
 4+ open Render_info
 5+ open Tex
 6+}
 7+let space = [' ' '\t' '\n' '\r']
 8+let alpha = ['a'-'z' 'A'-'Z']
 9+let literal_id = ['a'-'z' 'A'-'Z']
 10+let literal_mn = ['0'-'9']
 11+let literal_uf_lt = [',' ':' ';' '?' '!' '\'']
 12+let delimiter_uf_lt = ['(' ')' '.']
 13+let literal_uf_op = ['+' '-' '*' '=']
 14+let delimiter_uf_op = ['/' '|']
 15+let boxchars = ['0'-'9' 'a'-'z' 'A'-'Z' '+' '-' '*' ',' '=' '(' ')' ':' '/' ';' '?' '.' '!' ' ' '\128'-'\255']
 16+let aboxchars = ['0'-'9' 'a'-'z' 'A'-'Z' '+' '-' '*' ',' '=' '(' ')' ':' '/' ';' '?' '.' '!' ' ']
 17+
 18+rule token = parse
 19+ space + { token lexbuf }
 20+ | "\\text" space * '{' boxchars + '}'
 21+ { Texutil.tex_use_ams (); let str = Lexing.lexeme lexbuf in
 22+ let n = String.index str '{' + 1 in
 23+ BOX ("\\text", String.sub str n (String.length str - n - 1)) }
 24+ | "\\mbox" space * '{' aboxchars + '}'
 25+ { let str = Lexing.lexeme lexbuf in
 26+ let n = String.index str '{' + 1 in
 27+ BOX ("\\mbox", String.sub str n (String.length str - n - 1)) }
 28+ | "\\hbox" space * '{' aboxchars + '}'
 29+ { let str = Lexing.lexeme lexbuf in
 30+ let n = String.index str '{' + 1 in
 31+ BOX ("\\hbox", String.sub str n (String.length str - n - 1)) }
 32+ | "\\vbox" space * '{' aboxchars + '}'
 33+ { let str = Lexing.lexeme lexbuf in
 34+ let n = String.index str '{' + 1 in
 35+ BOX ("\\vbox", String.sub str n (String.length str - n - 1)) }
 36+ | "\\mbox" space * '{' boxchars + '}'
 37+ { let str = Lexing.lexeme lexbuf in
 38+ let n = String.index str '{' + 1 in
 39+ Texutil.tex_use_nonascii();
 40+ BOX ("\\mbox", String.sub str n (String.length str - n - 1)) }
 41+ | "\\hbox" space * '{' boxchars + '}'
 42+ { let str = Lexing.lexeme lexbuf in
 43+ let n = String.index str '{' + 1 in
 44+ Texutil.tex_use_nonascii();
 45+ BOX ("\\hbox", String.sub str n (String.length str - n - 1)) }
 46+ | "\\vbox" space * '{' boxchars + '}'
 47+ { let str = Lexing.lexeme lexbuf in
 48+ let n = String.index str '{' + 1 in
 49+ Texutil.tex_use_nonascii();
 50+ BOX ("\\vbox", String.sub str n (String.length str - n - 1)) }
 51+ | literal_id { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_IT, str,str,MI,str)) }
 52+ | literal_mn { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_RM, str,str,MN,str)) }
 53+ | literal_uf_lt { let str = Lexing.lexeme lexbuf in LITERAL (HTMLABLEC (FONT_UFH, str,str)) }
 54+ | delimiter_uf_lt { let str = Lexing.lexeme lexbuf in DELIMITER (HTMLABLEC (FONT_UFH, str,str)) }
 55+ | "-" { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_UFH,"-"," &minus; ",MO,str))}
 56+ | literal_uf_op { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_UFH, str," "^str^" ",MO,str)) }
 57+ | delimiter_uf_op { let str = Lexing.lexeme lexbuf in DELIMITER (MHTMLABLEC (FONT_UFH, str," "^str^" ",MO,str)) }
 58+ | "\\" alpha + { Texutil.find (Lexing.lexeme lexbuf) }
 59+ | "\\sqrt" space * "[" { FUN_AR1opt "\\sqrt" }
 60+ | "\\xleftarrow" space * "[" { Texutil.tex_use_ams(); FUN_AR1opt "\\xleftarrow" }
 61+ | "\\xrightarrow" space * "[" { Texutil.tex_use_ams(); FUN_AR1opt "\\xrightarrow" }
 62+ | "\\," { LITERAL (HTMLABLE (FONT_UF, "\\,","&nbsp;")) }
 63+ | "\\ " { LITERAL (HTMLABLE (FONT_UF, "\\ ","&nbsp;")) }
 64+ | "\\;" { LITERAL (HTMLABLE (FONT_UF, "\\;","&nbsp;")) }
 65+ | "\\!" { LITERAL (TEX_ONLY "\\!") }
 66+ | "\\{" { DELIMITER (HTMLABLEC(FONT_UFH,"\\{","{")) }
 67+ | "\\}" { DELIMITER (HTMLABLEC(FONT_UFH,"\\}","}")) }
 68+ | "\\|" { DELIMITER (HTMLABLE (FONT_UFH,"\\|","||")) }
 69+ | "\\_" { LITERAL (HTMLABLEC(FONT_UFH,"\\_","_")) }
 70+ | "\\#" { LITERAL (HTMLABLE (FONT_UFH,"\\#","#")) }
 71+ | "\\%" { LITERAL (HTMLABLE (FONT_UFH,"\\%","%")) }
 72+ | "\\$" { LITERAL (HTMLABLE (FONT_UFH,"\\$","$")) }
 73+ | "\\&" { LITERAL (HTMLABLEC (FONT_RM,"\\&","&amp;")) }
 74+ | "&" { NEXT_CELL }
 75+ | "\\\\" { NEXT_ROW }
 76+ | "\\begin{matrix}" { Texutil.tex_use_ams(); BEGIN__MATRIX }
 77+ | "\\end{matrix}" { END__MATRIX }
 78+ | "\\begin{pmatrix}" { Texutil.tex_use_ams(); BEGIN_PMATRIX }
 79+ | "\\end{pmatrix}" { END_PMATRIX }
 80+ | "\\begin{bmatrix}" { Texutil.tex_use_ams(); BEGIN_BMATRIX }
 81+ | "\\end{bmatrix}" { END_BMATRIX }
 82+ | "\\begin{Bmatrix}" { Texutil.tex_use_ams(); BEGIN_BBMATRIX }
 83+ | "\\end{Bmatrix}" { END_BBMATRIX }
 84+ | "\\begin{vmatrix}" { Texutil.tex_use_ams(); BEGIN_VMATRIX }
 85+ | "\\end{vmatrix}" { END_VMATRIX }
 86+ | "\\begin{Vmatrix}" { Texutil.tex_use_ams(); BEGIN_VVMATRIX }
 87+ | "\\end{Vmatrix}" { END_VVMATRIX }
 88+ | "\\begin{array}" { Texutil.tex_use_ams(); BEGIN_ARRAY }
 89+ | "\\end{array}" { END_ARRAY }
 90+ | "\\begin{align}" { Texutil.tex_use_ams(); BEGIN_ALIGN }
 91+ | "\\end{align}" { END_ALIGN }
 92+ | "\\begin{alignat}" { Texutil.tex_use_ams(); BEGIN_ALIGNAT }
 93+ | "\\end{alignat}" { END_ALIGNAT }
 94+ | "\\begin{smallmatrix}" { Texutil.tex_use_ams(); BEGIN_SMALLMATRIX }
 95+ | "\\end{smallmatrix}" { END_SMALLMATRIX }
 96+ | "\\begin{cases}" { Texutil.tex_use_ams(); BEGIN_CASES }
 97+ | "\\end{cases}" { END_CASES }
 98+ | '>' { LITERAL (HTMLABLEC(FONT_UFH,">"," &gt; ")) }
 99+ | '<' { LITERAL (HTMLABLEC(FONT_UFH,"<"," &lt; ")) }
 100+ | '%' { LITERAL (HTMLABLEC(FONT_UFH,"\\%","%")) }
 101+ | '$' { LITERAL (HTMLABLEC(FONT_UFH,"\\$","$")) }
 102+ | '~' { LITERAL (HTMLABLE (FONT_UF, "~","&nbsp;")) }
 103+ | '[' { DELIMITER (HTMLABLEC(FONT_UFH,"[","[")) }
 104+ | ']' { SQ_CLOSE }
 105+ | '{' { CURLY_OPEN }
 106+ | '}' { CURLY_CLOSE }
 107+ | '^' { SUP }
 108+ | '_' { SUB }
 109+ | eof { EOF }
Property changes on: trunk/extensions/Math/math/lexer.mll
___________________________________________________________________
Added: svn:keywords
1110 + Author Date Id Revision
Added: svn:eol-style
2111 + native
Index: trunk/extensions/Math/math/mathml.mli
@@ -0,0 +1 @@
 2+val render : Tex.t list -> string option
Property changes on: trunk/extensions/Math/math/mathml.mli
___________________________________________________________________
Added: svn:keywords
13 + Author Date Id Revision
Added: svn:eol-style
24 + native
Index: trunk/extensions/Math/math/TODO
@@ -0,0 +1,3 @@
 2+* It would be better if PNGs were transparent
 3+* CJK support
 4+* Documentation, in particular about instalation of Latex support for Unicode
Property changes on: trunk/extensions/Math/math/TODO
___________________________________________________________________
Added: svn:keywords
15 + Author Date Id Revision
Added: svn:eol-style
26 + native
Index: trunk/extensions/Math/math/texutil.ml
@@ -0,0 +1,760 @@
 2+(* vim: set sw=8 ts=8 et: *)
 3+open Parser
 4+open Render_info
 5+open Tex
 6+open Util
 7+
 8+let tex_part = function
 9+ HTMLABLE (_,t,_) -> t
 10+ | HTMLABLEM (_,t,_) -> t
 11+ | HTMLABLEC (_,t,_) -> t
 12+ | MHTMLABLEC (_,t,_,_,_) -> t
 13+ | HTMLABLE_BIG (t,_) -> t
 14+ | TEX_ONLY t -> t
 15+
 16+let rec render_tex = function
 17+ TEX_FQ (a,b,c) -> (render_tex a) ^ "_{" ^ (render_tex b) ^ "}^{" ^ (render_tex c) ^ "}"
 18+ | TEX_DQ (a,b) -> (render_tex a) ^ "_{" ^ (render_tex b) ^ "}"
 19+ | TEX_UQ (a,b) -> (render_tex a) ^ "^{" ^ (render_tex b) ^ "}"
 20+ | TEX_FQN (a,b) -> "_{" ^ (render_tex a) ^ "}^{" ^ (render_tex b) ^ "}"
 21+ | TEX_DQN (a) -> "_{" ^ (render_tex a) ^ "}"
 22+ | TEX_UQN (a) -> "^{" ^ (render_tex a) ^ "}"
 23+ | TEX_LITERAL s -> tex_part s
 24+ | TEX_FUN1 (f,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
 25+ | TEX_FUN1hl (f,_,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
 26+ | TEX_FUN1hf (f,_,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
 27+ | TEX_DECLh (f,_,a) -> "{" ^ f ^ "{" ^ (mapjoin render_tex a) ^ "}}"
 28+ | TEX_FUN2 (f,a,b) -> "{" ^ f ^ " " ^ (render_tex a) ^ (render_tex b) ^ "}"
 29+ | TEX_FUN2nb (f,a,b) -> f ^ (render_tex a) ^ (render_tex b)
 30+ | TEX_FUN2h (f,_,a,b) -> "{" ^ f ^ " " ^ (render_tex a) ^ (render_tex b) ^ "}"
 31+ | TEX_FUN2sq (f,a,b) -> "{" ^ f ^ "[ " ^ (render_tex a) ^ "]" ^ (render_tex b) ^ "}"
 32+ | TEX_CURLY (tl) -> "{" ^ (mapjoin render_tex tl) ^ "}"
 33+ | TEX_INFIX (s,ll,rl) -> "{" ^ (mapjoin render_tex ll) ^ " " ^ s ^ "" ^ (mapjoin render_tex rl) ^ "}"
 34+ | TEX_INFIXh (s,_,ll,rl) -> "{" ^ (mapjoin render_tex ll) ^ " " ^ s ^ "" ^ (mapjoin render_tex rl) ^ "}"
 35+ | TEX_BOX (bt,s) -> "{"^bt^"{" ^ s ^ "}}"
 36+ | TEX_BIG (bt,d) -> "{"^bt^(tex_part d)^"}"
 37+ | TEX_MATRIX (t,rows) -> "{\\begin{"^t^"}"^(mapjoine "\\\\" (mapjoine "&" (mapjoin render_tex)) rows)^"\\end{"^t^"}}"
 38+ | TEX_LR (l,r,tl) -> "\\left "^(tex_part l)^(mapjoin render_tex tl)^"\\right "^(tex_part r)
 39+
 40+
 41+(* Dynamic loading*)
 42+type encoding_t = LATIN1 | LATIN2 | UTF8
 43+
 44+(* module properties *)
 45+let modules_ams = ref false
 46+let modules_nonascii = ref false
 47+let modules_encoding = ref UTF8
 48+let modules_color = ref false
 49+
 50+(* wrappers to easily set / reset module properties *)
 51+let tex_use_ams () = modules_ams := true
 52+let tex_use_nonascii () = modules_nonascii := true
 53+let tex_use_color () = modules_color := true
 54+let tex_mod_reset () = (
 55+ modules_ams := false;
 56+ modules_nonascii := false;
 57+ modules_encoding := UTF8;
 58+ modules_color := false
 59+ )
 60+
 61+(* Return TeX fragment for one of the encodings in (UTF8,LATIN1,LATIN2) *)
 62+let get_encoding = function
 63+ UTF8 -> "\\usepackage{ucs}\n\\usepackage[utf8]{inputenc}\n"
 64+ | LATIN1 -> "\\usepackage[latin1]{inputenc}\n"
 65+ | LATIN2 -> "\\usepackage[latin2]{inputenc}\n"
 66+
 67+(* TeX fragment inserted before the output *)
 68+let get_preface () = "\\nonstopmode\n\\documentclass[12pt]{article}\n" ^
 69+ (if !modules_nonascii then get_encoding !modules_encoding else "") ^
 70+ (if !modules_ams then "\\usepackage{amsmath}\n\\usepackage{amsfonts}\n\\usepackage{amssymb}\n" else "") ^
 71+ (if !modules_color then "\\usepackage[dvips,usenames]{color}\n" else "") ^
 72+ "\\usepackage{cancel}\n\\pagestyle{empty}\n\\begin{document}\n$$\n"
 73+
 74+(* TeX fragment appended after the content *)
 75+let get_footer () = "\n$$\n\\end{document}\n"
 76+
 77+(* Default to UTF8 *)
 78+let set_encoding = function
 79+ "ISO-8859-1" -> modules_encoding := LATIN1
 80+ | "iso-8859-1" -> modules_encoding := LATIN1
 81+ | "ISO-8859-2" -> modules_encoding := LATIN2
 82+ | _ -> modules_encoding := UTF8
 83+
 84+(* Turn that into hash table lookup *)
 85+exception Illegal_tex_function of string
 86+
 87+let find = function
 88+ "\\alpha" -> LITERAL (HTMLABLEC (FONT_UF, "\\alpha ", "&alpha;"))
 89+ | "\\Alpha" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 90+ "\\mathrm{A}", "&Alpha;")))
 91+ | "\\beta" -> LITERAL (HTMLABLEC (FONT_UF, "\\beta ", "&beta;"))
 92+ | "\\Beta" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 93+ "\\mathrm{B}", "&Beta;")))
 94+ | "\\gamma" -> LITERAL (HTMLABLEC (FONT_UF, "\\gamma ", "&gamma;"))
 95+ | "\\Gamma" -> LITERAL (HTMLABLEC (FONT_UF, "\\Gamma ", "&Gamma;"))
 96+ | "\\delta" -> LITERAL (HTMLABLEC (FONT_UF, "\\delta ", "&delta;"))
 97+ | "\\Delta" -> LITERAL (HTMLABLEC (FONT_UF, "\\Delta ", "&Delta;"))
 98+ | "\\epsilon" -> LITERAL (TEX_ONLY "\\epsilon ")
 99+ | "\\Epsilon" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 100+ "\\mathrm{E}", "&Epsilon;")))
 101+ | "\\varepsilon" -> LITERAL (TEX_ONLY "\\varepsilon ")
 102+ | "\\zeta" -> LITERAL (HTMLABLEC (FONT_UF, "\\zeta ", "&zeta;"))
 103+ | "\\Zeta" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 104+ "\\mathrm{Z}", "&Zeta;")))
 105+ | "\\eta" -> LITERAL (HTMLABLEC (FONT_UF, "\\eta ", "&eta;"))
 106+ | "\\Eta" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 107+ "\\mathrm{H}", "&Eta;")))
 108+ | "\\theta" -> LITERAL (HTMLABLEC (FONT_UF, "\\theta ", "&theta;"))
 109+ | "\\Theta" -> LITERAL (HTMLABLEC (FONT_UF, "\\Theta ", "&Theta;"))
 110+ | "\\vartheta" -> LITERAL (HTMLABLE (FONT_UF, "\\vartheta ", "&thetasym;"))
 111+ | "\\thetasym" -> LITERAL (HTMLABLE (FONT_UF, "\\vartheta ", "&thetasym;"))
 112+ | "\\iota" -> LITERAL (HTMLABLEC (FONT_UF, "\\iota ", "&iota;"))
 113+ | "\\Iota" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 114+ "\\mathrm{I}", "&Iota;")))
 115+ | "\\kappa" -> LITERAL (HTMLABLEC (FONT_UF, "\\kappa ", "&kappa;"))
 116+ | "\\Kappa" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 117+ "\\mathrm{K}", "&Kappa;")))
 118+ | "\\lambda" -> LITERAL (HTMLABLEC (FONT_UF, "\\lambda ", "&lambda;"))
 119+ | "\\Lambda" -> LITERAL (HTMLABLEC (FONT_UF, "\\Lambda ", "&Lambda;"))
 120+ | "\\mu" -> LITERAL (HTMLABLEC (FONT_UF, "\\mu ", "&mu;"))
 121+ | "\\Mu" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 122+ "\\mathrm{M}", "&Mu;")))
 123+ | "\\nu" -> LITERAL (HTMLABLEC (FONT_UF, "\\nu ", "&nu;"))
 124+ | "\\Nu" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 125+ "\\mathrm{N}", "&Nu;")))
 126+ | "\\omicron" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 127+ "\\mathrm{o}", "&omicron;")))
 128+ | "\\Omicron" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 129+ "\\mathrm{O}", "&Omicron;")))
 130+ | "\\pi" -> LITERAL (HTMLABLEC (FONT_UF, "\\pi ", "&pi;"))
 131+ | "\\Pi" -> LITERAL (HTMLABLEC (FONT_UF, "\\Pi ", "&Pi;"))
 132+ | "\\varpi" -> LITERAL (TEX_ONLY "\\varpi ")
 133+ | "\\rho" -> LITERAL (HTMLABLEC (FONT_UF, "\\rho ", "&rho;"))
 134+ | "\\Rho" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 135+ "\\mathrm{P}", "&Rho;")))
 136+ | "\\varrho" -> LITERAL (TEX_ONLY "\\varrho ")
 137+ | "\\sim" -> LITERAL (HTMLABLEC (FONT_UF, "\\sim ", "&sim;"))
 138+ | "\\sigma" -> LITERAL (HTMLABLEC (FONT_UF, "\\sigma ", "&sigma;"))
 139+ | "\\Sigma" -> LITERAL (HTMLABLEC (FONT_UF, "\\Sigma ", "&Sigma;"))
 140+ | "\\varsigma" -> LITERAL (TEX_ONLY "\\varsigma ")
 141+ | "\\tau" -> LITERAL (HTMLABLEC (FONT_UF, "\\tau ", "&tau;"))
 142+ | "\\Tau" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 143+ "\\mathrm{T}", "&Tau;")))
 144+ | "\\upsilon" -> LITERAL (HTMLABLEC (FONT_UF, "\\upsilon ", "&upsilon;"))
 145+ | "\\Upsilon" -> LITERAL (HTMLABLEC (FONT_UF, "\\Upsilon ", "&Upsilon;"))
 146+ | "\\phi" -> LITERAL (TEX_ONLY "\\phi ")
 147+ | "\\Phi" -> LITERAL (HTMLABLEC (FONT_UF, "\\Phi ", "&Phi;"))
 148+ | "\\varphi" -> LITERAL (TEX_ONLY "\\varphi ")
 149+ | "\\chi" -> LITERAL (HTMLABLEC (FONT_UF, "\\chi ", "&chi;"))
 150+ | "\\Chi" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
 151+ "\\mathrm{X}", "&Chi;")))
 152+ | "\\psi" -> LITERAL (HTMLABLEC (FONT_UF, "\\psi ", "&psi;"))
 153+ | "\\Psi" -> LITERAL (HTMLABLEC (FONT_UF, "\\Psi ", "&Psi;"))
 154+ | "\\omega" -> LITERAL (HTMLABLEC (FONT_UF, "\\omega ", "&omega;"))
 155+ | "\\Omega" -> LITERAL (HTMLABLEC (FONT_UF, "\\Omega ", "&Omega;"))
 156+ | "\\xi" -> LITERAL (HTMLABLEC (FONT_UF, "\\xi ", "&xi;"))
 157+ | "\\Xi" -> LITERAL (HTMLABLEC (FONT_UF, "\\Xi ", "&Xi;"))
 158+ | "\\aleph" -> LITERAL (HTMLABLE (FONT_UF, "\\aleph ", "&alefsym;"))
 159+ | "\\alef" -> LITERAL (HTMLABLE (FONT_UF, "\\aleph ", "&alefsym;"))
 160+ | "\\alefsym" -> LITERAL (HTMLABLE (FONT_UF, "\\aleph ", "&alefsym;"))
 161+ | "\\larr" -> LITERAL (HTMLABLEM (FONT_UF, "\\leftarrow ", "&larr;"))
 162+ | "\\leftarrow" -> LITERAL (HTMLABLEM (FONT_UF, "\\leftarrow ", "&larr;"))
 163+ | "\\rarr" -> LITERAL (HTMLABLEM (FONT_UF, "\\rightarrow ", "&rarr;"))
 164+ | "\\to" -> LITERAL (HTMLABLEM (FONT_UF, "\\to ", "&rarr;"))
 165+ | "\\gets" -> LITERAL (HTMLABLEM (FONT_UF, "\\gets ", "&larr;"))
 166+ | "\\rightarrow" -> LITERAL (HTMLABLEM (FONT_UF, "\\rightarrow ", "&rarr;"))
 167+ | "\\longleftarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\longleftarrow ", "&larr;"))
 168+ | "\\longrightarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\longrightarrow ", "&rarr;"))
 169+ | "\\Larr" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftarrow ", "&lArr;"))
 170+ | "\\lArr" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftarrow ", "&lArr;"))
 171+ | "\\Leftarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftarrow ", "&lArr;"))
 172+ | "\\Rarr" -> LITERAL (HTMLABLE (FONT_UF, "\\Rightarrow ", "&rArr;"))
 173+ | "\\rArr" -> LITERAL (HTMLABLE (FONT_UF, "\\Rightarrow ", "&rArr;"))
 174+ | "\\Rightarrow" -> LITERAL (HTMLABLEM (FONT_UF, "\\Rightarrow ", "&rArr;"))
 175+ | "\\mapsto" -> LITERAL (HTMLABLE (FONT_UF, "\\mapsto ", "&rarr;"))
 176+ | "\\longmapsto" -> LITERAL (HTMLABLE (FONT_UF, "\\longmapsto ", "&rarr;"))
 177+ | "\\Longleftarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\Longleftarrow ", "&lArr;"))
 178+ | "\\Longrightarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\Longrightarrow ", "&rArr;"))
 179+ | "\\uarr" -> DELIMITER (HTMLABLEM (FONT_UF, "\\uparrow ", "&uarr;"))
 180+ | "\\uparrow" -> DELIMITER (HTMLABLEM (FONT_UF, "\\uparrow ", "&uarr;"))
 181+ | "\\uArr" -> DELIMITER (HTMLABLE (FONT_UF, "\\Uparrow ", "&uArr;"))
 182+ | "\\Uarr" -> DELIMITER (HTMLABLE (FONT_UF, "\\Uparrow ", "&uArr;"))
 183+ | "\\Uparrow" -> DELIMITER (HTMLABLE (FONT_UF, "\\Uparrow ", "&uArr;"))
 184+ | "\\darr" -> DELIMITER (HTMLABLEM (FONT_UF, "\\downarrow ", "&darr;"))
 185+ | "\\downarrow" -> DELIMITER (HTMLABLEM (FONT_UF, "\\downarrow ", "&darr;"))
 186+ | "\\dArr" -> DELIMITER (HTMLABLE (FONT_UF, "\\Downarrow ", "&dArr;"))
 187+ | "\\Darr" -> DELIMITER (HTMLABLE (FONT_UF, "\\Downarrow ", "&dArr;"))
 188+ | "\\Downarrow" -> DELIMITER (HTMLABLE (FONT_UF, "\\Downarrow ", "&dArr;"))
 189+ | "\\updownarrow" -> DELIMITER (TEX_ONLY "\\updownarrow ")
 190+ | "\\Updownarrow" -> DELIMITER (TEX_ONLY "\\Updownarrow ")
 191+ | "\\ulcorner" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\ulcorner "))
 192+ | "\\urcorner" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\urcorner "))
 193+ | "\\llcorner" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\llcorner "))
 194+ | "\\lrcorner" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\lrcorner "))
 195+ | "\\twoheadleftarrow" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\twoheadleftarrow "))
 196+ | "\\twoheadrightarrow" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\twoheadrightarrow "))
 197+ | "\\xleftarrow" -> (tex_use_ams (); FUN_AR1 "\\xleftarrow ")
 198+ | "\\xrightarrow" -> (tex_use_ams (); FUN_AR1 "\\xrightarrow ")
 199+ | "\\rightleftharpoons" -> DELIMITER (TEX_ONLY "\\rightleftharpoons ")
 200+ | "\\leftrightarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\leftrightarrow ", "&harr;"))
 201+ | "\\lrarr" -> LITERAL (HTMLABLE (FONT_UF, "\\leftrightarrow ", "&harr;"))
 202+ | "\\harr" -> LITERAL (HTMLABLE (FONT_UF, "\\leftrightarrow ", "&harr;"))
 203+ | "\\Leftrightarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftrightarrow ", "&hArr;"))
 204+ | "\\Lrarr" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftrightarrow ", "&hArr;"))
 205+ | "\\Harr" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftrightarrow ", "&hArr;"))
 206+ | "\\lrArr" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftrightarrow ", "&hArr;"))
 207+ | "\\hAar" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftrightarrow ", "&hArr;"))
 208+ | "\\longleftrightarrow"->LITERAL (HTMLABLE (FONT_UF, "\\longleftrightarrow ", "&harr;"))
 209+ | "\\Longleftrightarrow"->LITERAL (HTMLABLE (FONT_UF, "\\Longleftrightarrow ", "&harr;"))
 210+ | "\\iff" -> LITERAL (HTMLABLE (FONT_UF, "\\iff ", "&harr;"))
 211+ | "\\ll" -> LITERAL (TEX_ONLY "\\ll ")
 212+ | "\\gg" -> LITERAL (TEX_ONLY "\\gg ")
 213+ | "\\div" -> LITERAL (TEX_ONLY "\\div ")
 214+ | "\\searrow" -> LITERAL (TEX_ONLY "\\searrow ")
 215+ | "\\nearrow" -> LITERAL (TEX_ONLY "\\nearrow ")
 216+ | "\\swarrow" -> LITERAL (TEX_ONLY "\\swarrow ")
 217+ | "\\nwarrow" -> LITERAL (TEX_ONLY "\\nwarrow ")
 218+ | "\\simeq" -> LITERAL (TEX_ONLY "\\simeq ")
 219+ | "\\ast" -> LITERAL (TEX_ONLY "\\ast ")
 220+ | "\\star" -> LITERAL (TEX_ONLY "\\star ")
 221+ | "\\ell" -> LITERAL (TEX_ONLY "\\ell ")
 222+ | "\\P" -> LITERAL (TEX_ONLY "\\P ")
 223+ | "\\smile" -> LITERAL (TEX_ONLY "\\smile ")
 224+ | "\\frown" -> LITERAL (TEX_ONLY "\\frown ")
 225+ | "\\bigcap" -> LITERAL (TEX_ONLY "\\bigcap ")
 226+ | "\\bigodot" -> LITERAL (TEX_ONLY "\\bigodot ")
 227+ | "\\bigcup" -> LITERAL (TEX_ONLY "\\bigcup ")
 228+ | "\\bigotimes" -> LITERAL (TEX_ONLY "\\bigotimes ")
 229+ | "\\coprod" -> LITERAL (TEX_ONLY "\\coprod ")
 230+ | "\\bigsqcup" -> LITERAL (TEX_ONLY "\\bigsqcup ")
 231+ | "\\bigoplus" -> LITERAL (TEX_ONLY "\\bigoplus ")
 232+ | "\\bigvee" -> LITERAL (TEX_ONLY "\\bigvee ")
 233+ | "\\biguplus" -> LITERAL (TEX_ONLY "\\biguplus ")
 234+ | "\\oint" -> LITERAL (TEX_ONLY "\\oint ")
 235+ | "\\bigwedge" -> LITERAL (TEX_ONLY "\\bigwedge ")
 236+ | "\\models" -> LITERAL (TEX_ONLY "\\models ")
 237+ | "\\vdash" -> LITERAL (TEX_ONLY "\\vdash ")
 238+ | "\\triangle" -> LITERAL (TEX_ONLY "\\triangle ")
 239+ | "\\bowtie" -> LITERAL (TEX_ONLY "\\bowtie ")
 240+ | "\\wr" -> LITERAL (TEX_ONLY "\\wr ")
 241+ | "\\triangleleft" -> LITERAL (TEX_ONLY "\\triangleleft ")
 242+ | "\\triangleright" -> LITERAL (TEX_ONLY "\\triangleright ")
 243+ | "\\textvisiblespace" -> LITERAL (TEX_ONLY "\\textvisiblespace ")
 244+ | "\\ker" -> LITERAL (HTMLABLEC(FONT_UFH,"\\ker ","ker"))
 245+ | "\\lim" -> LITERAL (TEX_ONLY "\\lim ")
 246+ | "\\limsup" -> LITERAL (TEX_ONLY "\\limsup ")
 247+ | "\\liminf" -> LITERAL (TEX_ONLY "\\liminf ")
 248+ | "\\sup" -> LITERAL (TEX_ONLY "\\sup ")
 249+ | "\\Pr" -> LITERAL (TEX_ONLY "\\Pr ")
 250+ | "\\hom" -> LITERAL (HTMLABLEC(FONT_UFH,"\\hom ","hom"))
 251+ | "\\arg" -> LITERAL (HTMLABLEC(FONT_UFH,"\\arg ","arg"))
 252+ | "\\dim" -> LITERAL (HTMLABLEC(FONT_UFH,"\\dim ","dim"))
 253+ | "\\inf" -> LITERAL (TEX_ONLY "\\inf ")
 254+ | "\\circ" -> LITERAL (TEX_ONLY "\\circ ")
 255+ | "\\hbar" -> LITERAL (TEX_ONLY "\\hbar ")
 256+ | "\\imath" -> LITERAL (TEX_ONLY "\\imath ")
 257+ | "\\jmath" -> LITERAL (TEX_ONLY "\\jmath ")
 258+ | "\\lnot" -> LITERAL (TEX_ONLY "\\lnot ")
 259+ | "\\hookrightarrow" -> LITERAL (TEX_ONLY "\\hookrightarrow ")
 260+ | "\\hookleftarrow" -> LITERAL (TEX_ONLY "\\hookleftarrow ")
 261+ | "\\mp" -> LITERAL (TEX_ONLY "\\mp ")
 262+ | "\\approx" -> LITERAL (HTMLABLE (FONT_UF, "\\approx ", "&asymp;"))
 263+ | "\\propto" -> LITERAL (TEX_ONLY "\\propto ")
 264+ | "\\flat" -> LITERAL (TEX_ONLY "\\flat ")
 265+ | "\\sharp" -> LITERAL (TEX_ONLY "\\sharp ")
 266+ | "\\natural" -> LITERAL (TEX_ONLY "\\natural ")
 267+ | "\\int" -> LITERAL (HTMLABLE_BIG ("\\int ", "&int;"))
 268+ | "\\sum" -> LITERAL (HTMLABLE_BIG ("\\sum ", "&sum;"))
 269+ | "\\prod" -> LITERAL (HTMLABLE_BIG ("\\prod ", "&prod;"))
 270+ | "\\vdots" -> LITERAL (TEX_ONLY "\\vdots ")
 271+ | "\\limits" -> LITERAL (TEX_ONLY "\\limits ")
 272+ | "\\nolimits" -> LITERAL (TEX_ONLY "\\nolimits ")
 273+ | "\\top" -> LITERAL (TEX_ONLY "\\top ")
 274+ | "\\sin" -> LITERAL (HTMLABLEC(FONT_UFH,"\\sin ","sin"))
 275+ | "\\cos" -> LITERAL (HTMLABLEC(FONT_UFH,"\\cos ","cos"))
 276+ | "\\sinh" -> LITERAL (HTMLABLEC(FONT_UFH,"\\sinh ","sinh"))
 277+ | "\\cosh" -> LITERAL (HTMLABLEC(FONT_UFH,"\\cosh ","cosh"))
 278+ | "\\tan" -> LITERAL (HTMLABLEC(FONT_UFH,"\\tan ","tan"))
 279+ | "\\tanh" -> LITERAL (HTMLABLEC(FONT_UFH,"\\tanh ","tanh"))
 280+ | "\\sec" -> LITERAL (HTMLABLEC(FONT_UFH,"\\sec ","sec"))
 281+ | "\\csc" -> LITERAL (HTMLABLEC(FONT_UFH,"\\csc ","csc"))
 282+ | "\\arcsin" -> LITERAL (HTMLABLEC(FONT_UFH,"\\arcsin ","arcsin"))
 283+ | "\\arctan" -> LITERAL (HTMLABLEC(FONT_UFH,"\\arctan ","arctan"))
 284+ | "\\arccos" -> (tex_use_ams (); LITERAL (HTMLABLEC(FONT_UFH,"\\mathop{\\mathrm{arccos}}","arccos")))
 285+ | "\\arccot" -> (tex_use_ams (); LITERAL (HTMLABLEC(FONT_UFH,"\\mathop{\\mathrm{arccot}}","arccot")))
 286+ | "\\arcsec" -> (tex_use_ams (); LITERAL (HTMLABLEC(FONT_UFH,"\\mathop{\\mathrm{arcsec}}","arcsec")))
 287+ | "\\arccsc" -> (tex_use_ams (); LITERAL (HTMLABLEC(FONT_UFH,"\\mathop{\\mathrm{arccsc}}","arccsc")))
 288+ | "\\sgn" -> (tex_use_ams (); LITERAL (HTMLABLEC(FONT_UFH,"\\mathop{\\mathrm{sgn}}","sgn")))
 289+ | "\\cot" -> LITERAL (HTMLABLEC(FONT_UFH,"\\cot ","cot"))
 290+ | "\\coth" -> LITERAL (HTMLABLEC(FONT_UFH,"\\coth ","coth"))
 291+ | "\\log" -> LITERAL (HTMLABLEC(FONT_UFH,"\\log ", "log"))
 292+ | "\\lg" -> LITERAL (HTMLABLEC(FONT_UFH,"\\lg ", "lg"))
 293+ | "\\ln" -> LITERAL (HTMLABLEC(FONT_UFH,"\\ln ", "ln"))
 294+ | "\\exp" -> LITERAL (HTMLABLEC(FONT_UFH,"\\exp ", "exp"))
 295+ | "\\min" -> LITERAL (HTMLABLEC(FONT_UFH,"\\min ", "min"))
 296+ | "\\max" -> LITERAL (HTMLABLEC(FONT_UFH,"\\max ", "max"))
 297+ | "\\gcd" -> LITERAL (HTMLABLEC(FONT_UFH,"\\gcd ", "gcd"))
 298+ | "\\deg" -> LITERAL (HTMLABLEC(FONT_UFH,"\\deg ", "deg"))
 299+ | "\\det" -> LITERAL (HTMLABLEC(FONT_UFH,"\\det ", "det"))
 300+ | "\\bullet" -> LITERAL (HTMLABLE (FONT_UFH, "\\bullet ", "&bull;"))
 301+ | "\\bull" -> LITERAL (HTMLABLE (FONT_UFH, "\\bullet ", "&bull;"))
 302+ | "\\angle" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\angle ", "&ang;")))
 303+ | "\\dagger" -> LITERAL (HTMLABLEM(FONT_UFH, "\\dagger ", "&dagger;"))
 304+ | "\\ddagger" -> LITERAL (HTMLABLEM(FONT_UFH, "\\ddagger ", "&Dagger;"))
 305+ | "\\Dagger" -> LITERAL (HTMLABLEM(FONT_UFH, "\\ddagger ", "&Dagger;"))
 306+ | "\\colon" -> LITERAL (HTMLABLEC(FONT_UFH, "\\colon ", ":"))
 307+ | "\\Vert" -> DELIMITER (HTMLABLEM(FONT_UFH, "\\Vert ", "||"))
 308+ | "\\vert" -> DELIMITER (HTMLABLEM(FONT_UFH, "\\vert ", "|"))
 309+ | "\\wp" -> LITERAL (HTMLABLE (FONT_UF, "\\wp ", "&weierp;"))
 310+ | "\\weierp" -> LITERAL (HTMLABLE (FONT_UF, "\\wp ", "&weierp;"))
 311+ | "\\wedge" -> LITERAL (HTMLABLE (FONT_UF, "\\wedge ", "&and;"))
 312+ | "\\and" -> LITERAL (HTMLABLE (FONT_UF, "\\land ", "&and;"))
 313+ | "\\land" -> LITERAL (HTMLABLE (FONT_UF, "\\land ", "&and;"))
 314+ | "\\vee" -> LITERAL (HTMLABLE (FONT_UF, "\\vee ", "&or;"))
 315+ | "\\or" -> LITERAL (HTMLABLE (FONT_UF, "\\lor ", "&or;"))
 316+ | "\\lor" -> LITERAL (HTMLABLE (FONT_UF, "\\lor ", "&or;"))
 317+ | "\\sub" -> LITERAL (HTMLABLE (FONT_UF, "\\subset ", "&sub;"))
 318+ | "\\supe" -> LITERAL (HTMLABLE (FONT_UF, "\\supseteq ", "&supe;"))
 319+ | "\\sube" -> LITERAL (HTMLABLE (FONT_UF, "\\subseteq ", "&sube;"))
 320+ | "\\supset" -> LITERAL (HTMLABLE (FONT_UF, "\\supset ", "&sup;"))
 321+ | "\\subset" -> LITERAL (HTMLABLE (FONT_UF, "\\subset ", "&sub;"))
 322+ | "\\supseteq" -> LITERAL (HTMLABLE (FONT_UF, "\\supseteq ", "&supe;"))
 323+ | "\\subseteq" -> LITERAL (HTMLABLE (FONT_UF, "\\subseteq ", "&sube;"))
 324+ | "\\sqsupset" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsupset "))
 325+ | "\\sqsubset" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsubset "))
 326+ | "\\sqsupseteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsupseteq "))
 327+ | "\\sqsubseteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsubseteq "))
 328+ | "\\perp" -> LITERAL (HTMLABLE (FONT_UF, "\\perp ", "&perp;"))
 329+ | "\\bot" -> LITERAL (HTMLABLE (FONT_UF, "\\bot ", "&perp;"))
 330+ | "\\lfloor" -> DELIMITER (HTMLABLE (FONT_UF, "\\lfloor ", "&lfloor;"))
 331+ | "\\rfloor" -> DELIMITER (HTMLABLE (FONT_UF, "\\rfloor ", "&rfloor;"))
 332+ | "\\lceil" -> DELIMITER (HTMLABLE (FONT_UF, "\\lceil ", "&lceil;"))
 333+ | "\\rceil" -> DELIMITER (HTMLABLE (FONT_UF, "\\rceil ", "&rceil;"))
 334+ | "\\lbrace" -> DELIMITER (HTMLABLEC(FONT_UFH, "\\lbrace ", "{"))
 335+ | "\\rbrace" -> DELIMITER (HTMLABLEC(FONT_UFH, "\\rbrace ", "}"))
 336+ | "\\infty" -> LITERAL (HTMLABLEM(FONT_UF, "\\infty ", "&infin;"))
 337+ | "\\infin" -> LITERAL (HTMLABLEM(FONT_UF, "\\infty ", "&infin;"))
 338+ | "\\isin" -> LITERAL (HTMLABLE (FONT_UF, "\\in ", "&isin;"))
 339+ | "\\in" -> LITERAL (HTMLABLE (FONT_UF, "\\in ", "&isin;"))
 340+ | "\\ni" -> LITERAL (HTMLABLE (FONT_UF, "\\ni ", "&ni;"))
 341+ | "\\notin" -> LITERAL (HTMLABLE (FONT_UF, "\\notin ", "&notin;"))
 342+ | "\\smallsetminus" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\smallsetminus "))
 343+ | "\\And" -> (tex_use_ams (); LITERAL (HTMLABLEM(FONT_UFH, "\\And ", "&nbsp;&amp;&nbsp;")))
 344+ | "\\forall" -> LITERAL (HTMLABLE (FONT_UFH, "\\forall ", "&forall;"))
 345+ | "\\exists" -> LITERAL (HTMLABLE (FONT_UFH, "\\exists ", "&exist;"))
 346+ | "\\exist" -> LITERAL (HTMLABLE (FONT_UFH, "\\exists ", "&exist;"))
 347+ | "\\equiv" -> LITERAL (HTMLABLEM(FONT_UFH, "\\equiv ", "&equiv;"))
 348+ | "\\ne" -> LITERAL (HTMLABLEM(FONT_UFH, "\\neq ", "&ne;"))
 349+ | "\\neq" -> LITERAL (HTMLABLEM(FONT_UFH, "\\neq ", "&ne;"))
 350+ | "\\Re" -> LITERAL (HTMLABLE (FONT_UF, "\\Re ", "&real;"))
 351+ | "\\real" -> LITERAL (HTMLABLE (FONT_UF, "\\Re ", "&real;"))
 352+ | "\\Im" -> LITERAL (HTMLABLE (FONT_UF, "\\Im ", "&image;"))
 353+ | "\\image" -> LITERAL (HTMLABLE (FONT_UF, "\\Im ", "&image;"))
 354+ | "\\prime" -> LITERAL (HTMLABLE (FONT_UFH,"\\prime ", "&prime;"))
 355+ | "\\backslash" -> DELIMITER (HTMLABLEM(FONT_UFH,"\\backslash ", "\\"))
 356+ | "\\setminus" -> LITERAL (HTMLABLEM(FONT_UFH,"\\setminus ", "\\"))
 357+ | "\\times" -> LITERAL (HTMLABLEM(FONT_UFH,"\\times ", "&times;"))
 358+ | "\\pm" -> LITERAL (HTMLABLEM(FONT_UFH,"\\pm ", "&plusmn;"))
 359+ | "\\plusmn" -> LITERAL (HTMLABLEM(FONT_UFH,"\\pm ", "&plusmn;"))
 360+ | "\\cdot" -> LITERAL (HTMLABLE (FONT_UFH,"\\cdot ", "&sdot;"))
 361+ | "\\AA" -> LITERAL (HTMLABLE (FONT_UFH,"\\AA ", "&Aring;"))
 362+ | "\\cdots" -> LITERAL (HTMLABLE (FONT_UFH,"\\cdots ", "&sdot;&sdot;&sdot;"))
 363+ | "\\sdot" -> LITERAL (HTMLABLE (FONT_UFH,"\\cdot ", "&sdot;"))
 364+ | "\\oplus" -> LITERAL (HTMLABLE (FONT_UF, "\\oplus ", "&oplus;"))
 365+ | "\\otimes" -> LITERAL (HTMLABLE (FONT_UF, "\\otimes ", "&otimes;"))
 366+ | "\\cap" -> LITERAL (HTMLABLEM(FONT_UF, "\\cap ", "&cap;"))
 367+ | "\\cup" -> LITERAL (HTMLABLE (FONT_UF, "\\cup ", "&cup;"))
 368+ | "\\uplus" -> LITERAL (TEX_ONLY "\\uplus ")
 369+ | "\\sqcap" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqcap "))
 370+ | "\\sqcup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqcup "))
 371+ | "\\empty" -> LITERAL (HTMLABLE (FONT_UF, "\\emptyset ", "&empty;"))
 372+ | "\\emptyset" -> LITERAL (HTMLABLE (FONT_UF, "\\emptyset ", "&empty;"))
 373+ | "\\O" -> LITERAL (HTMLABLE (FONT_UF, "\\emptyset ", "&empty;"))
 374+ | "\\S" -> LITERAL (HTMLABLEM(FONT_UFH,"\\S ", "&sect;"))
 375+ | "\\sect" -> LITERAL (HTMLABLEM(FONT_UFH,"\\S ", "&sect;"))
 376+ | "\\nabla" -> LITERAL (HTMLABLE (FONT_UF, "\\nabla ", "&nabla;"))
 377+ | "\\geq" -> LITERAL (HTMLABLE (FONT_UFH,"\\geq ", "&ge;"))
 378+ | "\\ge" -> LITERAL (HTMLABLE (FONT_UFH,"\\geq ", "&ge;"))
 379+ | "\\leq" -> LITERAL (HTMLABLE (FONT_UFH,"\\leq ", "&le;"))
 380+ | "\\le" -> LITERAL (HTMLABLE (FONT_UFH,"\\leq ", "&le;"))
 381+ | "\\cong" -> LITERAL (HTMLABLE (FONT_UF, "\\cong ", "&cong;"))
 382+ | "\\ang" -> LITERAL (HTMLABLE (FONT_UF, "\\angle ", "&ang;"))
 383+ | "\\part" -> LITERAL (HTMLABLEM(FONT_UF, "\\partial ", "&part;"))
 384+ | "\\partial" -> LITERAL (HTMLABLEM(FONT_UF, "\\partial ", "&part;"))
 385+ | "\\ldots" -> LITERAL (HTMLABLEM(FONT_UFH,"\\ldots ", "..."))
 386+ | "\\dots" -> LITERAL (HTMLABLEM(FONT_UFH,"\\dots ", "..."))
 387+ | "\\quad" -> LITERAL (HTMLABLE (FONT_UF, "\\quad ","&nbsp;&nbsp;"))
 388+ | "\\qquad" -> LITERAL (HTMLABLE (FONT_UF, "\\qquad ","&nbsp;&nbsp;&nbsp;&nbsp;"))
 389+ | "\\mid" -> LITERAL (HTMLABLEM(FONT_UFH,"\\mid ", " | "))
 390+ | "\\neg" -> LITERAL (HTMLABLEM(FONT_UFH,"\\neg ", "&not;"))
 391+ | "\\langle" -> DELIMITER (HTMLABLE (FONT_UFH,"\\langle ","&lang;"))
 392+ | "\\rangle" -> DELIMITER (HTMLABLE (FONT_UFH,"\\rangle ","&rang;"))
 393+ | "\\lang" -> DELIMITER (HTMLABLE (FONT_UFH,"\\langle ","&lang;"))
 394+ | "\\rang" -> DELIMITER (HTMLABLE (FONT_UFH,"\\rangle ","&rang;"))
 395+ | "\\lbrack" -> DELIMITER (HTMLABLEC(FONT_UFH,"[","["))
 396+ | "\\rbrack" -> DELIMITER (HTMLABLEC(FONT_UFH,"]","]"))
 397+ | "\\surd" -> LITERAL (TEX_ONLY "\\surd ")
 398+ | "\\ddots" -> LITERAL (TEX_ONLY "\\ddots ")
 399+ | "\\clubs" -> LITERAL (TEX_ONLY "\\clubsuit ")
 400+ | "\\clubsuit" -> LITERAL (TEX_ONLY "\\clubsuit ")
 401+ | "\\spades" -> LITERAL (TEX_ONLY "\\spadesuit ")
 402+ | "\\spadesuit" -> LITERAL (TEX_ONLY "\\spadesuit ")
 403+ | "\\hearts" -> LITERAL (TEX_ONLY "\\heartsuit ")
 404+ | "\\heartsuit" -> LITERAL (TEX_ONLY "\\heartsuit ")
 405+ | "\\diamonds" -> LITERAL (TEX_ONLY "\\diamondsuit ")
 406+ | "\\diamond" -> LITERAL (TEX_ONLY "\\diamond ")
 407+ | "\\bigtriangleup" -> LITERAL (TEX_ONLY "\\bigtriangleup ")
 408+ | "\\bigtriangledown" -> LITERAL (TEX_ONLY "\\bigtriangledown ")
 409+ | "\\diamondsuit" -> LITERAL (TEX_ONLY "\\diamondsuit ")
 410+ | "\\ominus" -> LITERAL (TEX_ONLY "\\ominus ")
 411+ | "\\oslash" -> LITERAL (TEX_ONLY "\\oslash ")
 412+ | "\\odot" -> LITERAL (TEX_ONLY "\\odot ")
 413+ | "\\bigcirc" -> LITERAL (TEX_ONLY "\\bigcirc ")
 414+ | "\\amalg" -> LITERAL (TEX_ONLY "\\amalg ")
 415+ | "\\prec" -> LITERAL (TEX_ONLY "\\prec ")
 416+ | "\\succ" -> LITERAL (TEX_ONLY "\\succ ")
 417+ | "\\preceq" -> LITERAL (TEX_ONLY "\\preceq ")
 418+ | "\\succeq" -> LITERAL (TEX_ONLY "\\succeq ")
 419+ | "\\dashv" -> LITERAL (TEX_ONLY "\\dashv ")
 420+ | "\\asymp" -> LITERAL (TEX_ONLY "\\asymp ")
 421+ | "\\doteq" -> LITERAL (TEX_ONLY "\\doteq ")
 422+ | "\\parallel" -> LITERAL (TEX_ONLY "\\parallel ")
 423+ | "\\implies" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\implies ", "&rArr;")))
 424+ | "\\mod" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mod ", "mod")))
 425+ | "\\Diamond" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\Diamond ", "&loz;")))
 426+ | "\\dotsb" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotsb ", "&sdot;&sdot;&sdot;")))
 427+ | "\\dotsc" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotsc ", "...")))
 428+ | "\\dotsi" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotsi ", "&sdot;&sdot;&sdot;")))
 429+ | "\\dotsm" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotsm ", "&sdot;&sdot;&sdot;")))
 430+ | "\\dotso" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotso ", "...")))
 431+ | "\\reals" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{R}", "<b>R</b>")))
 432+ | "\\Reals" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{R}", "<b>R</b>")))
 433+ | "\\R" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{R}", "<b>R</b>")))
 434+ | "\\C" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{C}", "<b>C</b>")))
 435+ | "\\cnums" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{C}", "<b>C</b>")))
 436+ | "\\Complex" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{C}", "<b>C</b>")))
 437+ | "\\Z" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{Z}", "<b>Z</b>")))
 438+ | "\\natnums" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{N}", "<b>N</b>")))
 439+ | "\\N" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{N}", "<b>N</b>")))
 440+ | "\\Q" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{Q}", "<b>Q</b>")))
 441+ | "\\lVert" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\lVert ", "||")))
 442+ | "\\rVert" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\rVert ", "||")))
 443+ | "\\nmid" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nmid "))
 444+ | "\\lesssim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lesssim "))
 445+ | "\\ngeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ngeq "))
 446+ | "\\smallsmile" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\smallsmile "))
 447+ | "\\smallfrown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\smallfrown "))
 448+ | "\\nleftarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleftarrow "))
 449+ | "\\nrightarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nrightarrow "))
 450+ | "\\trianglelefteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\trianglelefteq "))
 451+ | "\\trianglerighteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\trianglerighteq "))
 452+ | "\\square" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\square "))
 453+ | "\\checkmark" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\checkmark "))
 454+ | "\\supsetneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\supsetneq "))
 455+ | "\\subsetneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\subsetneq "))
 456+ | "\\Box" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Box "))
 457+ | "\\nleq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleq "))
 458+ | "\\upharpoonright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\upharpoonright "))
 459+ | "\\restriction" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\upharpoonright "))
 460+ | "\\upharpoonleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\upharpoonleft "))
 461+ | "\\downharpoonright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\downharpoonright "))
 462+ | "\\downharpoonleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\downharpoonleft "))
 463+ | "\\rightharpoonup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightharpoonup "))
 464+ | "\\rightharpoondown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightharpoondown "))
 465+ | "\\leftharpoonup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftharpoonup "))
 466+ | "\\leftharpoondown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftharpoondown "))
 467+ | "\\nless" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nless "))
 468+ | "\\Vdash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Vdash "))
 469+ | "\\vDash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\vDash "))
 470+ | "\\varkappa" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varkappa "))
 471+ | "\\digamma" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\digamma "))
 472+ | "\\beth" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\beth "))
 473+ | "\\daleth" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\daleth "))
 474+ | "\\gimel" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gimel "))
 475+ | "\\complement" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\complement "))
 476+ | "\\eth" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eth "))
 477+ | "\\hslash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\hslash "))
 478+ | "\\mho" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\mho "))
 479+ | "\\Finv" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Finv "))
 480+ | "\\Game" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Game "))
 481+ | "\\varlimsup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varlimsup "))
 482+ | "\\varliminf" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varliminf "))
 483+ | "\\varinjlim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varinjlim "))
 484+ | "\\varprojlim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varprojlim "))
 485+ | "\\injlim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\injlim "))
 486+ | "\\projlim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\projlim "))
 487+ | "\\iint" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\iint "))
 488+ | "\\iiint" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\iiint "))
 489+ | "\\iiiint" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\iiiint "))
 490+ | "\\varnothing" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varnothing "))
 491+ | "\\left" -> LEFT
 492+ | "\\right" -> RIGHT
 493+ | "\\hat" -> FUN_AR1 "\\hat "
 494+ | "\\hline" -> LITERAL (TEX_ONLY "\\hline ")
 495+ | "\\vline" -> LITERAL (TEX_ONLY "\\vline ")
 496+ | "\\widehat" -> LITERAL (TEX_ONLY "\\widehat ")
 497+ | "\\overline" -> LITERAL (TEX_ONLY "\\overline ")
 498+ | "\\overbrace" -> LITERAL (TEX_ONLY "\\overbrace ")
 499+ | "\\underline" -> LITERAL (TEX_ONLY "\\underline ")
 500+ | "\\underbrace" -> LITERAL (TEX_ONLY "\\underbrace ")
 501+ | "\\overleftarrow" -> LITERAL (TEX_ONLY "\\overleftarrow ")
 502+ | "\\overrightarrow" -> LITERAL (TEX_ONLY "\\overrightarrow ")
 503+ | "\\overleftrightarrow"-> (tex_use_ams(); LITERAL (TEX_ONLY "\\overleftrightarrow "))
 504+ | "\\check" -> FUN_AR1 "\\check "
 505+ | "\\acute" -> FUN_AR1 "\\acute "
 506+ | "\\grave" -> FUN_AR1 "\\grave "
 507+ | "\\bar" -> FUN_AR1 "\\bar "
 508+ | "\\vec" -> FUN_AR1 "\\vec "
 509+ | "\\dot" -> FUN_AR1 "\\dot "
 510+ | "\\ddot" -> FUN_AR1 "\\ddot "
 511+ | "\\breve" -> FUN_AR1 "\\breve "
 512+ | "\\tilde" -> FUN_AR1 "\\tilde "
 513+ | "\\not" -> LITERAL (TEX_ONLY "\\not ")
 514+ | "\\choose" -> FUN_INFIX "\\choose "
 515+ | "\\atop" -> FUN_INFIX "\\atop "
 516+ | "\\binom" -> (tex_use_ams (); FUN_AR2 "\\binom ")
 517+ | "\\dbinom" -> (tex_use_ams (); FUN_AR2 "\\dbinom ")
 518+ | "\\tbinom" -> (tex_use_ams (); FUN_AR2 "\\tbinom ")
 519+ | "\\stackrel" -> FUN_AR2 "\\stackrel "
 520+ | "\\sideset" -> (tex_use_ams (); FUN_AR2nb "\\sideset ")
 521+ | "\\underset" -> (tex_use_ams (); FUN_AR2 "\\underset ")
 522+ | "\\overset" -> (tex_use_ams (); FUN_AR2 "\\overset ")
 523+ | "\\frac" -> FUN_AR2h ("\\frac ", fun num den -> Html.html_render [num], "<hr style=\"{background: black}\"/>", Html.html_render [den])
 524+ | "\\dfrac" -> (tex_use_ams () ; FUN_AR2 "\\dfrac ")
 525+ | "\\tfrac" -> (tex_use_ams () ; FUN_AR2h ("\\tfrac ", fun num den -> Html.html_render [num], "<hr style=\"background: black\">", Html.html_render [den]))
 526+ | "\\cfrac" -> (tex_use_ams (); FUN_AR2h ("\\cfrac ", fun num den -> Html.html_render [num], "<hr style=\"{background: black}\">", Html.html_render [den]))
 527+ | "\\over" -> FUN_INFIXh ("\\over ", fun num den -> Html.html_render num, "<hr style=\"{background: black}\"/>", Html.html_render den)
 528+ | "\\sqrt" -> FUN_AR1 "\\sqrt "
 529+ | "\\cancel" -> FUN_AR1 "\\cancel "
 530+ | "\\bcancel" -> FUN_AR1 "\\bcancel "
 531+ | "\\xcancel" -> FUN_AR1 "\\xcancel "
 532+ | "\\cancelto" -> FUN_AR2 "\\cancelto "
 533+ | "\\pmod" -> FUN_AR1hl ("\\pmod ", ("(mod ", ")"))
 534+ | "\\bmod" -> FUN_AR1hl ("\\bmod ", ("mod ", ""))
 535+ | "\\emph" -> FUN_AR1 "\\emph "
 536+ | "\\texttt" -> FUN_AR1 "\\texttt "
 537+ | "\\textbf" -> FUN_AR1 "\\textbf "
 538+ | "\\textsf" -> FUN_AR1 "\\textsf "
 539+ | "\\textit" -> FUN_AR1hf ("\\textit ", FONTFORCE_IT)
 540+ | "\\textrm" -> FUN_AR1hf ("\\textrm ", FONTFORCE_RM)
 541+ | "\\rm" -> DECLh ("\\rm ", FONTFORCE_RM)
 542+ | "\\it" -> DECLh ("\\it ", FONTFORCE_IT)
 543+ | "\\cal" -> DECL "\\cal "
 544+ | "\\displaystyle" -> LITERAL (TEX_ONLY "\\displaystyle ")
 545+ | "\\scriptstyle" -> LITERAL (TEX_ONLY "\\scriptstyle ")
 546+ | "\\textstyle" -> LITERAL (TEX_ONLY "\\textstyle ")
 547+ | "\\scriptscriptstyle"-> LITERAL (TEX_ONLY "\\scriptscriptstyle ")
 548+ | "\\bf" -> DECL "\\bf "
 549+ | "\\big" -> BIG "\\big "
 550+ | "\\Big" -> BIG "\\Big "
 551+ | "\\bigg" -> BIG "\\bigg "
 552+ | "\\Bigg" -> BIG "\\Bigg "
 553+ | "\\bigl" -> (tex_use_ams ();BIG "\\bigl ")
 554+ | "\\bigr" -> (tex_use_ams ();BIG "\\bigr ")
 555+ | "\\Bigl" -> (tex_use_ams ();BIG "\\Bigl ")
 556+ | "\\Bigr" -> (tex_use_ams ();BIG "\\Bigr ")
 557+ | "\\biggl" -> (tex_use_ams ();BIG "\\biggl ")
 558+ | "\\biggr" -> (tex_use_ams ();BIG "\\biggr ")
 559+ | "\\Biggl" -> (tex_use_ams ();BIG "\\Biggl ")
 560+ | "\\Biggr" -> (tex_use_ams ();BIG "\\Biggr ")
 561+ | "\\vartriangle" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\vartriangle "))
 562+ | "\\triangledown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\triangledown "))
 563+ | "\\lozenge" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lozenge "))
 564+ | "\\circledS" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circledS "))
 565+ | "\\measuredangle" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\measuredangle "))
 566+ | "\\nexists" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nexists "))
 567+ | "\\Bbbk" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Bbbk "))
 568+ | "\\backprime" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\backprime "))
 569+ | "\\blacktriangle" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacktriangle "))
 570+ | "\\blacktriangledown"-> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacktriangledown "))
 571+ | "\\blacksquare" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacksquare "))
 572+ | "\\blacklozenge" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacklozenge "))
 573+ | "\\bigstar" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\bigstar "))
 574+ | "\\sphericalangle" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sphericalangle "))
 575+ | "\\diagup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\diagup "))
 576+ | "\\diagdown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\diagdown "))
 577+ | "\\dotplus" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\dotplus "))
 578+ | "\\Cap" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Cap "))
 579+ | "\\doublecap" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Cap "))
 580+ | "\\Cup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Cup "))
 581+ | "\\doublecup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Cup "))
 582+ | "\\barwedge" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\barwedge "))
 583+ | "\\veebar" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\veebar "))
 584+ | "\\doublebarwedge" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\doublebarwedge "))
 585+ | "\\boxminus" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\boxminus "))
 586+ | "\\boxtimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\boxtimes "))
 587+ | "\\boxdot" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\boxdot "))
 588+ | "\\boxplus" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\boxplus "))
 589+ | "\\divideontimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\divideontimes "))
 590+ | "\\ltimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ltimes "))
 591+ | "\\rtimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rtimes "))
 592+ | "\\leftthreetimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftthreetimes "))
 593+ | "\\rightthreetimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightthreetimes "))
 594+ | "\\curlywedge" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curlywedge "))
 595+ | "\\curlyvee" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curlyvee "))
 596+ | "\\circleddash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circleddash "))
 597+ | "\\circledast" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circledast "))
 598+ | "\\circledcirc" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circledcirc "))
 599+ | "\\centerdot" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\centerdot "))
 600+ | "\\intercal" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\intercal "))
 601+ | "\\leqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leqq "))
 602+ | "\\leqslant" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leqslant "))
 603+ | "\\eqslantless" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eqslantless "))
 604+ | "\\lessapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lessapprox "))
 605+ | "\\approxeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\approxeq "))
 606+ | "\\lessdot" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lessdot "))
 607+ | "\\lll" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lll "))
 608+ | "\\lessgtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lessgtr "))
 609+ | "\\lesseqgtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lesseqgtr "))
 610+ | "\\lesseqqgtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lesseqqgtr "))
 611+ | "\\doteqdot" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\doteqdot "))
 612+ | "\\Doteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\doteqdot "))
 613+ | "\\risingdotseq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\risingdotseq "))
 614+ | "\\fallingdotseq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\fallingdotseq "))
 615+ | "\\backsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\backsim "))
 616+ | "\\backsimeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\backsimeq "))
 617+ | "\\subseteqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\subseteqq "))
 618+ | "\\Subset" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Subset "))
 619+ | "\\preccurlyeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\preccurlyeq "))
 620+ | "\\curlyeqprec" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curlyeqprec "))
 621+ | "\\precsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\precsim "))
 622+ | "\\precapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\precapprox "))
 623+ | "\\vartriangleleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\vartriangleleft "))
 624+ | "\\Vvdash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Vvdash "))
 625+ | "\\bumpeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\bumpeq "))
 626+ | "\\Bumpeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Bumpeq "))
 627+ | "\\geqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\geqq "))
 628+ | "\\geqslant" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\geqslant "))
 629+ | "\\eqslantgtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eqslantgtr "))
 630+ | "\\gtrsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtrsim "))
 631+ | "\\gtrapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtrapprox "))
 632+ | "\\eqsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eqsim "))
 633+ | "\\gtrdot" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtrdot "))
 634+ | "\\ggg" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ggg "))
 635+ | "\\gggtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ggg "))
 636+ | "\\gtrless" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtrless "))
 637+ | "\\gtreqless" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtreqless "))
 638+ | "\\gtreqqless" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtreqqless "))
 639+ | "\\eqcirc" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eqcirc "))
 640+ | "\\circeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circeq "))
 641+ | "\\triangleq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\triangleq "))
 642+ | "\\thicksim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\thicksim "))
 643+ | "\\thickapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\thickapprox "))
 644+ | "\\supseteqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\supseteqq "))
 645+ | "\\Supset" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Supset "))
 646+ | "\\succcurlyeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succcurlyeq "))
 647+ | "\\curlyeqsucc" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curlyeqsucc "))
 648+ | "\\succsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succsim "))
 649+ | "\\succapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succapprox "))
 650+ | "\\vartriangleright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\vartriangleright "))
 651+ | "\\shortmid" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\shortmid "))
 652+ | "\\shortparallel" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\shortparallel "))
 653+ | "\\between" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\between "))
 654+ | "\\pitchfork" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\pitchfork "))
 655+ | "\\varpropto" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varpropto "))
 656+ | "\\blacktriangleleft"-> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacktriangleleft "))
 657+ | "\\therefore" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\therefore "))
 658+ | "\\backepsilon" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\backepsilon "))
 659+ | "\\blacktriangleright"-> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacktriangleright "))
 660+ | "\\because" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\because "))
 661+ | "\\nleqslant" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleqslant "))
 662+ | "\\nleqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleqq "))
 663+ | "\\lneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lneq "))
 664+ | "\\lneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lneqq "))
 665+ | "\\lvertneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lvertneqq "))
 666+ | "\\lnsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lnsim "))
 667+ | "\\lnapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lnapprox "))
 668+ | "\\nprec" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nprec "))
 669+ | "\\npreceq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\npreceq "))
 670+ | "\\precneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\precneqq "))
 671+ | "\\precnsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\precnsim "))
 672+ | "\\precnapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\precnapprox "))
 673+ | "\\nsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsim "))
 674+ | "\\nshortmid" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nshortmid "))
 675+ | "\\nvdash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nvdash "))
 676+ | "\\nVdash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nVdash "))
 677+ | "\\ntriangleleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ntriangleleft "))
 678+ | "\\ntrianglelefteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ntrianglelefteq "))
 679+ | "\\nsubseteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsubseteq "))
 680+ | "\\nsubseteqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsubseteqq "))
 681+ | "\\varsubsetneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varsubsetneq "))
 682+ | "\\subsetneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\subsetneqq "))
 683+ | "\\varsubsetneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varsubsetneqq "))
 684+ | "\\ngtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ngtr "))
 685+ | "\\ngeqslant" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ngeqslant "))
 686+ | "\\ngeqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ngeqq "))
 687+ | "\\gneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gneq "))
 688+ | "\\gneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gneqq "))
 689+ | "\\gvertneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gvertneqq "))
 690+ | "\\gnsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gnsim "))
 691+ | "\\gnapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gnapprox "))
 692+ | "\\nsucc" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsucc "))
 693+ | "\\nsucceq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsucceq "))
 694+ | "\\succneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succneqq "))
 695+ | "\\succnsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succnsim "))
 696+ | "\\succnapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succnapprox "))
 697+ | "\\ncong" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ncong "))
 698+ | "\\nshortparallel" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nshortparallel "))
 699+ | "\\nparallel" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nparallel "))
 700+ | "\\nvDash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nvDash "))
 701+ | "\\nVDash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nVDash "))
 702+ | "\\ntriangleright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ntriangleright "))
 703+ | "\\ntrianglerighteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ntrianglerighteq "))
 704+ | "\\nsupseteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsupseteq "))
 705+ | "\\nsupseteqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsupseteqq "))
 706+ | "\\varsupsetneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varsupsetneq "))
 707+ | "\\supsetneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\supsetneqq "))
 708+ | "\\varsupsetneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varsupsetneqq "))
 709+ | "\\leftleftarrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftleftarrows "))
 710+ | "\\leftrightarrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftrightarrows "))
 711+ | "\\Lleftarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Lleftarrow "))
 712+ | "\\leftarrowtail" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftarrowtail "))
 713+ | "\\looparrowleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\looparrowleft "))
 714+ | "\\leftrightharpoons"-> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftrightharpoons "))
 715+ | "\\curvearrowleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curvearrowleft "))
 716+ | "\\circlearrowleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circlearrowleft "))
 717+ | "\\Lsh" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Lsh "))
 718+ | "\\upuparrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\upuparrows "))
 719+ | "\\rightrightarrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightrightarrows "))
 720+ | "\\rightleftarrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightleftarrows "))
 721+ | "\\Rrightarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Rrightarrow "))
 722+ | "\\rightarrowtail" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightarrowtail "))
 723+ | "\\looparrowright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\looparrowright "))
 724+ | "\\curvearrowright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curvearrowright "))
 725+ | "\\circlearrowright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circlearrowright "))
 726+ | "\\Rsh" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Rsh "))
 727+ | "\\downdownarrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\downdownarrows "))
 728+ | "\\multimap" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\multimap "))
 729+ | "\\leftrightsquigarrow"-> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftrightsquigarrow "))
 730+ | "\\rightsquigarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightsquigarrow "))
 731+ | "\\nLeftarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nLeftarrow "))
 732+ | "\\nleftrightarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleftrightarrow "))
 733+ | "\\nRightarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nRightarrow "))
 734+ | "\\nLeftrightarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nLeftrightarrow "))
 735+ | "\\mathit" -> (tex_use_ams (); FUN_AR1hf ("\\mathit ", FONTFORCE_IT))
 736+ | "\\mathrm" -> (tex_use_ams (); FUN_AR1hf ("\\mathrm ", FONTFORCE_RM))
 737+ | "\\mathord" -> (tex_use_ams (); FUN_AR1 "\\mathord ")
 738+ | "\\mathop" -> (tex_use_ams (); FUN_AR1 "\\mathop ")
 739+ | "\\mathbin" -> (tex_use_ams (); FUN_AR1 "\\mathbin ")
 740+ | "\\mathrel" -> (tex_use_ams (); FUN_AR1 "\\mathrel ")
 741+ | "\\mathopen" -> (tex_use_ams (); FUN_AR1 "\\mathopen ")
 742+ | "\\mathclose" -> (tex_use_ams (); FUN_AR1 "\\mathclose ")
 743+ | "\\mathpunct" -> (tex_use_ams (); FUN_AR1 "\\mathpunct ")
 744+ | "\\boldsymbol" -> (tex_use_ams (); FUN_AR1 "\\boldsymbol ")
 745+ | "\\bold" -> (tex_use_ams (); FUN_AR1 "\\mathbf ")
 746+ | "\\Bbb" -> (tex_use_ams (); FUN_AR1 "\\mathbb ")
 747+ | "\\mathbf" -> (tex_use_ams (); FUN_AR1 "\\mathbf ")
 748+ | "\\mathsf" -> (tex_use_ams (); FUN_AR1 "\\mathsf ")
 749+ | "\\mathcal" -> (tex_use_ams (); FUN_AR1 "\\mathcal ")
 750+ | "\\mathbb" -> (tex_use_ams (); FUN_AR1 "\\mathbb ")
 751+ | "\\mathtt" -> (tex_use_ams (); FUN_AR1 "\\mathtt ")
 752+ | "\\mathfrak" -> (tex_use_ams (); FUN_AR1 "\\mathfrak ")
 753+ | "\\operatorname" -> (tex_use_ams (); FUN_AR1 "\\operatorname ")
 754+ | "\\text" -> raise (Failure "malformatted \\text")
 755+ | "\\mbox" -> raise (Failure "malformatted \\mbox")
 756+ | "\\vbox" -> raise (Failure "malformatted \\vbox")
 757+ | "\\hbox" -> raise (Failure "malformatted \\hbox")
 758+ | "\\color" -> (tex_use_color (); LITERAL (TEX_ONLY "\\color"))
 759+ | "\\pagecolor" -> (tex_use_color (); LITERAL (TEX_ONLY "\\pagecolor"))
 760+ | "\\definecolor" -> (tex_use_color (); LITERAL (TEX_ONLY "\\definecolor"))
 761+ | s -> raise (Illegal_tex_function s)
Property changes on: trunk/extensions/Math/math/texutil.ml
___________________________________________________________________
Added: svn:keywords
1762 + Author Date Id Revision
Added: svn:eol-style
2763 + native
Index: trunk/extensions/Math/math/render_info.mli
@@ -0,0 +1,20 @@
 2+type font_force =
 3+ FONTFORCE_IT
 4+ | FONTFORCE_RM
 5+type font_class =
 6+ FONT_IT (* IT default, may be forced to be RM *)
 7+ | FONT_RM (* RM default, may be forced to be IT *)
 8+ | FONT_UF (* not affected by IT/RM setting *)
 9+ | FONT_RTI (* RM - any, IT - not available in HTML *)
 10+ | FONT_UFH (* in TeX UF, in HTML RM *)
 11+type math_class =
 12+ MN
 13+ | MI
 14+ | MO
 15+type t =
 16+ HTMLABLEC of font_class * string * string
 17+ | HTMLABLEM of font_class * string * string
 18+ | HTMLABLE of font_class * string * string
 19+ | MHTMLABLEC of font_class * string * string * math_class * string
 20+ | HTMLABLE_BIG of string * string
 21+ | TEX_ONLY of string
Property changes on: trunk/extensions/Math/math/render_info.mli
___________________________________________________________________
Added: svn:keywords
122 + Author Date Id Revision
Added: svn:eol-style
223 + native
Index: trunk/extensions/Math/math/html.ml
@@ -0,0 +1,142 @@
 2+open Render_info
 3+open Tex
 4+open Util
 5+
 6+exception Too_difficult_for_html
 7+type context = CTX_NORMAL | CTX_IT | CTX_RM
 8+type conservativeness_t = CONSERVATIVE | MODERATE | LIBERAL
 9+
 10+let conservativeness = ref CONSERVATIVE
 11+let html_liberal () = conservativeness := LIBERAL
 12+let html_moderate () = if !conservativeness = CONSERVATIVE then conservativeness := MODERATE else ()
 13+
 14+
 15+let new_ctx = function
 16+ FONTFORCE_IT -> CTX_IT
 17+ | FONTFORCE_RM -> CTX_RM
 18+let font_render lit = function
 19+ (_, FONT_UFH) -> lit
 20+ | (_, FONT_UF) -> lit
 21+ | (CTX_IT,FONT_RTI) -> raise Too_difficult_for_html
 22+ | (_, FONT_RTI) -> lit
 23+ | (CTX_IT,FONT_RM) -> "<i>"^lit^"</i>"
 24+ | (_, FONT_RM) -> lit
 25+ | (CTX_RM,FONT_IT) -> lit
 26+ | (_, FONT_IT) -> "<i>"^lit^"</i>"
 27+
 28+let rec html_render_flat ctx = function
 29+ TEX_LITERAL (HTMLABLE (ft,_,sh))::r -> (html_liberal (); (font_render sh (ctx,ft))^html_render_flat ctx r)
 30+ | TEX_LITERAL (HTMLABLEC(ft,_,sh))::r -> (font_render sh (ctx,ft))^html_render_flat ctx r
 31+ | TEX_LITERAL (MHTMLABLEC(ft,_,sh,_,_))::r -> (font_render sh (ctx,ft))^html_render_flat ctx r
 32+ | TEX_LITERAL (HTMLABLEM(ft,_,sh))::r -> (html_moderate(); (font_render sh (ctx,ft))^html_render_flat ctx r)
 33+ | TEX_LITERAL (HTMLABLE_BIG (_,sh))::r -> (html_liberal (); sh^html_render_flat ctx r)
 34+ | TEX_FUN1hl (_,(f1,f2),a)::r -> f1^(html_render_flat ctx [a])^f2^html_render_flat ctx r
 35+ | TEX_FUN1hf (_,ff,a)::r -> (html_render_flat (new_ctx ff) [a])^html_render_flat ctx r
 36+ | TEX_DECLh (_,ff,a)::r -> (html_render_flat (new_ctx ff) a)^html_render_flat ctx r
 37+ | TEX_CURLY ls::r -> html_render_flat ctx (ls @ r)
 38+ | TEX_DQ (a,b)::r -> (html_liberal ();
 39+ let bs = html_render_flat ctx [b] in match html_render_size ctx a with
 40+ true, s -> raise Too_difficult_for_html
 41+ | false, s -> s^"<sub>"^bs^"</sub>")^html_render_flat ctx r
 42+ | TEX_UQ (a,b)::r -> (html_liberal ();
 43+ let bs = html_render_flat ctx [b] in match html_render_size ctx a with
 44+ true, s -> raise Too_difficult_for_html
 45+ | false, s -> s^"<sup>"^bs^"</sup>")^html_render_flat ctx r
 46+ | TEX_FQ (a,b,c)::r -> (html_liberal ();
 47+ (let bs = html_render_flat ctx [b] in let cs = html_render_flat ctx [c] in
 48+ match html_render_size ctx a with
 49+ true, s -> raise Too_difficult_for_html
 50+ | false, s -> s^"<sub>"^bs^"</sub><sup>"^cs^"</sup>")^html_render_flat ctx r)
 51+ | TEX_DQN (a)::r -> (html_liberal ();
 52+ let bs = html_render_flat ctx [a] in "<sub>"^bs^"</sub>")^html_render_flat ctx r
 53+ | TEX_UQN (a)::r -> (html_liberal ();
 54+ let bs = html_render_flat ctx [a] in "<sup>"^bs^"</sup>")^html_render_flat ctx r
 55+ | TEX_FQN (a,b)::r -> (html_liberal ();
 56+ (let bs = html_render_flat ctx [a] in let cs = html_render_flat ctx [b] in "<sub>"^bs^"</sub><sup>"^cs^"</sup>")^html_render_flat ctx r)
 57+ | TEX_BOX (_,s)::r -> s^html_render_flat ctx r
 58+ | TEX_LITERAL (TEX_ONLY _)::_ -> raise Too_difficult_for_html
 59+ | TEX_FUN1 _::_ -> raise Too_difficult_for_html
 60+ | TEX_FUN2 _::_ -> raise Too_difficult_for_html
 61+ | TEX_FUN2nb _::_ -> raise Too_difficult_for_html
 62+ | TEX_FUN2h _::_ -> raise Too_difficult_for_html
 63+ | TEX_FUN2sq _::_ -> raise Too_difficult_for_html
 64+ | TEX_INFIX _::_ -> raise Too_difficult_for_html
 65+ | TEX_INFIXh _::_ -> raise Too_difficult_for_html
 66+ | TEX_MATRIX _::_ -> raise Too_difficult_for_html
 67+ | TEX_LR _::_ -> raise Too_difficult_for_html
 68+ | TEX_BIG _::_ -> raise Too_difficult_for_html
 69+ | [] -> ""
 70+and html_render_size ctx = function
 71+ TEX_LITERAL (HTMLABLE_BIG (_,sh)) -> true,sh
 72+ | x -> false,html_render_flat ctx [x]
 73+
 74+let rec html_render_deep ctx = function
 75+ TEX_LITERAL (HTMLABLE (ft,_,sh))::r -> (html_liberal (); ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r)
 76+ | TEX_LITERAL (HTMLABLEM(ft,_,sh))::r -> (html_moderate(); ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r)
 77+ | TEX_LITERAL (HTMLABLEC(ft,_,sh))::r -> ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r
 78+ | TEX_LITERAL (MHTMLABLEC(ft,_,sh,_,_))::r -> ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r
 79+ | TEX_LITERAL (HTMLABLE_BIG (_,sh))::r -> (html_liberal (); ("",sh,"")::html_render_deep ctx r)
 80+ | TEX_FUN2h (_,f,a,b)::r -> (html_liberal (); (f a b)::html_render_deep ctx r)
 81+ | TEX_INFIXh (_,f,a,b)::r -> (html_liberal (); (f a b)::html_render_deep ctx r)
 82+ | TEX_CURLY ls::r -> html_render_deep ctx (ls @ r)
 83+ | TEX_DQ (a,b)::r -> (let bs = html_render_flat ctx [b] in match html_render_size ctx a with
 84+ true, s -> "","<span style='font-size: x-large; font-family: serif;'>"^s^"</span>",bs
 85+ | false, s -> "",(s^"<sub>"^bs^"</sub>"),"")::html_render_deep ctx r
 86+ | TEX_UQ (a,b)::r -> (let bs = html_render_flat ctx [b] in match html_render_size ctx a with
 87+ true, s -> bs,"<span style='font-size: x-large; font-family: serif;'>"^s^"</span>",""
 88+ | false, s -> "",(s^"<sup>"^bs^"</sup>"),"")::html_render_deep ctx r
 89+ | TEX_FQ (a,b,c)::r -> (html_liberal ();
 90+ (let bs = html_render_flat ctx [b] in let cs = html_render_flat ctx [c] in
 91+ match html_render_size ctx a with
 92+ true, s -> (cs,"<span style='font-size: x-large; font-family: serif;'>"^s^"</span>",bs)
 93+ | false, s -> ("",(s^"<sub>"^bs^"</sub><sup>"^cs^"</sup>"),""))::html_render_deep ctx r)
 94+ | TEX_DQN (a)::r -> (let bs = html_render_flat ctx [a] in "",("<sub>"^bs^"</sub>"),"")::html_render_deep ctx r
 95+ | TEX_UQN (a)::r -> (let bs = html_render_flat ctx [a] in "",("<sup>"^bs^"</sup>"),"")::html_render_deep ctx r
 96+ | TEX_FQN (a,b)::r -> (html_liberal ();
 97+ (let bs = html_render_flat ctx [a] in let cs = html_render_flat ctx [b] in
 98+ ("",("<sub>"^bs^"</sub><sup>"^cs^"</sup>"),""))::html_render_deep ctx r)
 99+ | TEX_FUN1hl (_,(f1,f2),a)::r -> ("",f1,"")::(html_render_deep ctx [a]) @ ("",f2,"")::html_render_deep ctx r
 100+ | TEX_FUN1hf (_,ff,a)::r -> (html_render_deep (new_ctx ff) [a]) @ html_render_deep ctx r
 101+ | TEX_DECLh (_,ff,a)::r -> (html_render_deep (new_ctx ff) a) @ html_render_deep ctx r
 102+ | TEX_BOX (_,s)::r -> ("",s,"")::html_render_deep ctx r
 103+ | TEX_LITERAL (TEX_ONLY _)::_ -> raise Too_difficult_for_html
 104+ | TEX_FUN1 _::_ -> raise Too_difficult_for_html
 105+ | TEX_FUN2 _::_ -> raise Too_difficult_for_html
 106+ | TEX_FUN2nb _::_ -> raise Too_difficult_for_html
 107+ | TEX_FUN2sq _::_ -> raise Too_difficult_for_html
 108+ | TEX_INFIX _::_ -> raise Too_difficult_for_html
 109+ | TEX_MATRIX _::_ -> raise Too_difficult_for_html
 110+ | TEX_LR _::_ -> raise Too_difficult_for_html
 111+ | TEX_BIG _::_ -> raise Too_difficult_for_html
 112+ | [] -> []
 113+
 114+let rec html_render_table = function
 115+ sf,u,d,("",a,"")::("",b,"")::r -> html_render_table (sf,u,d,(("",a^b,"")::r))
 116+ | sf,u,d,(("",a,"") as c)::r -> html_render_table (c::sf,u,d,r)
 117+ | sf,u,d,((_,a,"") as c)::r -> html_render_table (c::sf,true,d,r)
 118+ | sf,u,d,(("",a,_) as c)::r -> html_render_table (c::sf,u,true,r)
 119+ | sf,u,d,((_,a,_) as c)::r -> html_render_table (c::sf,true,true,r)
 120+ | sf,false,false,[] -> mapjoin (function (u,m,d) -> m) (List.rev sf)
 121+ | sf,true,false,[] -> let ustr,mstr = List.fold_left (fun (us,ms) (u,m,d) -> (us^"<td>"^u^"</td>",ms^"<td>"^u^"</td>"))
 122+ ("","") (List.rev sf) in
 123+ "\n<table>\n" ^
 124+ "\t\t<tr style='text-align: center; vertical-align: bottom;'>" ^ ustr ^ "</tr>\n" ^
 125+ "\t\t<tr style='text-align: center;'>" ^ mstr ^ "</tr>\n" ^
 126+ "</table>\n"
 127+ | sf,false,true,[] -> let mstr,dstr = List.fold_left (fun (ms,ds) (u,m,d) -> (ms^"<td>"^m^"</td>",ds^"<td>"^d^"</td>"))
 128+ ("","") (List.rev sf) in
 129+ "\n<table>\n" ^
 130+ "\t\t<tr style='text-align: center;'>" ^ mstr ^ "</tr>\n" ^
 131+ "\t\t<tr style='text-align: center; vertical-align: top;'>" ^ dstr ^ "</tr>\n" ^
 132+ "</table>\n"
 133+ | sf,true,true,[] -> let ustr,mstr,dstr = List.fold_left (fun (us,ms,ds) (u,m,d) ->
 134+ (us^"<td>"^u^"</td>",ms^"<td>"^m^"</td>",ds^"<td>"^d^"</td>")) ("","","") (List.rev sf) in
 135+ "\n<table>\n" ^
 136+ "\t\t<tr style='text-align: center; vertical-align: bottom;'>" ^ ustr ^ "</tr>\n" ^
 137+ "\t\t<tr style='text-align: center;'>" ^ mstr ^ "</tr>\n" ^
 138+ "\t\t<tr style='text-align: center; vertical-align: top;'>" ^ dstr ^ "</tr>\n" ^
 139+ "</table>\n"
 140+
 141+let html_render tree = html_render_table ([],false,false,html_render_deep CTX_NORMAL tree)
 142+
 143+let render tree = try Some (html_render tree) with _ -> None
Property changes on: trunk/extensions/Math/math/html.ml
___________________________________________________________________
Added: svn:keywords
1144 + Author Date Id Revision
Added: svn:eol-style
2145 + native
Index: trunk/extensions/Math/math/.htaccess
@@ -0,0 +1 @@
 2+Deny from all
Property changes on: trunk/extensions/Math/math/.htaccess
___________________________________________________________________
Added: svn:keywords
13 + Author Date Id Revision
Added: svn:eol-style
24 + native
Index: trunk/extensions/Math/math/Makefile
@@ -0,0 +1,87 @@
 2+.PHONY: clean all
 3+
 4+OBJ=render_info.cmo tex.cmo texutil.cmo parser.cmo lexer.cmo texvc.cmo \
 5+render_info.cmx tex.cmx texutil.cmx parser.cmx lexer.cmx texvc.cmx \
 6+lexer.cmi parser.cmi render_info.cmi tex.cmi texutil.cmi texvc.cmi \
 7+lexer.o parser.o render_info.o tex.o texutil.o texvc.o \
 8+lexer.ml parser.ml parser.mli texvc texvc.bc texvc_test.cmo \
 9+texvc_test.cmx texvc_test.cmi texvc_test.o texvc_test util.o \
 10+util.cmo util.cmx util.cmi texvc_cgi.cmi texvc_cgi texvc_cgi.cmo \
 11+render.o render.cmi render.cmo render.cmx texvc_tex.cmx \
 12+texvc_tex.o texvc_tex.cmi texvc_tex html.cmi html.cmo html.cmx \
 13+html.o mathml.cmi mathml.cmo mathml.cmx mathml.o
 14+CGIPATH=-I /usr/lib/ocaml/cgi -I /usr/lib/ocaml/netstring -I /usr/lib/ocaml/pcre
 15+
 16+COMMON_NATIVE_OBJ =util.cmx parser.cmx html.cmx mathml.cmx texutil.cmx lexer.cmx
 17+COMMON_BYTECODE_OBJ=util.cmo parser.cmo html.cmo mathml.cmo texutil.cmo lexer.cmo
 18+
 19+all: texvc texvc_test texvc_tex
 20+cgi: texvc_cgi.cmo texvc_cgi
 21+clean:
 22+ rm -f $(OBJ)
 23+
 24+# Native versions
 25+texvc: $(COMMON_NATIVE_OBJ) render.cmx texvc.cmx
 26+ ocamlopt -o $@ unix.cmxa $^
 27+texvc_test: $(COMMON_NATIVE_OBJ) lexer.cmx texvc_test.cmx
 28+ ocamlopt -o $@ $^
 29+texvc_tex: $(COMMON_NATIVE_OBJ) texvc_tex.cmx
 30+ ocamlopt -o $@ $^
 31+
 32+# Bytecode version
 33+texvc.bc: $(COMMON_BYTECODE_OBJ) render.cmo texvc.cmo
 34+ ocamlc -o $@ unix.cma $^
 35+
 36+# CGI related targets:
 37+texvc_cgi.cmo: texvc_cgi.ml
 38+ ocamlc -c $(CGIPATH) $<
 39+texvc_cgi: util.cmo parser.cmo texutil.cmo render.cmo lexer.cmo texvc_cgi.cmo
 40+ ocamlc -o $@ unix.cma $(CGIPATH) pcre.cma netstring.cma cgi.cma $^
 41+ chmod g-w $@
 42+
 43+#
 44+# Pattern rules
 45+#
 46+
 47+# .ml source .mli interface
 48+# .cmi compiled interface
 49+# .cmo object .cma library object
 50+# .cmx object file .cmxa library object file
 51+%.ml: %.mll
 52+ ocamllex $<
 53+%.mli %.ml: %.mly
 54+ ocamlyacc $<
 55+%.cmo: %.ml
 56+ ocamlc -c $<
 57+%.cmx: %.ml
 58+ ocamlopt -c $<
 59+%.cmi: %.mli
 60+ ocamlc -c $<
 61+
 62+# Various dependencies
 63+
 64+html.cmo: render_info.cmi tex.cmi util.cmo html.cmi
 65+html.cmx: render_info.cmi tex.cmi util.cmx html.cmi
 66+html.cmi: tex.cmi
 67+lexer.cmo: parser.cmi render_info.cmi tex.cmi texutil.cmi
 68+lexer.cmx: parser.cmx render_info.cmi tex.cmi texutil.cmx
 69+mathml.cmo: tex.cmi mathml.cmi
 70+mathml.cmx: tex.cmi mathml.cmi
 71+mathml.cmi: tex.cmi
 72+parser.cmo: render_info.cmi tex.cmi parser.cmi
 73+parser.cmx: render_info.cmi tex.cmi parser.cmi
 74+parser.cmi: render_info.cmi tex.cmi
 75+render.cmo: texutil.cmi util.cmo
 76+render.cmx: texutil.cmx util.cmx
 77+tex.cmi: render_info.cmi
 78+texutil.cmo: html.cmi parser.cmi render_info.cmi tex.cmi util.cmo texutil.cmi
 79+texutil.cmx: html.cmx parser.cmx render_info.cmi tex.cmi util.cmx texutil.cmi
 80+texutil.cmi: parser.cmi tex.cmi
 81+texvc.cmo: html.cmi lexer.cmo mathml.cmi parser.cmi render.cmo texutil.cmi util.cmo
 82+texvc.cmx: html.cmx lexer.cmx mathml.cmx parser.cmx render.cmx texutil.cmx util.cmx
 83+texvc_cgi.cmo: lexer.cmo parser.cmi render.cmo texutil.cmi util.cmo
 84+texvc_cgi.cmx: lexer.cmx parser.cmx render.cmx texutil.cmx util.cmx
 85+texvc_test.cmo: html.cmi lexer.cmo parser.cmi texutil.cmi util.cmo
 86+texvc_test.cmx: html.cmx lexer.cmx parser.cmx texutil.cmx util.cmx
 87+texvc_tex.cmo: lexer.cmo parser.cmi texutil.cmi util.cmo
 88+texvc_tex.cmx: lexer.cmx parser.cmx texutil.cmx util.cmx
Property changes on: trunk/extensions/Math/math/Makefile
___________________________________________________________________
Added: svn:keywords
189 + Author Date Id Revision
Added: svn:eol-style
290 + native
Index: trunk/extensions/Math/math/texutil.mli
@@ -0,0 +1,11 @@
 2+val render_tex : Tex.t -> string
 3+
 4+val set_encoding : string -> unit
 5+val tex_use_nonascii: unit -> unit
 6+val tex_use_ams: unit -> unit
 7+
 8+val get_preface : unit -> string
 9+val get_footer : unit -> string
 10+
 11+exception Illegal_tex_function of string
 12+val find: string -> Parser.token
Property changes on: trunk/extensions/Math/math/texutil.mli
___________________________________________________________________
Added: svn:keywords
113 + Author Date Id Revision
Added: svn:eol-style
214 + native
Property changes on: trunk/extensions/Math/math
___________________________________________________________________
Added: svn:ignore
315 + texvc
texvc_test
texvc_tex
*.cmi
*.cmx
*.mli
*~
Index: trunk/extensions/Math/Math.body.php
@@ -0,0 +1,348 @@
 2+<?php
 3+/**
 4+ * MediaWiki math extension
 5+ *
 6+ * (c) 2002-2011 Tomasz Wegrzanowski, Brion Vibber, and other MediaWiki contributors
 7+ * GPLv2 license; info in main package.
 8+ *
 9+ * Contain everything related to <math> </math> parsing
 10+ * @file
 11+ * @ingroup Parser
 12+ */
 13+
 14+/**
 15+ * Takes LaTeX fragments, sends them to a helper program (texvc) for rendering
 16+ * to rasterized PNG and HTML and MathML approximations. An appropriate
 17+ * rendering form is picked and returned.
 18+ *
 19+ * @author Tomasz Wegrzanowski, with additions by Brion Vibber (2003, 2004)
 20+ * @ingroup Parser
 21+ */
 22+class MathRenderer {
 23+ var $mode = MW_MATH_MODERN;
 24+ var $tex = '';
 25+ var $inputhash = '';
 26+ var $hash = '';
 27+ var $html = '';
 28+ var $mathml = '';
 29+ var $conservativeness = 0;
 30+
 31+ function __construct( $tex, $params=array() ) {
 32+ $this->tex = $tex;
 33+ $this->params = $params;
 34+ }
 35+
 36+ function setOutputMode( $mode ) {
 37+ $this->mode = $mode;
 38+ }
 39+
 40+ function render() {
 41+ global $wgTmpDirectory, $wgInputEncoding;
 42+ global $wgTexvc, $wgMathCheckFiles, $wgTexvcBackgroundColor;
 43+
 44+ if( $this->mode == MW_MATH_SOURCE ) {
 45+ # No need to render or parse anything more!
 46+ # New lines are replaced with spaces, which avoids confusing our parser (bugs 23190, 22818)
 47+ return ('<span class="tex" dir="ltr">$ ' . str_replace( "\n", " ", htmlspecialchars( $this->tex ) ) . ' $</span>');
 48+ }
 49+ if( $this->tex == '' ) {
 50+ return; # bug 8372
 51+ }
 52+
 53+ if( !$this->_recall() ) {
 54+ if( $wgMathCheckFiles ) {
 55+ # Ensure that the temp and output directories are available before continuing...
 56+ if( !file_exists( $wgTmpDirectory ) ) {
 57+ if( !wfMkdirParents( $wgTmpDirectory ) ) {
 58+ return $this->_error( 'math_bad_tmpdir' );
 59+ }
 60+ } elseif( !is_dir( $wgTmpDirectory ) || !is_writable( $wgTmpDirectory ) ) {
 61+ return $this->_error( 'math_bad_tmpdir' );
 62+ }
 63+ }
 64+
 65+ if( !is_executable( $wgTexvc ) ) {
 66+ return $this->_error( 'math_notexvc' );
 67+ }
 68+ $cmd = $wgTexvc . ' ' .
 69+ escapeshellarg( $wgTmpDirectory ).' '.
 70+ escapeshellarg( $wgTmpDirectory ).' '.
 71+ escapeshellarg( $this->tex ).' '.
 72+ escapeshellarg( $wgInputEncoding ).' '.
 73+ escapeshellarg( $wgTexvcBackgroundColor );
 74+
 75+ if ( wfIsWindows() ) {
 76+ # Invoke it within cygwin sh, because texvc expects sh features in its default shell
 77+ $cmd = 'sh -c ' . wfEscapeShellArg( $cmd );
 78+ }
 79+
 80+ wfDebug( "TeX: $cmd\n" );
 81+ $contents = wfShellExec( $cmd );
 82+ wfDebug( "TeX output:\n $contents\n---\n" );
 83+
 84+ if (strlen($contents) == 0) {
 85+ return $this->_error( 'math_unknown_error' );
 86+ }
 87+
 88+ $retval = substr ($contents, 0, 1);
 89+ $errmsg = '';
 90+ if (($retval == 'C') || ($retval == 'M') || ($retval == 'L')) {
 91+ if ($retval == 'C') {
 92+ $this->conservativeness = 2;
 93+ } else if ($retval == 'M') {
 94+ $this->conservativeness = 1;
 95+ } else {
 96+ $this->conservativeness = 0;
 97+ }
 98+ $outdata = substr ($contents, 33);
 99+
 100+ $i = strpos($outdata, "\000");
 101+
 102+ $this->html = substr($outdata, 0, $i);
 103+ $this->mathml = substr($outdata, $i+1);
 104+ } else if (($retval == 'c') || ($retval == 'm') || ($retval == 'l')) {
 105+ $this->html = substr ($contents, 33);
 106+ if ($retval == 'c') {
 107+ $this->conservativeness = 2;
 108+ } else if ($retval == 'm') {
 109+ $this->conservativeness = 1;
 110+ } else {
 111+ $this->conservativeness = 0;
 112+ }
 113+ $this->mathml = null;
 114+ } else if ($retval == 'X') {
 115+ $this->html = null;
 116+ $this->mathml = substr ($contents, 33);
 117+ $this->conservativeness = 0;
 118+ } else if ($retval == '+') {
 119+ $this->html = null;
 120+ $this->mathml = null;
 121+ $this->conservativeness = 0;
 122+ } else {
 123+ $errbit = htmlspecialchars( substr($contents, 1) );
 124+ switch( $retval ) {
 125+ case 'E':
 126+ $errmsg = $this->_error( 'math_lexing_error', $errbit );
 127+ break;
 128+ case 'S':
 129+ $errmsg = $this->_error( 'math_syntax_error', $errbit );
 130+ break;
 131+ case 'F':
 132+ $errmsg = $this->_error( 'math_unknown_function', $errbit );
 133+ break;
 134+ default:
 135+ $errmsg = $this->_error( 'math_unknown_error', $errbit );
 136+ }
 137+ }
 138+
 139+ if ( !$errmsg ) {
 140+ $this->hash = substr ($contents, 1, 32);
 141+ }
 142+
 143+ wfRunHooks( 'MathAfterTexvc', array( &$this, &$errmsg ) );
 144+
 145+ if ( $errmsg ) {
 146+ return $errmsg;
 147+ }
 148+
 149+ if (!preg_match("/^[a-f0-9]{32}$/", $this->hash)) {
 150+ return $this->_error( 'math_unknown_error' );
 151+ }
 152+
 153+ if( !file_exists( "$wgTmpDirectory/{$this->hash}.png" ) ) {
 154+ return $this->_error( 'math_image_error' );
 155+ }
 156+
 157+ if( filesize( "$wgTmpDirectory/{$this->hash}.png" ) == 0 ) {
 158+ return $this->_error( 'math_image_error' );
 159+ }
 160+
 161+ $hashpath = $this->_getHashPath();
 162+ if( !file_exists( $hashpath ) ) {
 163+ wfSuppressWarnings();
 164+ $ret = wfMkdirParents( $hashpath, 0755 );
 165+ wfRestoreWarnings();
 166+ if( !$ret ) {
 167+ return $this->_error( 'math_bad_output' );
 168+ }
 169+ } elseif( !is_dir( $hashpath ) || !is_writable( $hashpath ) ) {
 170+ return $this->_error( 'math_bad_output' );
 171+ }
 172+
 173+ if( !rename( "$wgTmpDirectory/{$this->hash}.png", "$hashpath/{$this->hash}.png" ) ) {
 174+ return $this->_error( 'math_output_error' );
 175+ }
 176+
 177+ # Now save it back to the DB:
 178+ if ( !wfReadOnly() ) {
 179+ $outmd5_sql = pack('H32', $this->hash);
 180+
 181+ $md5_sql = pack('H32', $this->md5); # Binary packed, not hex
 182+
 183+ $dbw = wfGetDB( DB_MASTER );
 184+ $dbw->replace( 'math', array( 'math_inputhash' ),
 185+ array(
 186+ 'math_inputhash' => $dbw->encodeBlob($md5_sql),
 187+ 'math_outputhash' => $dbw->encodeBlob($outmd5_sql),
 188+ 'math_html_conservativeness' => $this->conservativeness,
 189+ 'math_html' => $this->html,
 190+ 'math_mathml' => $this->mathml,
 191+ ), __METHOD__
 192+ );
 193+ }
 194+
 195+ // If we're replacing an older version of the image, make sure it's current.
 196+ global $wgUseSquid;
 197+ if ( $wgUseSquid ) {
 198+ $urls = array( $this->_mathImageUrl() );
 199+ $u = new SquidUpdate( $urls );
 200+ $u->doUpdate();
 201+ }
 202+ }
 203+
 204+ return $this->_doRender();
 205+ }
 206+
 207+ function _error( $msg, $append = '' ) {
 208+ $mf = htmlspecialchars( wfMsg( 'math_failure' ) );
 209+ $errmsg = htmlspecialchars( wfMsg( $msg ) );
 210+ $source = htmlspecialchars( str_replace( "\n", ' ', $this->tex ) );
 211+ return "<strong class='error'>$mf ($errmsg$append): $source</strong>\n";
 212+ }
 213+
 214+ function _recall() {
 215+ global $wgMathDirectory, $wgMathCheckFiles;
 216+
 217+ $this->md5 = md5( $this->tex );
 218+ $dbr = wfGetDB( DB_SLAVE );
 219+ $rpage = $dbr->selectRow( 'math',
 220+ array( 'math_outputhash','math_html_conservativeness','math_html','math_mathml' ),
 221+ array( 'math_inputhash' => $dbr->encodeBlob(pack("H32", $this->md5))), # Binary packed, not hex
 222+ __METHOD__
 223+ );
 224+
 225+ if( $rpage !== false ) {
 226+ # Tailing 0x20s can get dropped by the database, add it back on if necessary:
 227+ $xhash = unpack( 'H32md5', $dbr->decodeBlob($rpage->math_outputhash) . " " );
 228+ $this->hash = $xhash ['md5'];
 229+
 230+ $this->conservativeness = $rpage->math_html_conservativeness;
 231+ $this->html = $rpage->math_html;
 232+ $this->mathml = $rpage->math_mathml;
 233+
 234+ $filename = $this->_getHashPath() . "/{$this->hash}.png";
 235+
 236+ if( !$wgMathCheckFiles ) {
 237+ // Short-circuit the file existence & migration checks
 238+ return true;
 239+ }
 240+
 241+ if( file_exists( $filename ) ) {
 242+ if( filesize( $filename ) == 0 ) {
 243+ // Some horrible error corrupted stuff :(
 244+ wfSuppressWarnings();
 245+ unlink( $filename );
 246+ wfRestoreWarnings();
 247+ } else {
 248+ return true;
 249+ }
 250+ }
 251+
 252+ if( file_exists( $wgMathDirectory . "/{$this->hash}.png" ) ) {
 253+ $hashpath = $this->_getHashPath();
 254+
 255+ if( !file_exists( $hashpath ) ) {
 256+ wfSuppressWarnings();
 257+ $ret = wfMkdirParents( $hashpath, 0755 );
 258+ wfRestoreWarnings();
 259+ if( !$ret ) {
 260+ return false;
 261+ }
 262+ } elseif( !is_dir( $hashpath ) || !is_writable( $hashpath ) ) {
 263+ return false;
 264+ }
 265+ if ( function_exists( "link" ) ) {
 266+ return link ( $wgMathDirectory . "/{$this->hash}.png",
 267+ $hashpath . "/{$this->hash}.png" );
 268+ } else {
 269+ return rename ( $wgMathDirectory . "/{$this->hash}.png",
 270+ $hashpath . "/{$this->hash}.png" );
 271+ }
 272+ }
 273+
 274+ }
 275+
 276+ # Missing from the database and/or the render cache
 277+ return false;
 278+ }
 279+
 280+ /**
 281+ * Select among PNG, HTML, or MathML output depending on
 282+ */
 283+ function _doRender() {
 284+ if( $this->mode == MW_MATH_MATHML && $this->mathml != '' ) {
 285+ return Xml::tags( 'math',
 286+ $this->_attribs( 'math',
 287+ array( 'xmlns' => 'http://www.w3.org/1998/Math/MathML' ) ),
 288+ $this->mathml );
 289+ }
 290+ if (($this->mode == MW_MATH_PNG) || ($this->html == '') ||
 291+ (($this->mode == MW_MATH_SIMPLE) && ($this->conservativeness != 2)) ||
 292+ (($this->mode == MW_MATH_MODERN || $this->mode == MW_MATH_MATHML) && ($this->conservativeness == 0))) {
 293+ return $this->_linkToMathImage();
 294+ } else {
 295+ return Xml::tags( 'span',
 296+ $this->_attribs( 'span',
 297+ array( 'class' => 'texhtml',
 298+ 'dir' => 'ltr'
 299+ ) ),
 300+ $this->html );
 301+ }
 302+ }
 303+
 304+ function _attribs( $tag, $defaults=array(), $overrides=array() ) {
 305+ $attribs = Sanitizer::validateTagAttributes( $this->params, $tag );
 306+ $attribs = Sanitizer::mergeAttributes( $defaults, $attribs );
 307+ $attribs = Sanitizer::mergeAttributes( $attribs, $overrides );
 308+ return $attribs;
 309+ }
 310+
 311+ function _linkToMathImage() {
 312+ $url = $this->_mathImageUrl();
 313+
 314+ return Xml::element( 'img',
 315+ $this->_attribs(
 316+ 'img',
 317+ array(
 318+ 'class' => 'tex',
 319+ 'alt' => $this->tex ),
 320+ array(
 321+ 'src' => $url ) ) );
 322+ }
 323+
 324+ function _mathImageUrl() {
 325+ global $wgMathPath;
 326+ $dir = $this->_getHashSubPath();
 327+ return "$wgMathPath/$dir/{$this->hash}.png";
 328+ }
 329+
 330+ function _getHashPath() {
 331+ global $wgMathDirectory;
 332+ $path = $wgMathDirectory .'/' . $this->_getHashSubPath();
 333+ wfDebug( "TeX: getHashPath, hash is: $this->hash, path is: $path\n" );
 334+ return $path;
 335+ }
 336+
 337+ function _getHashSubPath() {
 338+ return substr($this->hash, 0, 1)
 339+ .'/'. substr($this->hash, 1, 1)
 340+ .'/'. substr($this->hash, 2, 1);
 341+ }
 342+
 343+ public static function renderMath( $tex, $params=array(), ParserOptions $parserOptions = null ) {
 344+ $math = new MathRenderer( $tex, $params );
 345+ if ( $parserOptions )
 346+ $math->setOutputMode( $parserOptions->getMath() );
 347+ return $math->render();
 348+ }
 349+}
Property changes on: trunk/extensions/Math/Math.body.php
___________________________________________________________________
Added: svn:keywords
1350 + Author Date Id Revision
Added: svn:eol-style
2351 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r85723Math extension:...ashley15:13, 9 April 2011
r85724...and remove the math-related messages from MessagesEn.php; follow-up to r85723ashley15:18, 9 April 2011
r85727Rebuild of Math messages previously in core.siebrand17:14, 9 April 2011
r85728Follow-up r85724: update messages.inc and rebuild all language files.siebrand17:21, 9 April 2011
r85735Followup to r85706 and friends: now that Math messages have been moved to ext...brion19:57, 9 April 2011
r94206Add Math to make-wmf-branch...reedy22:24, 10 August 2011

Comments

#Comment by 😂 (talk | contribs)   00:50, 9 April 2011

I love you.

#Comment by Reedy (talk | contribs)   01:40, 9 April 2011

I'm guessing the language files need carefully stripping of math stuff too...

#Comment by Brion VIBBER (talk | contribs)   19:10, 9 April 2011

Siebrand, can you clarify what warrants "fixme" status? Messages need migration, but this is supplementary work (started in r85723), not repair of a regression. If there's anything else not mentioned above, please make sure you explicitly call it out so it can be found and fixed.

#Comment by Siebrand (talk | contribs)   20:04, 9 April 2011

I marked it fixme, indeed because of the incomplete migration - primarily i18n. As this was done earlier today, I set it back to new.

#Comment by Brion VIBBER (talk | contribs)   20:46, 9 April 2011

Thanks!

#Comment by Happy-melon (talk | contribs)   10:00, 12 April 2011

\o/ Go Brion!!

#Comment by Bryan (talk | contribs)   19:03, 30 June 2011

We should really ship this extension with the tarball to avoid breaking existing installations imho.

Status & tagging log