PageSourceSearch

https://costrice.github.io/vminer/static/js/LaTeXMathML.js

js costrice.github.io collected 2026-10-03 08:49:54 UTC 115,872 bytes, 2,368 lines download raw bytes

1/*
2LaTeXMathML.js
3==============
4
5This file, in this form, is due to Douglas Woodall, June 2006.
6It contains JavaScript functions to convert (most simple) LaTeX
7math notation to Presentation MathML.  It was obtained by
8downloading the file ASCIIMathML.js from
9	http://www1.chapman.edu/~jipsen/mathml/asciimathdownload/
10and modifying it so that it carries out ONLY those conversions
11that would be carried out in LaTeX.  A description of the original
12file, with examples, can be found at
13	www1.chapman.edu/~jipsen/mathml/asciimath.html
14	ASCIIMathML: Math on the web for everyone
15
16Here is the header notice from the original file:
17
18ASCIIMathML.js
19==============
20This file contains JavaScript functions to convert ASCII math notation
21to Presentation MathML. The conversion is done while the (X)HTML page
22loads, and should work with Firefox/Mozilla/Netscape 7+ and Internet
23Explorer 6+MathPlayer (http://www.dessci.com/en/products/mathplayer/).
24Just add the next line to your (X)HTML page with this file in the same folder:
25<script type="text/javascript" src="ASCIIMathML.js"></script>
26This is a convenient and inexpensive solution for authoring MathML.
27
28Version 1.4.7 Dec 15, 2005, (c) Peter Jipsen http://www.chapman.edu/~jipsen
29Latest version at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML.js
30For changes see http://www.chapman.edu/~jipsen/mathml/asciimathchanges.txt
31If you use it on a webpage, please send the URL to [email protected]
32
33This program is free software; you can redistribute it and/or modify
34it under the terms of the GNU General Public License as published by
35the Free Software Foundation; either version 2 of the License, or (at
36your option) any later version.
37
38This program is distributed in the hope that it will be useful,
39but WITHOUT ANY WARRANTY; without even the implied warranty of
40MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41General Public License (at http://www.gnu.org/copyleft/gpl.html)
42for more details.
43
44LaTeXMathML.js (ctd)
45==============
46
47The instructions for use are the same as for the original
48ASCIIMathML.js, except that of course the line you add to your
49file should be
50<script type="text/javascript" src="LaTeXMathML.js"></script>
51Or use absolute path names if the file is not in the same folder
52as your (X)HTML page.
53*/
54
55var checkForMathML = true;   // check if browser can display MathML
56var notifyIfNoMathML = true; // display note if no MathML capability
57var alertIfNoMathML = false;  // show alert box if no MathML capability
58// was "red":
59var mathcolor = "";	     // change it to "" (to inherit) or any other color
60// was "serif":
61var mathfontfamily = "";      // change to "" to inherit (works in IE)
62                              // or another family (e.g. "arial")
63var showasciiformulaonhover = true; // helps students learn ASCIIMath
64/*
65// Commented out by DRW -- not now used -- see DELIMITERS (twice) near the end
66var displaystyle = false;     // puts limits above and below large operators
67var decimalsign = ".";        // change to "," if you like, beware of `(1,2)`!
68var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters
69var AMdelimiter2 = "$", AMescape2 = "\\\\\\$", AMdelimiter2regexp = "\\$";
70var doubleblankmathdelimiter = false; // if true,  x+1  is equal to `x+1`
71                                      // for IE this works only in <!--   -->
72//var separatetokens;// has been removed (email me if this is a problem)
73*/
74var isIE = document.createElementNS==null;
75
76if (document.getElementById==null)
77  alert("This webpage requires a recent browser such as \nMozilla/Netscape 7+ or Internet Explorer 6+MathPlayer")
78
79// all further global variables start with "AM"
80
81function AMcreateElementXHTML(t) {
82  if (isIE) return document.createElement(t);
83  else return document.createElementNS("http://www.w3.org/1999/xhtml",t);
84}
85
86function AMnoMathMLNote() {
87  var nd = AMcreateElementXHTML("h3");
88  nd.setAttribute("align","center")
89  nd.appendChild(AMcreateElementXHTML("p"));
90  nd.appendChild(document.createTextNode("To view the "));
91  var an = AMcreateElementXHTML("a");
92  an.appendChild(document.createTextNode("LaTeXMathML"));
93  an.setAttribute("href","http://www.maths.nott.ac.uk/personal/drw/lm.html");
94  nd.appendChild(an);
95  nd.appendChild(document.createTextNode(" notation use Internet Explorer 6+"));
96  an = AMcreateElementXHTML("a");
97  an.appendChild(document.createTextNode("MathPlayer"));
98  an.setAttribute("href","http://www.dessci.com/en/products/mathplayer/download.htm");
99  nd.appendChild(an);
100  nd.appendChild(document.createTextNode(" or Netscape/Mozilla/Firefox"));
101  nd.appendChild(AMcreateElementXHTML("p"));
102  return nd;
103}
104
105function AMisMathMLavailable() {
106  if (navigator.appName.slice(0,8)=="Netscape")
107    if (navigator.appVersion.slice(0,1)>="5") return null;
108    else return AMnoMathMLNote();
109  else if (navigator.appName.slice(0,9)=="Microsoft")
110    try {
111        var ActiveX = new ActiveXObject("MathPlayer.Factory.1");
112        return null;
113    } catch (e) {
114        return AMnoMathMLNote();
115    }
116  else return AMnoMathMLNote();
117}
118
119// character lists for Mozilla/Netscape fonts
120var AMcal = ["\uD835\uDC9C", "\uD835\uDC9D", "\uD835\uDC9E", "\uD835\uDC9F", "\uD835\uDCA0", "\uD835\uDCA1", "\uD835\uDCA2", "\uD835\uDCA3", "\uD835\uDCA4", "\uD835\uDCA5", "\uD835\uDCA6", "\uD835\uDCA7", "\uD835\uDCA8", "\uD835\uDCA9", "\uD835\uDCAA", "\uD835\uDCAB", "\uD835\uDCAC", "\uD835\uDCAD", "\uD835\uDCAE", "\uD835\uDCAF", "\uD835\uDCB0", "\uD835\uDCB1", "\uD835\uDCB2", "\uD835\uDCB3", "\uD835\uDCB4", "\uD835\uDCB5"];
121var AMfrk = ["\uD835\uDD04", "\uD835\uDD05", "\uD835\uDD06", "\uD835\uDD07", "\uD835\uDD08", "\uD835\uDD09", "\uD835\uDD0A", "\uD835\uDD0B", "\uD835\uDD0C", "\uD835\uDD0D", "\uD835\uDD0E", "\uD835\uDD0F", "\uD835\uDD10", "\uD835\uDD11", "\uD835\uDD12", "\uD835\uDD13", "\uD835\uDD14", "\uD835\uDD15", "\uD835\uDD16", "\uD835\uDD17", "\uD835\uDD18", "\uD835\uDD19", "\uD835\uDD1A", "\uD835\uDD1B", "\uD835\uDD1C", "\uD835\uDD1D"];
122var AMbbb = ["\uD835\uDD38", "\uD835\uDD39", "\uD835\uDD3A", "\uD835\uDD3B", "\uD835\uDD3C", "\uD835\uDD3D", "\uD835\uDD3E", "\uD835\uDD3F", "\uD835\uDD40", "\uD835\uDD41", "\uD835\uDD42", "\uD835\uDD43", "\uD835\uDD44", "\uD835\uDD45", "\uD835\uDD46", "\uD835\uDD47", "\uD835\uDD48", "\uD835\uDD49", "\uD835\uDD4A", "\uD835\uDD4B", "\uD835\uDD4C", "\uD835\uDD4D", "\uD835\uDD4E", "\uD835\uDD4F", "\uD835\uDD50", "\uD835\uDD51"];
123
124var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,
125    RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,
126    TEXT = 9, BIG = 10, LONG = 11, STRETCHY = 12, MATRIX = 13; // token types
127
128var AMsqrt = {input:"\\sqrt",	tag:"msqrt", output:"sqrt",	ttype:UNARY},
129  AMnot = {input:"\\not",	tag:"mnot", output:"not",	ttype:UNARY},
130  AMroot = {input:"\\root",	tag:"mroot", output:"root",	ttype:BINARY},
131  AMfrac = {input:"\\frac",	tag:"mfrac", output:"/",	ttype:BINARY},
132  AMover = {input:"\\stackrel", tag:"mover", output:"stackrel", ttype:BINARY},
133  AMatop = {input:"\\atop",	tag:"mfrac", output:"",		ttype:INFIX},
134  AMchoose = {input:"\\choose", tag:"mfrac", output:"",		ttype:INFIX},
135  AMsub  = {input:"_",		tag:"msub",  output:"_",	ttype:INFIX},
136  AMsup  = {input:"^",		tag:"msup",  output:"^",	ttype:INFIX},
137  AMtext = {input:"\\mathrm",	tag:"mtext", output:"text",	ttype:TEXT},
138  AMmbox = {input:"\\mbox",	tag:"mtext", output:"mbox",	ttype:TEXT};
139
140// Commented out by DRW to prevent 1/2 turning into a 2-line fraction
141// AMdiv   = {input:"/",	 tag:"mfrac", output:"/",    ttype:INFIX},
142// Commented out by DRW so that " prints literally in equations
143// AMquote = {input:"\"",	 tag:"mtext", output:"mbox", ttype:TEXT};
144
145// List of negations obtained from http://frodo.elon.edu/tutorial/tutorial.pdf
146var AMRelationNegations = {
147  "\u003C":"\u226E", "\u003E":"\u226F", "\u2264":"\u2270", "\u2265":"\u2271",
148  "\u003D":"\u2260", "\u2261":"\u2262", "\u227A":"\u2280", "\u227B":"\u2281",
149  "\u227C":"\u22E0", "\u227D":"\u22E1", "\u223C":"\u2241", "\u2243":"\u2244",
150  "\u2282":"\u2284", "\u2283":"\u2285", "\u2286":"\u2288", "\u2287":"\u2289",
151  "\u2248":"\u2249", "\u2245":"\u2247", "\u2291":"\u22E2", "\u2292":"\u22E3",
152  "\u224D":"\u226D"
153}
154
155var AMsymbols = [
156//Greek letters
157{input:"\\alpha",	tag:"mi", output:"\u03B1", ttype:CONST},
158{input:"\\beta",	tag:"mi", output:"\u03B2", ttype:CONST},
159{input:"\\gamma",	tag:"mi", output:"\u03B3", ttype:CONST},
160{input:"\\delta",	tag:"mi", output:"\u03B4", ttype:CONST},
161{input:"\\epsilon",	tag:"mi", output:"\u03B5", ttype:CONST},
162{input:"\\varepsilon",  tag:"mi", output:"\u025B", ttype:CONST},
163{input:"\\zeta",	tag:"mi", output:"\u03B6", ttype:CONST},
164{input:"\\eta",		tag:"mi", output:"\u03B7", ttype:CONST},
165{input:"\\theta",	tag:"mi", output:"\u03B8", ttype:CONST},
166{input:"\\vartheta",	tag:"mi", output:"\u03D1", ttype:CONST},
167{input:"\\iota",	tag:"mi", output:"\u03B9", ttype:CONST},
168{input:"\\kappa",	tag:"mi", output:"\u03BA", ttype:CONST},
169{input:"\\lambda",	tag:"mi", output:"\u03BB", ttype:CONST},
170{input:"\\mu",		tag:"mi", output:"\u03BC", ttype:CONST},
171{input:"\\nu",		tag:"mi", output:"\u03BD", ttype:CONST},
172{input:"\\xi",		tag:"mi", output:"\u03BE", ttype:CONST},
173{input:"\\pi",		tag:"mi", output:"\u03C0", ttype:CONST},
174{input:"\\varpi",	tag:"mi", output:"\u03D6", ttype:CONST},
175{input:"\\rho",		tag:"mi", output:"\u03C1", ttype:CONST},
176{input:"\\varrho",	tag:"mi", output:"\u03F1", ttype:CONST},
177{input:"\\varsigma",	tag:"mi", output:"\u03C2", ttype:CONST},
178{input:"\\sigma",	tag:"mi", output:"\u03C3", ttype:CONST},
179{input:"\\tau",		tag:"mi", output:"\u03C4", ttype:CONST},
180{input:"\\upsilon",	tag:"mi", output:"\u03C5", ttype:CONST},
181{input:"\\phi",		tag:"mi", output:"\u03C6", ttype:CONST},
182{input:"\\varphi",	tag:"mi", output:"\u03D5", ttype:CONST},
183{input:"\\chi",		tag:"mi", output:"\u03C7", ttype:CONST},
184{input:"\\psi",		tag:"mi", output:"\u03C8", ttype:CONST},
185{input:"\\omega",	tag:"mi", output:"\u03C9", ttype:CONST},
186{input:"\\Gamma",	tag:"mo", output:"\u0393", ttype:CONST},
187{input:"\\Delta",	tag:"mo", output:"\u0394", ttype:CONST},
188{input:"\\Theta",	tag:"mo", output:"\u0398", ttype:CONST},
189{input:"\\Lambda",	tag:"mo", output:"\u039B", ttype:CONST},
190{input:"\\Xi",		tag:"mo", output:"\u039E", ttype:CONST},
191{input:"\\Pi",		tag:"mo", output:"\u03A0", ttype:CONST},
192{input:"\\Sigma",	tag:"mo", output:"\u03A3", ttype:CONST},
193{input:"\\Upsilon",	tag:"mo", output:"\u03A5", ttype:CONST},
194{input:"\\Phi",		tag:"mo", output:"\u03A6", ttype:CONST},
195{input:"\\Psi",		tag:"mo", output:"\u03A8", ttype:CONST},
196{input:"\\Omega",	tag:"mo", output:"\u03A9", ttype:CONST},
197
198//fractions
199{input:"\\frac12",	tag:"mo", output:"\u00BD", ttype:CONST},
200{input:"\\frac14",	tag:"mo", output:"\u00BC", ttype:CONST},
201{input:"\\frac34",	tag:"mo", output:"\u00BE", ttype:CONST},
202{input:"\\frac13",	tag:"mo", output:"\u2153", ttype:CONST},
203{input:"\\frac23",	tag:"mo", output:"\u2154", ttype:CONST},
204{input:"\\frac15",	tag:"mo", output:"\u2155", ttype:CONST},
205{input:"\\frac25",	tag:"mo", output:"\u2156", ttype:CONST},
206{input:"\\frac35",	tag:"mo", output:"\u2157", ttype:CONST},
207{input:"\\frac45",	tag:"mo", output:"\u2158", ttype:CONST},
208{input:"\\frac16",	tag:"mo", output:"\u2159", ttype:CONST},
209{input:"\\frac56",	tag:"mo", output:"\u215A", ttype:CONST},
210{input:"\\frac18",	tag:"mo", output:"\u215B", ttype:CONST},
211{input:"\\frac38",	tag:"mo", output:"\u215C", ttype:CONST},
212{input:"\\frac58",	tag:"mo", output:"\u215D", ttype:CONST},
213{input:"\\frac78",	tag:"mo", output:"\u215E", ttype:CONST},
214
215//binary operation symbols
216{input:"\\pm",		tag:"mo", output:"\u00B1", ttype:CONST},
217{input:"\\mp",		tag:"mo", output:"\u2213", ttype:CONST},
218{input:"\\triangleleft",tag:"mo", output:"\u22B2", ttype:CONST},
219{input:"\\triangleright",tag:"mo",output:"\u22B3", ttype:CONST},
220{input:"\\cdot",	tag:"mo", output:"\u22C5", ttype:CONST},
221{input:"\\star",	tag:"mo", output:"\u22C6", ttype:CONST},
222{input:"\\ast",		tag:"mo", output:"\u002A", ttype:CONST},
223{input:"\\times",	tag:"mo", output:"\u00D7", ttype:CONST},
224{input:"\\div",		tag:"mo", output:"\u00F7", ttype:CONST},
225{input:"\\circ",	tag:"mo", output:"\u2218", ttype:CONST},
226//{input:"\\bullet",	  tag:"mo", output:"\u2219", ttype:CONST},
227{input:"\\bullet",	tag:"mo", output:"\u2022", ttype:CONST},
228{input:"\\oplus",	tag:"mo", output:"\u2295", ttype:CONST},
229{input:"\\ominus",	tag:"mo", output:"\u2296", ttype:CONST},
230{input:"\\otimes",	tag:"mo", output:"\u2297", ttype:CONST},
231{input:"\\bigcirc",	tag:"mo", output:"\u25CB", ttype:CONST},
232{input:"\\oslash",	tag:"mo", output:"\u2298", ttype:CONST},
233{input:"\\odot",	tag:"mo", output:"\u2299", ttype:CONST},
234{input:"\\land",	tag:"mo", output:"\u2227", ttype:CONST},
235{input:"\\wedge",	tag:"mo", output:"\u2227", ttype:CONST},
236{input:"\\lor",		tag:"mo", output:"\u2228", ttype:CONST},
237{input:"\\vee",		tag:"mo", output:"\u2228", ttype:CONST},
238{input:"\\cap",		tag:"mo", output:"\u2229", ttype:CONST},
239{input:"\\cup",		tag:"mo", output:"\u222A", ttype:CONST},
240{input:"\\sqcap",	tag:"mo", output:"\u2293", ttype:CONST},
241{input:"\\sqcup",	tag:"mo", output:"\u2294", ttype:CONST},
242{input:"\\uplus",	tag:"mo", output:"\u228E", ttype:CONST},
243{input:"\\amalg",	tag:"mo", output:"\u2210", ttype:CONST},
244{input:"\\bigtriangleup",tag:"mo",output:"\u25B3", ttype:CONST},
245{input:"\\bigtriangledown",tag:"mo",output:"\u25BD", ttype:CONST},
246{input:"\\dag",		tag:"mo", output:"\u2020", ttype:CONST},
247{input:"\\dagger",	tag:"mo", output:"\u2020", ttype:CONST},
248{input:"\\ddag",	tag:"mo", output:"\u2021", ttype:CONST},
249{input:"\\ddagger",	tag:"mo", output:"\u2021", ttype:CONST},
250{input:"\\lhd",		tag:"mo", output:"\u22B2", ttype:CONST},
251{input:"\\rhd",		tag:"mo", output:"\u22B3", ttype:CONST},
252{input:"\\unlhd",	tag:"mo", output:"\u22B4", ttype:CONST},
253{input:"\\unrhd",	tag:"mo", output:"\u22B5", ttype:CONST},
254
255
256//BIG Operators
257{input:"\\sum",		tag:"mo", output:"\u2211", ttype:UNDEROVER},
258{input:"\\prod",	tag:"mo", output:"\u220F", ttype:UNDEROVER},
259{input:"\\bigcap",	tag:"mo", output:"\u22C2", ttype:UNDEROVER},
260{input:"\\bigcup",	tag:"mo", output:"\u22C3", ttype:UNDEROVER},
261{input:"\\bigwedge",	tag:"mo", output:"\u22C0", ttype:UNDEROVER},
262{input:"\\bigvee",	tag:"mo", output:"\u22C1", ttype:UNDEROVER},
263{input:"\\bigsqcap",	tag:"mo", output:"\u2A05", ttype:UNDEROVER},
264{input:"\\bigsqcup",	tag:"mo", output:"\u2A06", ttype:UNDEROVER},
265{input:"\\coprod",	tag:"mo", output:"\u2210", ttype:UNDEROVER},
266{input:"\\bigoplus",	tag:"mo", output:"\u2A01", ttype:UNDEROVER},
267{input:"\\bigotimes",	tag:"mo", output:"\u2A02", ttype:UNDEROVER},
268{input:"\\bigodot",	tag:"mo", output:"\u2A00", ttype:UNDEROVER},
269{input:"\\biguplus",	tag:"mo", output:"\u2A04", ttype:UNDEROVER},
270{input:"\\int",		tag:"mo", output:"\u222B", ttype:CONST},
271{input:"\\oint",	tag:"mo", output:"\u222E", ttype:CONST},
272
273//binary relation symbols
274{input:":=",		tag:"mo", output:":=",	   ttype:CONST},
275{input:"\\lt",		tag:"mo", output:"<",	   ttype:CONST},
276{input:"\\gt",		tag:"mo", output:">",	   ttype:CONST},
277{input:"\\ne",		tag:"mo", output:"\u2260", ttype:CONST},
278{input:"\\neq",		tag:"mo", output:"\u2260", ttype:CONST},
279{input:"\\le",		tag:"mo", output:"\u2264", ttype:CONST},
280{input:"\\leq",		tag:"mo", output:"\u2264", ttype:CONST},
281{input:"\\leqslant",	tag:"mo", output:"\u2264", ttype:CONST},
282{input:"\\ge",		tag:"mo", output:"\u2265", ttype:CONST},
283{input:"\\geq",		tag:"mo", output:"\u2265", ttype:CONST},
284{input:"\\geqslant",	tag:"mo", output:"\u2265", ttype:CONST},
285{input:"\\equiv",	tag:"mo", output:"\u2261", ttype:CONST},
286{input:"\\ll",		tag:"mo", output:"\u226A", ttype:CONST},
287{input:"\\gg",		tag:"mo", output:"\u226B", ttype:CONST},
288{input:"\\doteq",	tag:"mo", output:"\u2250", ttype:CONST},
289{input:"\\prec",	tag:"mo", output:"\u227A", ttype:CONST},
290{input:"\\succ",	tag:"mo", output:"\u227B", ttype:CONST},
291{input:"\\preceq",	tag:"mo", output:"\u227C", ttype:CONST},
292{input:"\\succeq",	tag:"mo", output:"\u227D", ttype:CONST},
293{input:"\\subset",	tag:"mo", output:"\u2282", ttype:CONST},
294{input:"\\supset",	tag:"mo", output:"\u2283", ttype:CONST},
295{input:"\\subseteq",	tag:"mo", output:"\u2286", ttype:CONST},
296{input:"\\supseteq",	tag:"mo", output:"\u2287", ttype:CONST},
297{input:"\\subsetneq",	tag:"mo", output:"\u228A", ttype:CONST},
298{input:"\\supsetneq",	tag:"mo", output:"\u228B", ttype:CONST},
299{input:"\\sqsubset",	tag:"mo", output:"\u228F", ttype:CONST},
300{input:"\\sqsupset",	tag:"mo", output:"\u2290", ttype:CONST},
301{input:"\\sqsubseteq",  tag:"mo", output:"\u2291", ttype:CONST},
302{input:"\\sqsupseteq",  tag:"mo", output:"\u2292", ttype:CONST},
303{input:"\\sim",		tag:"mo", output:"\u223C", ttype:CONST},
304{input:"\\simeq",	tag:"mo", output:"\u2243", ttype:CONST},
305{input:"\\approx",	tag:"mo", output:"\u2248", ttype:CONST},
306{input:"\\cong",	tag:"mo", output:"\u2245", ttype:CONST},
307{input:"\\Join",	tag:"mo", output:"\u22C8", ttype:CONST},
308{input:"\\bowtie",	tag:"mo", output:"\u22C8", ttype:CONST},
309{input:"\\in",		tag:"mo", output:"\u2208", ttype:CONST},
310{input:"\\ni",		tag:"mo", output:"\u220B", ttype:CONST},
311{input:"\\owns",	tag:"mo", output:"\u220B", ttype:CONST},
312{input:"\\propto",	tag:"mo", output:"\u221D", ttype:CONST},
313{input:"\\vdash",	tag:"mo", output:"\u22A2", ttype:CONST},
314{input:"\\dashv",	tag:"mo", output:"\u22A3", ttype:CONST},
315{input:"\\models",	tag:"mo", output:"\u22A8", ttype:CONST},
316{input:"\\perp",	tag:"mo", output:"\u22A5", ttype:CONST},
317{input:"\\smile",	tag:"mo", output:"\u2323", ttype:CONST},
318{input:"\\frown",	tag:"mo", output:"\u2322", ttype:CONST},
319{input:"\\asymp",	tag:"mo", output:"\u224D", ttype:CONST},
320{input:"\\notin",	tag:"mo", output:"\u2209", ttype:CONST},
321
322//matrices
323{input:"\\begin{eqnarray}",	output:"X",	ttype:MATRIX, invisible:true},
324{input:"\\begin{array}",	output:"X",	ttype:MATRIX, invisible:true},
325{input:"\\\\",			output:"}&{",	ttype:DEFINITION},
326{input:"\\end{eqnarray}",	output:"}}",	ttype:DEFINITION},
327{input:"\\end{array}",		output:"}}",	ttype:DEFINITION},
328
329//grouping and literal brackets -- ieval is for IE
330{input:"\\big",	   tag:"mo", output:"X", atval:"1.2", ieval:"2.2", ttype:BIG},
331{input:"\\Big",	   tag:"mo", output:"X", atval:"1.6", ieval:"2.6", ttype:BIG},
332{input:"\\bigg",   tag:"mo", output:"X", atval:"2.2", ieval:"3.2", ttype:BIG},
333{input:"\\Bigg",   tag:"mo", output:"X", atval:"2.9", ieval:"3.9", ttype:BIG},
334{input:"\\left",   tag:"mo", output:"X", ttype:LEFTBRACKET},
335{input:"\\right",  tag:"mo", output:"X", ttype:RIGHTBRACKET},
336{input:"{",	   output:"{", ttype:LEFTBRACKET,  invisible:true},
337{input:"}",	   output:"}", ttype:RIGHTBRACKET, invisible:true},
338
339{input:"(",	   tag:"mo", output:"(",      atval:"1", ttype:STRETCHY},
340{input:"[",	   tag:"mo", output:"[",      atval:"1", ttype:STRETCHY},
341{input:"\\lbrack", tag:"mo", output:"[",      atval:"1", ttype:STRETCHY},
342{input:"\\{",	   tag:"mo", output:"{",      atval:"1", ttype:STRETCHY},
343{input:"\\lbrace", tag:"mo", output:"{",      atval:"1", ttype:STRETCHY},
344{input:"\\langle", tag:"mo", output:"\u2329", atval:"1", ttype:STRETCHY},
345{input:"\\lfloor", tag:"mo", output:"\u230A", atval:"1", ttype:STRETCHY},
346{input:"\\lceil",  tag:"mo", output:"\u2308", atval:"1", ttype:STRETCHY},
347
348// rtag:"mi" causes space to be inserted before a following sin, cos, etc.
349// (see function AMparseExpr() )
350{input:")",	  tag:"mo",output:")",	    rtag:"mi",atval:"1",ttype:STRETCHY},
351{input:"]",	  tag:"mo",output:"]",	    rtag:"mi",atval:"1",ttype:STRETCHY},
352{input:"\\rbrack",tag:"mo",output:"]",	    rtag:"mi",atval:"1",ttype:STRETCHY},
353{input:"\\}",	  tag:"mo",output:"}",	    rtag:"mi",atval:"1",ttype:STRETCHY},
354{input:"\\rbrace",tag:"mo",output:"}",	    rtag:"mi",atval:"1",ttype:STRETCHY},
355{input:"\\rangle",tag:"mo",output:"\u232A", rtag:"mi",atval:"1",ttype:STRETCHY},
356{input:"\\rfloor",tag:"mo",output:"\u230B", rtag:"mi",atval:"1",ttype:STRETCHY},
357{input:"\\rceil", tag:"mo",output:"\u2309", rtag:"mi",atval:"1",ttype:STRETCHY},
358
359// "|", "\\|", "\\vert" and "\\Vert" modified later: lspace = rspace = 0em
360{input:"|",		tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},
361{input:"\\|",		tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},
362{input:"\\vert",	tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},
363{input:"\\Vert",	tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},
364{input:"\\mid",		tag:"mo", output:"\u2223", atval:"1", ttype:STRETCHY},
365{input:"\\parallel",	tag:"mo", output:"\u2225", atval:"1", ttype:STRETCHY},
366{input:"/",		tag:"mo", output:"/",	atval:"1.01", ttype:STRETCHY},
367{input:"\\backslash",	tag:"mo", output:"\u2216", atval:"1", ttype:STRETCHY},
368{input:"\\setminus",	tag:"mo", output:"\\",	   ttype:CONST},
369
370//miscellaneous symbols
371{input:"\\!",	  tag:"mspace", atname:"width", atval:"-0.167em", ttype:SPACE},
372{input:"\\,",	  tag:"mspace", atname:"width", atval:"0.167em", ttype:SPACE},
373{input:"\\>",	  tag:"mspace", atname:"width", atval:"0.222em", ttype:SPACE},
374{input:"\\:",	  tag:"mspace", atname:"width", atval:"0.222em", ttype:SPACE},
375{input:"\\;",	  tag:"mspace", atname:"width", atval:"0.278em", ttype:SPACE},
376{input:"~",	  tag:"mspace", atname:"width", atval:"0.333em", ttype:SPACE},
377{input:"\\quad",  tag:"mspace", atname:"width", atval:"1em", ttype:SPACE},
378{input:"\\qquad", tag:"mspace", atname:"width", atval:"2em", ttype:SPACE},
379//{input:"{}",		  tag:"mo", output:"\u200B", ttype:CONST}, // zero-width
380{input:"\\prime",	tag:"mo", output:"\u2032", ttype:CONST},
381{input:"'",		tag:"mo", output:"\u02B9", ttype:CONST},
382{input:"''",		tag:"mo", output:"\u02BA", ttype:CONST},
383{input:"'''",		tag:"mo", output:"\u2034", ttype:CONST},
384{input:"''''",		tag:"mo", output:"\u2057", ttype:CONST},
385{input:"\\ldots",	tag:"mo", output:"\u2026", ttype:CONST},
386{input:"\\cdots",	tag:"mo", output:"\u22EF", ttype:CONST},
387{input:"\\vdots",	tag:"mo", output:"\u22EE", ttype:CONST},
388{input:"\\ddots",	tag:"mo", output:"\u22F1", ttype:CONST},
389{input:"\\forall",	tag:"mo", output:"\u2200", ttype:CONST},
390{input:"\\exists",	tag:"mo", output:"\u2203", ttype:CONST},
391{input:"\\Re",		tag:"mo", output:"\u211C", ttype:CONST},
392{input:"\\Im",		tag:"mo", output:"\u2111", ttype:CONST},
393{input:"\\aleph",	tag:"mo", output:"\u2135", ttype:CONST},
394{input:"\\hbar",	tag:"mo", output:"\u210F", ttype:CONST},
395{input:"\\ell",		tag:"mo", output:"\u2113", ttype:CONST},
396{input:"\\wp",		tag:"mo", output:"\u2118", ttype:CONST},
397{input:"\\emptyset",	tag:"mo", output:"\u2205", ttype:CONST},
398{input:"\\infty",	tag:"mo", output:"\u221E", ttype:CONST},
399{input:"\\surd",	tag:"mo", output:"\\sqrt{}", ttype:DEFINITION},
400{input:"\\partial",	tag:"mo", output:"\u2202", ttype:CONST},
401{input:"\\nabla",	tag:"mo", output:"\u2207", ttype:CONST},
402{input:"\\triangle",	tag:"mo", output:"\u25B3", ttype:CONST},
403{input:"\\therefore",	tag:"mo", output:"\u2234", ttype:CONST},
404{input:"\\angle",	tag:"mo", output:"\u2220", ttype:CONST},
405//{input:"\\\\ ",	  tag:"mo", output:"\u00A0", ttype:CONST},
406{input:"\\diamond",	tag:"mo", output:"\u22C4", ttype:CONST},
407//{input:"\\Diamond",	  tag:"mo", output:"\u25CA", ttype:CONST},
408{input:"\\Diamond",	tag:"mo", output:"\u25C7", ttype:CONST},
409{input:"\\neg",		tag:"mo", output:"\u00AC", ttype:CONST},
410{input:"\\lnot",	tag:"mo", output:"\u00AC", ttype:CONST},
411{input:"\\bot",		tag:"mo", output:"\u22A5", ttype:CONST},
412{input:"\\top",		tag:"mo", output:"\u22A4", ttype:CONST},
413{input:"\\square",	tag:"mo", output:"\u25AB", ttype:CONST},
414{input:"\\Box",		tag:"mo", output:"\u25A1", ttype:CONST},
415{input:"\\wr",		tag:"mo", output:"\u2240", ttype:CONST},
416
417//standard functions
418//Note UNDEROVER *must* have tag:"mo" to work properly
419{input:"\\arccos", tag:"mi", output:"arccos", ttype:UNARY, func:true},
420{input:"\\arcsin", tag:"mi", output:"arcsin", ttype:UNARY, func:true},
421{input:"\\arctan", tag:"mi", output:"arctan", ttype:UNARY, func:true},
422{input:"\\arg",	   tag:"mi", output:"arg",    ttype:UNARY, func:true},
423{input:"\\cos",	   tag:"mi", output:"cos",    ttype:UNARY, func:true},
424{input:"\\cosh",   tag:"mi", output:"cosh",   ttype:UNARY, func:true},
425{input:"\\cot",	   tag:"mi", output:"cot",    ttype:UNARY, func:true},
426{input:"\\coth",   tag:"mi", output:"coth",   ttype:UNARY, func:true},
427{input:"\\csc",	   tag:"mi", output:"csc",    ttype:UNARY, func:true},
428{input:"\\deg",	   tag:"mi", output:"deg",    ttype:UNARY, func:true},
429{input:"\\det",	   tag:"mi", output:"det",    ttype:UNARY, func:true},
430{input:"\\dim",	   tag:"mi", output:"dim",    ttype:UNARY, func:true}, //CONST?
431{input:"\\exp",	   tag:"mi", output:"exp",    ttype:UNARY, func:true},
432{input:"\\gcd",	   tag:"mi", output:"gcd",    ttype:UNARY, func:true}, //CONST?
433{input:"\\hom",	   tag:"mi", output:"hom",    ttype:UNARY, func:true},
434{input:"\\inf",	      tag:"mo", output:"inf",	 ttype:UNDEROVER},
435{input:"\\ker",	   tag:"mi", output:"ker",    ttype:UNARY, func:true},
436{input:"\\lg",	   tag:"mi", output:"lg",     ttype:UNARY, func:true},
437{input:"\\lim",	      tag:"mo", output:"lim",	 ttype:UNDEROVER},
438{input:"\\liminf",    tag:"mo", output:"liminf", ttype:UNDEROVER},
439{input:"\\limsup",    tag:"mo", output:"limsup", ttype:UNDEROVER},
440{input:"\\ln",	   tag:"mi", output:"ln",     ttype:UNARY, func:true},
441{input:"\\log",	   tag:"mi", output:"log",    ttype:UNARY, func:true},
442{input:"\\max",	      tag:"mo", output:"max",	 ttype:UNDEROVER},
443{input:"\\min",	      tag:"mo", output:"min",	 ttype:UNDEROVER},
444{input:"\\Pr",	   tag:"mi", output:"Pr",     ttype:UNARY, func:true},
445{input:"\\sec",	   tag:"mi", output:"sec",    ttype:UNARY, func:true},
446{input:"\\sin",	   tag:"mi", output:"sin",    ttype:UNARY, func:true},
447{input:"\\sinh",   tag:"mi", output:"sinh",   ttype:UNARY, func:true},
448{input:"\\sup",	      tag:"mo", output:"sup",	 ttype:UNDEROVER},
449{input:"\\tan",	   tag:"mi", output:"tan",    ttype:UNARY, func:true},
450{input:"\\tanh",   tag:"mi", output:"tanh",   ttype:UNARY, func:true},
451
452//arrows
453{input:"\\gets",		tag:"mo", output:"\u2190", ttype:CONST},
454{input:"\\leftarrow",		tag:"mo", output:"\u2190", ttype:CONST},
455{input:"\\to",			tag:"mo", output:"\u2192", ttype:CONST},
456{input:"\\rightarrow",		tag:"mo", output:"\u2192", ttype:CONST},
457{input:"\\leftrightarrow",	tag:"mo", output:"\u2194", ttype:CONST},
458{input:"\\uparrow",		tag:"mo", output:"\u2191", ttype:CONST},
459{input:"\\downarrow",		tag:"mo", output:"\u2193", ttype:CONST},
460{input:"\\updownarrow",		tag:"mo", output:"\u2195", ttype:CONST},
461{input:"\\Leftarrow",		tag:"mo", output:"\u21D0", ttype:CONST},
462{input:"\\Rightarrow",		tag:"mo", output:"\u21D2", ttype:CONST},
463{input:"\\Leftrightarrow",	tag:"mo", output:"\u21D4", ttype:CONST},
464{input:"\\iff", tag:"mo", output:"~\\Longleftrightarrow~", ttype:DEFINITION},
465{input:"\\Uparrow",		tag:"mo", output:"\u21D1", ttype:CONST},
466{input:"\\Downarrow",		tag:"mo", output:"\u21D3", ttype:CONST},
467{input:"\\Updownarrow",		tag:"mo", output:"\u21D5", ttype:CONST},
468{input:"\\mapsto",		tag:"mo", output:"\u21A6", ttype:CONST},
469{input:"\\longleftarrow",	tag:"mo", output:"\u2190", ttype:LONG},
470{input:"\\longrightarrow",	tag:"mo", output:"\u2192", ttype:LONG},
471{input:"\\longleftrightarrow",	tag:"mo", output:"\u2194", ttype:LONG},
472{input:"\\Longleftarrow",	tag:"mo", output:"\u21D0", ttype:LONG},
473{input:"\\Longrightarrow",	tag:"mo", output:"\u21D2", ttype:LONG},
474{input:"\\Longleftrightarrow",  tag:"mo", output:"\u21D4", ttype:LONG},
475{input:"\\longmapsto",		tag:"mo", output:"\u21A6", ttype:CONST},
476							// disaster if LONG
477
478//commands with argument
479AMsqrt, AMnot, AMroot, AMfrac, AMover, AMsub, AMsup, AMtext, AMmbox, AMatop, AMchoose,
480
481//AMdiv, AMquote,
482
483//diacritical marks
484{input:"\\acute",	tag:"mover",  output:"\u00B4", ttype:UNARY, acc:true},
485//{input:"\\acute",	  tag:"mover",  output:"\u0317", ttype:UNARY, acc:true},
486//{input:"\\acute",	  tag:"mover",  output:"\u0301", ttype:UNARY, acc:true},
487//{input:"\\grave",	  tag:"mover",  output:"\u0300", ttype:UNARY, acc:true},
488//{input:"\\grave",	  tag:"mover",  output:"\u0316", ttype:UNARY, acc:true},
489{input:"\\grave",	tag:"mover",  output:"\u0060", ttype:UNARY, acc:true},
490{input:"\\breve",	tag:"mover",  output:"\u02D8", ttype:UNARY, acc:true},
491{input:"\\check",	tag:"mover",  output:"\u02C7", ttype:UNARY, acc:true},
492{input:"\\dot",		tag:"mover",  output:".",      ttype:UNARY, acc:true},
493{input:"\\ddot",	tag:"mover",  output:"..",     ttype:UNARY, acc:true},
494//{input:"\\ddot",	  tag:"mover",  output:"\u00A8", ttype:UNARY, acc:true},
495{input:"\\mathring",	tag:"mover",  output:"\u00B0", ttype:UNARY, acc:true},
496{input:"\\vec",		tag:"mover",  output:"\u20D7", ttype:UNARY, acc:true},
497{input:"\\overrightarrow",tag:"mover",output:"\u20D7", ttype:UNARY, acc:true},
498{input:"\\overleftarrow",tag:"mover", output:"\u20D6", ttype:UNARY, acc:true},
499{input:"\\hat",		tag:"mover",  output:"\u005E", ttype:UNARY, acc:true},
500{input:"\\widehat",	tag:"mover",  output:"\u0302", ttype:UNARY, acc:true},
501{input:"\\tilde",	tag:"mover",  output:"~",      ttype:UNARY, acc:true},
502//{input:"\\tilde",	  tag:"mover",  output:"\u0303", ttype:UNARY, acc:true},
503{input:"\\widetilde",	tag:"mover",  output:"\u02DC", ttype:UNARY, acc:true},
504{input:"\\bar",		tag:"mover",  output:"\u203E", ttype:UNARY, acc:true},
505{input:"\\overbrace",	tag:"mover",  output:"\uFE37", ttype:UNARY, acc:true}, //Changed unicode overbrace
506{input:"\\overbracket", tag:"mover",  output:"\u23B4", ttype:UNARY, acc:true}, //old overbrace = overbracket
507{input:"\\overline",	tag:"mover",  output:"\u00AF", ttype:UNARY, acc:true},
508{input:"\\underbrace",  tag:"munder", output:"\uFE38", ttype:UNARY, acc:true}, //Changed unicode underbrace
509{input:"\\underbracket",tag:"munder", output:"\u23B5", ttype:UNARY, acc:true}, //old underbrace = underbracket
510{input:"\\underline",	tag:"munder", output:"\u00AF", ttype:UNARY, acc:true},
511//{input
511:"underline",	tag:"munder", output:"\u0332", ttype:UNARY, acc:true},
512
513//typestyles and fonts
514{input:"\\displaystyle",tag:"mstyle",atname:"displaystyle",atval:"true", ttype:UNARY},
515{input:"\\textstyle",tag:"mstyle",atname:"displaystyle",atval:"false", ttype:UNARY},
516{input:"\\scriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"1", ttype:UNARY},
517{input:"\\scriptscriptstyle",tag:"mstyle",atname:"scriptlevel",atval:"2", ttype:UNARY},
518{input:"\\textrm", tag:"mstyle", output:"\\mathrm", ttype: DEFINITION},
519{input:"\\mathbf", tag:"mstyle", atname:"mathvariant", atval:"bold", ttype:UNARY},
520{input:"\\textbf", tag:"mstyle", atname:"mathvariant", atval:"bold", ttype:UNARY},
521{input:"\\mathit", tag:"mstyle", atname:"mathvariant", atval:"italic", ttype:UNARY},
522{input:"\\textit", tag:"mstyle", atname:"mathvariant", atval:"italic", ttype:UNARY},
523{input:"\\mathtt", tag:"mstyle", atname:"mathvariant", atval:"monospace", ttype:UNARY},
524{input:"\\texttt", tag:"mstyle", atname:"mathvariant", atval:"monospace", ttype:UNARY},
525{input:"\\mathsf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", ttype:UNARY},
526{input:"\\mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", ttype:UNARY, codes:AMbbb},
527{input:"\\mathcal",tag:"mstyle", atname:"mathvariant", atval:"script", ttype:UNARY, codes:AMcal},
528{input:"\\mathfrak",tag:"mstyle",atname:"mathvariant", atval:"fraktur",ttype:UNARY, codes:AMfrk},
529{input:"\\textcolor",tag:"mstyle",atname:"mathvariant", atval:"mathcolor", ttype:BINARY},
530{input:"\\colorbox",tag:"mstyle",atname:"mathvariant", atval:"background", ttype:BINARY}
531];
532
533function compareNames(s1,s2) {
534  if (s1.input > s2.input) return 1
535  else return -1;
536}
537
538var AMnames = []; //list of input symbols
539
540function AMinitSymbols() {
541  AMsymbols.sort(compareNames);
542  for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;
543}
544
545var AMmathml = "http://www.w3.org/1998/Math/MathML";
546
547function AMcreateElementMathML(t) {
548  if (isIE) return document.createElement("m:"+t);
549  else return document.createElementNS(AMmathml,t);
550}
551
552function AMcreateMmlNode(t,frag) {
553//  var node = AMcreateElementMathML(name);
554  if (isIE) var node = document.createElement("m:"+t);
555  else var node = document.createElementNS(AMmathml,t);
556  node.appendChild(frag);
557  return node;
558}
559
560function newcommand(oldstr,newstr) {
561  AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr,
562                                 ttype:DEFINITION}]);
563}
564
565function AMremoveCharsAndBlanks(str,n) {
566//remove n characters and any following blanks
567  var st;
568  st = str.slice(n);
569  for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);
570  return st.slice(i);
571}
572
573function AMposition(arr, str, n) {
574// return position >=n where str appears or would be inserted
575// assumes arr is sorted
576  if (n==0) {
577    var h,m;
578    n = -1;
579    h = arr.length;
580    while (n+1<h) {
581      m = (n+h) >> 1;
582      if (arr[m]<str) n = m; else h = m;
583    }
584    return h;
585  } else
586    for (var i=n; i<arr.length && arr[i]<str; i++);
587  return i; // i=arr.length || arr[i]>=str
588}
589
590function AMgetSymbol(str) {
591//return maximal initial substring of str that appears in names
592//return null if there is none
593  var k = 0; //new pos
594  var j = 0; //old pos
595  var mk; //match pos
596  var st;
597  var tagst;
598  var match = "";
599  var more = true;
600  for (var i=1; i<=str.length && more; i++) {
601    st = str.slice(0,i); //initial substring of length i
602    j = k;
603    k = AMposition(AMnames, st, j);
604    if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){
605      match = AMnames[k];
606      mk = k;
607      i = match.length;
608    }
609    more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];
610  }
611  AMpreviousSymbol=AMcurrentSymbol;
612  if (match!=""){
613    AMcurrentSymbol=AMsymbols[mk].ttype;
614    return AMsymbols[mk];
615  }
616  AMcurrentSymbol=CONST;
617  k = 1;
618  st = str.slice(0,1); //take 1 character
619  if ("0"<=st && st<="9") tagst = "mn";
620  else tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");
621/*
622// Commented out by DRW (not fully understood, but probably to do with
623// use of "/" as an INFIX version of "\\frac", which we don't want):
624//}
625//if (st=="-" && AMpreviousSymbol==INFIX) {
626//  AMcurrentSymbol = INFIX;  //trick "/" into recognizing "-" on second parse
627//  return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};
628//}
629*/
630  return {input:st, tag:tagst, output:st, ttype:CONST};
631}
632
633
634/*Parsing ASCII math expressions with the following grammar
635v ::= [A-Za-z] | greek letters | numbers | other constant symbols
636u ::= sqrt | text | bb | other unary symbols for font commands
637b ::= frac | root | stackrel	binary symbols
638l ::= { | \left			left brackets
639r ::= } | \right		right brackets
640S ::= v | lEr | uS | bSS	Simple expression
641I ::= S_S | S^S | S_S^S | S	Intermediate expression
642E ::= IE | I/I			Expression
643Each terminal symbol is translated into a corresponding mathml node.*/
644
645var AMpreviousSymbol,AMcurrentSymbol;
646
647function AMparseSexpr(str) { //parses str and returns [node,tailstr,(node)tag]
648  var symbol, node, result, result2, i, st,// rightvert = false,
649    newFrag = document.createDocumentFragment();
650  str = AMremoveCharsAndBlanks(str,0);
651  symbol = AMgetSymbol(str);             //either a token or a bracket or empty
652  if (symbol == null || symbol.ttype == RIGHTBRACKET)
653    return [null,str,null];
654  if (symbol.ttype == DEFINITION) {
655    str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length);
656    symbol = AMgetSymbol(str);
657    if (symbol == null || symbol.ttype == RIGHTBRACKET)
658      return [null,str,null];
659  }
660  str = AMremoveCharsAndBlanks(str,symbol.input.length);
661  switch (symbol.ttype) {
662  case SPACE:
663    node = AMcreateElementMathML(symbol.tag);
664    node.setAttribute(symbol.atname,symbol.atval);
665    return [node,str,symbol.tag];
666  case UNDEROVER:
667    if (isIE) {
668      if (symbol.input.substr(0,4) == "\\big") {   // botch for missing symbols
669	str = "\\"+symbol.input.substr(4)+str;	   // make \bigcup = \cup etc.
670	symbol = AMgetSymbol(str);
671	symbol.ttype = UNDEROVER;
672	str = AMremoveCharsAndBlanks(str,symbol.input.length);
673      }
674    }
675    return [AMcreateMmlNode(symbol.tag,
676			document.createTextNode(symbol.output)),str,symbol.tag];
677  case CONST:
678    var output = symbol.output;
679    if (isIE) {
680      if (symbol.input == "'")
681	output = "\u2032";
682      else if (symbol.input == "''")
683	output = "\u2033";
684      else if (symbol.input == "'''")
685	output = "\u2033\u2032";
686      else if (symbol.input == "''''")
687	output = "\u2033\u2033";
688      else if (symbol.input == "\\square")
689	output = "\u25A1";	// same as \Box
690      else if (symbol.input.substr(0,5) == "\\frac") {
691						// botch for missing fractions
692	var denom = symbol.input.substr(6,1);
693	if (denom == "5" || denom == "6") {
694	  str = symbol.input.replace(/\\frac/,"\\frac ")+str;
695	  return [node,str,symbol.tag];
696	}
697      }
698    }
699    node = AMcreateMmlNode(symbol.tag,document.createTextNode(output));
700    return [node,str,symbol.tag];
701  case LONG:  // added by DRW
702    node = AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));
703    node.setAttribute("minsize","1.5");
704    node.setAttribute("maxsize","1.5");
705    node = AMcreateMmlNode("mover",node);
706    node.appendChild(AMcreateElementMathML("mspace"));
707    return [node,str,symbol.tag];
708  case STRETCHY:  // added by DRW
709    if (isIE && symbol.input == "\\backslash")
710	symbol.output = "\\";	// doesn't expand, but then nor does "\u2216"
711    node = AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));
712    if (symbol.input == "|" || symbol.input == "\\vert" ||
713	symbol.input == "\\|" || symbol.input == "\\Vert") {
714	  node.setAttribute("lspace","0em");
715	  node.setAttribute("rspace","0em");
716    }
717    node.setAttribute("maxsize",symbol.atval);  // don't allow to stretch here
718    if (symbol.rtag != null)
719      return [node,str,symbol.rtag];
720    else
721      return [node,str,symbol.tag];
722  case BIG:  // added by DRW
723    var atval = symbol.atval;
724    if (isIE)
725      atval = symbol.ieval;
726    symbol = AMgetSymbol(str);
727    if (symbol == null)
728	return [null,str,null];
729    str = AMremoveCharsAndBlanks(str,symbol.input.length);
730    node = AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output));
731    if (isIE) {		// to get brackets to expand
732      var space = AMcreateElementMathML("mspace");
733      space.setAttribute("height",atval+"ex");
734      node = AMcreateMmlNode("mrow",node);
735      node.appendChild(space);
736    } else {		// ignored in IE
737      node.setAttribute("minsize",atval);
738      node.setAttribute("maxsize",atval);
739    }
740    return [node,str,symbol.tag];
741  case LEFTBRACKET:   //read (expr+)
742    if (symbol.input == "\\left") { // left what?
743      symbol = AMgetSymbol(str);
744      if (symbol != null) {
745	if (symbol.input == ".")
746	  symbol.invisible = true;
747	str = AMremoveCharsAndBlanks(str,symbol.input.length);
748      }
749    }
750    result = AMparseExpr(str,true,false);
751    if (symbol==null ||
752	(typeof symbol.invisible == "boolean" && symbol.invisible))
753      node = AMcreateMmlNode("mrow",result[0]);
754    else {
755      node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));
756      node = AMcreateMmlNode("mrow",node);
757      node.appendChild(result[0]);
758    }
759    return [node,result[1],result[2]];
760  case MATRIX:	 //read (expr+)
761    if (symbol.input == "\\begin{array}") {
762      var mask = "";
763      symbol = AMgetSymbol(str);
764      str = AMremoveCharsAndBlanks(str,0);
765      if (symbol == null)
766	mask = "l";
767      else {
768	str = AMremoveCharsAndBlanks(str,symbol.input.length);
769	if (symbol.input != "{")
770	  mask = "l";
771	else do {
772	  symbol = AMgetSymbol(str);
773	  if (symbol != null) {
774	    str = AMremoveCharsAndBlanks(str,symbol.input.length);
775	    if (symbol.input != "}")
776	      mask = mask+symbol.input;
777	  }
778	} while (symbol != null && symbol.input != "" && symbol.input != "}");
779      }
780      result = AMparseExpr("{"+str,true,true);
781//    if (result[0]==null) return [AMcreateMmlNode("mo",
782//			   document.createTextNode(symbol.input)),str];
783      node = AMcreateMmlNode("mtable",result[0]);
784      mask = mask.replace(/l/g,"left ");
785      mask = mask.replace(/r/g,"right ");
786      mask = mask.replace(/c/g,"center ");
787      node.setAttribute("columnalign",mask);
788      node.setAttribute("displaystyle","false");
789      if (isIE)
790	return [node,result[1],null];
791// trying to get a *little* bit of space around the array
792// (IE already includes it)
793      var lspace = AMcreateElementMathML("mspace");
794      lspace.setAttribute("width","0.167em");
795      var rspace = AMcreateElementMathML("mspace");
796      rspace.setAttribute("width","0.167em");
797      var node1 = AMcreateMmlNode("mrow",lspace);
798      node1.appendChild(node);
799      node1.appendChild(rspace);
800      return [node1,result[1],null];
801    } else {	// eqnarray
802      result = AMparseExpr("{"+str,true,true);
803      node = AMcreateMmlNode("mtable",result[0]);
804      if (isIE)
805	node.setAttribute("columnspacing","0.25em"); // best in practice?
806      else
807	node.setAttribute("columnspacing","0.167em"); // correct (but ignored?)
808      node.setAttribute("columnalign","right center left");
809      node.setAttribute("displaystyle","true");
810      node = AMcreateMmlNode("mrow",node);
811      return [node,result[1],null];
812    }
813  case TEXT:
814      if (str.charAt(0)=="{") i=str.indexOf("}");
815      else i = 0;
816      if (i==-1)
817		 i = str.length;
818      st = str.slice(1,i);
819      if (st.charAt(0) == " ") {
820	node = AMcreateElementMathML("mspace");
821	node.setAttribute("width","0.33em");	// was 1ex
822	newFrag.appendChild(node);
823      }
824      newFrag.appendChild(
825        AMcreateMmlNode(symbol.tag,document.createTextNode(st)));
826      if (st.charAt(st.length-1) == " ") {
827	node = AMcreateElementMathML("mspace");
828	node.setAttribute("width","0.33em");	// was 1ex
829	newFrag.appendChild(node);
830      }
831      str = AMremoveCharsAndBlanks(str,i+1);
832      return [AMcreateMmlNode("mrow",newFrag),str,null];
833  case UNARY:
834      result = AMparseSexpr(str);
835      if (result[0]==null) return [AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str];
836      if (typeof symbol.func == "boolean" && symbol.func) { // functions hack
837		st = str.charAt(0);
838//		if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {
839		if (st=="^" || st=="_" || st==",") {
840		  return [AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)),str,symbol.tag];
841        } else {
842		  node = AMcreateMmlNode("mrow",AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));
843	  	  if (isIE) {
844	        var space = AMcreateElementMathML("mspace");
845	    	space.setAttribute("width","0.167em");
846	    	node.appendChild(space);
847	  	  }
848	  	  node.appendChild(result[0]);
849	  	  return [node,result[1],symbol.tag];
850        }
851      }
852      if (symbol.input == "\\sqrt") {		// sqrt
853	     if (isIE) {	// set minsize, for \surd
854	        var space = AMcreateElementMathML("mspace");
855	        space.setAttribute("height","1.2ex");
856	        space.setAttribute("width","0em");	// probably no effect
857	        node = AMcreateMmlNode(symbol.tag,result[0])
858//	        node.setAttribute("minsize","1");	// ignored
859//         	node = AMcreateMmlNode("mrow",node);  // hopefully unnecessary
860	  		node.appendChild(space);
861	  		return [node,result[1],symbol.tag];
862		} else
863		  return [AMcreateMmlNode(symbol.tag,result[0]),result[1],symbol.tag];
864      } else if (typeof symbol.acc == "boolean" && symbol.acc) {   // accent
865  	      node = AMcreateMmlNode(symbol.tag,result[0]);
866	      var output = symbol.output;
867		  if (isIE) {
868			if (symbol.input == "\\hat")
869				output = "\u0302";
870			else if (symbol.input == "\\widehat")
871				output = "\u005E";
872			else if (symbol.input == "\\bar")
873				output = "\u00AF";
874			else if (symbol.input == "\\grave")
875				output = "\u0300";
876			else if (symbol.input == "\\tilde")
877				output = "\u0303";
878		}
879		var node1 = AMcreateMmlNode("mo",document.createTextNode(output));
880		if (symbol.input == "\\vec" || symbol.input == "\\check")
881						// don't allow to stretch
882		    node1.setAttribute("maxsize","1.2");
883		 // why doesn't "1" work?  \vec nearly disappears in firefox
884		if (isIE && symbol.input == "\\bar")
885	    node1.setAttribute("maxsize","0.5");
886		if (symbol.input == "\\underbrace" || symbol.input == "\\underline")
887		  node1.setAttribute("accentunder","true");
888		else
889		  node1.setAttribute("accent","true");
890		node.appendChild(node1);
891		if (symbol.input == "\\overbrace" || symbol.input == "\\underbrace")
892		  node.ttype = UNDEROVER;
893		return [node,result[1],symbol.tag];
894	   } else if (symbol.input == "\\not") {		// not
895        // added by infinity0 on 2009-12-15 to implement \not command
896        text = result[0].childNodes[0].nodeValue;
897        if (typeof text == "string" && text.length == 1 && text in AMRelationNegations) {
898          result[0].childNodes[0].nodeValue = AMRelationNegations[text];
899          return [AMcreateMmlNode(symbol.tag,result[0]),result[1],symbol.tag];
900        }
901        return [AMcreateMmlNode("mo",document.createTextNode("\\")),"not " + str,symbol.tag];
902      } else {			      // font change or displaystyle command
903        if (!isIE && typeof symbol.codes != "undefined") {
904          for (i=0; i<result[0].childNodes.length; i++)
905            if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {
906              st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:
907                              result[0].childNodes[i].firstChild.nodeValue);
908              var newst = [];
909              for (var j=0; j<st.length; j++)
910                if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91)
911				{  newst = newst + symbol.codes[st.charCodeAt(j)-65] }
912                   // String.fromCharCode(symbol.internal[st.charCodeAt(j)-65]); alert(newst); }
913                else newst = newst + st.charAt(j);
914              if (result[0].nodeName=="mi")
915                result[0]=AMcreateElementMathML("mo").
916                          appendChild(document.createTextNode(newst));
917              else result[0].replaceChild(AMcreateElementMathML("mo").
918          appendChild(document.createTextNode(newst)),result[0].childNodes[i]);
919            }
920        }
921        node = AMcreateMmlNode(symbol.tag,result[0]);
922        node.setAttribute(symbol.atname,symbol.atval);
923	if (symbol.input == "\\scriptstyle" ||
924	    symbol.input == "\\scriptscriptstyle")
925		node.setAttribute("displaystyle","false");
926	return [node,result[1],symbol.tag];
927      }
928  case BINARY:
929    result = AMparseSexpr(str);
930    if (result[0]==null) return [AMcreateMmlNode("mo",document.createTextNode(symbol.input)),str,null];
931    result2 = AMparseSexpr(result[1]);
932    if (result2[0]==null) return [AMcreateMmlNode("mo",document.createTextNode(symbol.input)),str,null];
933    //added by J. Knisley to allow \textcolor and \colorbox within equations
934    if (symbol.input=="\\textcolor" || symbol.input=="\\colorbox") {
935      var tclr = str.match(/\{\s*([#\w]+)\s*\}/); //get's color from beginning of str
936      str = str.replace(/\{\s*[#\w]+\s*\}/,"");
937      if(tclr!=null) {
938         if(IsColorName.test(tclr[1].toLowerCase())) {
939   	       tclr=LaTeXColor[tclr[1].toLowerCase()];
940         } else {
941           tclr=tclr[1]; // no checking for valid color!!
942         }
943         node = AMcreateElementMathML("mstyle");
944         node.setAttribute(symbol.atval,tclr);
945         node.appendChild(result2[0]);
946         return [node,result2[1],symbol.tag];
947      }
948    }
949    if (symbol.input=="\\root" || symbol.input=="\\stackrel") newFrag.appendChild(result2[0]);
950    newFrag.appendChild(result[0]);
951    if (symbol.input=="\\frac") newFrag.appendChild(result2[0]);
952    return [AMcreateMmlNode(symbol.tag,newFrag),result2[1],symbol.tag];
953  case INFIX:
954    str = AMremoveCharsAndBlanks(str,symbol.input.length);
955    return [AMcreateMmlNode("mo",document.createTextNode(symbol.output)),
956	str,symbol.tag];
957  default:
958    return [AMcreateMmlNode(symbol.tag,        //its a constant
959	document.createTextNode(symbol.output)),str,symbol.tag];
960  }
961}
962
963function AMparseIexpr(str) {
964  var symbol, sym1, sym2, node, result, tag, underover;
965  str = AMremoveCharsAndBlanks(str,0);
966  sym1 = AMgetSymbol(str);
967  result = AMparseSexpr(str);
968  node = result[0];
969  str = result[1];
970  tag = result[2];
971  symbol = AMgetSymbol(str);
972  if (symbol.ttype == INFIX) {
973    str = AMremoveCharsAndBlanks(str,symbol.input.length);
974    result = AMparseSexpr(str);
975    if (result[0] == null) // show box in place of missing argument
976      result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1"));
977    str = result[1];
978    tag = result[2];
979    if (symbol.input == "_" || symbol.input == "^") {
980      sym2 = AMgetSymbol(str);
981      tag = null;	// no space between x^2 and a following sin, cos, etc.
982// This is for \underbrace and \overbrace
983      underover = ((sym1.ttype == UNDEROVER) || (node.ttype == UNDEROVER));
984//    underover = (sym1.ttype == UNDEROVER);
985      if (symbol.input == "_" && sym2.input == "^") {
986        str = AMremoveCharsAndBlanks(str,sym2.input.length);
987        var res2 = AMparseSexpr(str);
988	str = res2[1];
989	tag = res2[2];  // leave space between x_1^2 and a following sin etc.
990        node = AMcreateMmlNode((underover?"munderover":"msubsup"),node);
991        node.appendChild(result[0]);
992        node.appendChild(res2[0]);
993      } else if (symbol.input == "_") {
994	node = AMcreateMmlNode((underover?"munder":"msub"),node);
995        node.appendChild(result[0]);
996      } else {
997	node = AMcreateMmlNode((underover?"mover":"msup"),node);
998        node.appendChild(result[0]);
999      }
1000      node = AMcreateMmlNode("mrow",node); // so sum does not stretch
1001    } else {
1002      node = AMcreateMmlNode(symbol.tag,node);
1003      if (symbol.input == "\\atop" || symbol.input == "\\choose")
1004	node.setAttribute("linethickness","0ex");
1005      node.appendChild(result[0]);
1006      if (symbol.input == "\\choose")
1007	node = AMcreateMmlNode("mfenced",node);
1008    }
1009  }
1010  return [node,str,tag];
1011}
1012
1013function AMparseExpr(str,rightbracket,matrix) {
1014  var symbol, node, result, i, tag,
1015  newFrag = document.createDocumentFragment();
1016  do {
1017    str = AMremoveCharsAndBlanks(str,0);
1018    result = AMparseIexpr(str);
1019    node = result[0];
1020    str = result[1];
1021    tag = result[2];
1022    symbol = AMgetSymbol(str);
1023    if (node!=undefined) {
1024      if ((tag == "mn" || tag == "mi") && symbol!=null &&
1025	typeof symbol.func == "boolean" && symbol.func) {
1026			// Add space before \sin in 2\sin x or x\sin x
1027	  var space = AMcreateElementMathML("mspace");
1028	  space.setAttribute("width","0.167em");
1029	  node = AMcreateMmlNode("mrow",node);
1030	  node.appendChild(space);
1031      }
1032      newFrag.appendChild(node);
1033    }
1034  } while ((symbol.ttype != RIGHTBRACKET)
1035        && symbol!=null && symbol.output!="");
1036  tag = null;
1037  if (symbol.ttype == RIGHTBRACKET) {
1038    if (symbol.input == "\\right") { // right what?
1039      str = AMremoveCharsAndBlanks(str,symbol.input.length);
1040      symbol = AMgetSymbol(str);
1041      if (symbol != null && symbol.input == ".")
1042	symbol.invisible = true;
1043      if (symbol != null)
1044	tag = symbol.rtag;
1045    }
1046    if (symbol!=null)
1047      str = AMremoveCharsAndBlanks(str,symbol.input.length); // ready to return
1048    var len = newFrag.childNodes.length;
1049    if (matrix &&
1050      len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&
1051      newFrag.childNodes[len-2].nodeName == "mo" &&
1052      newFrag.childNodes[len-2].firstChild.nodeValue == "&") { //matrix
1053	var pos = []; // positions of ampersands
1054        var m = newFrag.childNodes.length;
1055        for (i=0; matrix && i<m; i=i+2) {
1056          pos[i] = [];
1057          node = newFrag.childNodes[i];
1058	  for (var j=0; j<node.childNodes.length; j++)
1059	    if (node.childNodes[j].firstChild.nodeValue=="&")
1060	      pos[i][pos[i].length]=j;
1061        }
1062	var row, frag, n, k, table = document.createDocumentFragment();
1063	for (i=0; i<m; i=i+2) {
1064	  row = document.createDocumentFragment();
1065	  frag = document.createDocumentFragment();
1066	  node = newFrag.firstChild; // <mrow> -&-&...&-&- </mrow>
1066
1067	  n = node.childNodes.length;
1068	  k = 0;
1069	  for (j=0; j<n; j++) {
1070	    if (typeof pos[i][k] != "undefined" && j==pos[i][k]){
1071	      node.removeChild(node.firstChild); //remove &
1072	      row.appendChild(AMcreateMmlNode("mtd",frag));
1073	      k++;
1074	    } else frag.appendChild(node.firstChild);
1075	  }
1076	  row.appendChild(AMcreateMmlNode("mtd",frag));
1077	  if (newFrag.childNodes.length>2) {
1078	    newFrag.removeChild(newFrag.firstChild); //remove <mrow> </mrow>
1079	    newFrag.removeChild(newFrag.firstChild); //remove <mo>&</mo>
1080	  }
1081	  table.appendChild(AMcreateMmlNode("mtr",row));
1082	}
1083	return [table,str];
1084    }
1085    if (typeof symbol.invisible != "boolean" || !symbol.invisible) {
1086      node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));
1087      newFrag.appendChild(node);
1088    }
1089  }
1090  return [newFrag,str,tag];
1091}
1092
1093function AMparseMath(str) {
1094  var result, node = AMcreateElementMathML("mstyle");
1095  //added by J. Knisley to allow limited implementation of \color
1096  var cclr = str.match(/\\color\s*\{\s*([#\w]+)\s*\}/);
1097  str = str.replace(/\\color\s*\{\s*[#\w]+\s*\}/g,"");
1098  if(cclr!=null) {
1099     if(IsColorName.test(cclr[1].toLowerCase())) {
1100   	    cclr=LaTeXColor[cclr[1].toLowerCase()];
1101     } else {
1102        cclr=cclr[1]; // no checking for valid color!!
1103     }
1104     node.setAttribute("mathcolor",cclr);
1105  } else {
1106    if (mathcolor != "") node.setAttribute("mathcolor",mathcolor);
1107  };
1108  if (mathfontfamily != "") node.setAttribute("fontfamily",mathfontfamily);
1109  node.appendChild(AMparseExpr(str.replace(/^\s+/g,""),false,false)[0]);
1110  node = AMcreateMmlNode("math",node);
1111  if (showasciiformulaonhover)                      //fixed by djhsu so newline
1112    node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko
1113  if (false ) { //&& mathfontfamily != "" && (isIE || mathfontfamily != "serif")) {
1114    var fnode = AMcreateElementXHTML("font");
1115    fnode.setAttribute("face",mathfontfamily);
1116    fnode.appendChild(node);
1117    return fnode;
1118  }
1119  return node;
1120}
1121
1122function AMstrarr2docFrag(arr, linebreaks) {
1123  var newFrag=document.createDocumentFragment();
1124  var expr = false;
1125  for (var i=0; i<arr.length; i++) {
1126    if (expr) newFrag.appendChild(AMparseMath(arr[i]));
1127    else {
1128      var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);
1129      newFrag.appendChild(AMcreateElementXHTML("span").
1130      appendChild(document.createTextNode(arri[0])));
1131      for (var j=1; j<arri.length; j++) {
1132        newFrag.appendChild(AMcreateElementXHTML("p"));
1133        newFrag.appendChild(AMcreateElementXHTML("span").
1134        appendChild(document.createTextNode(arri[j])));
1135      }
1136    }
1137    expr = !expr;
1138  }
1139  return newFrag;
1140}
1141
1142function AMprocessNodeR(n, linebreaks) {
1143  var mtch, str, arr, frg, i;
1144  if (n.childNodes.length == 0) {
1145   if ((n.nodeType!=8 || linebreaks) &&
1146    n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&
1147    n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" &&
1148    n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE") {
1149    str = n.nodeValue;
1150    if (!(str == null)) {
1151      str = str.replace(/\r\n\r\n/g,"\n\n");
1152      str = str.replace(/\x20+/g," ");
1153      str = str.replace(/\s*\r\n/g," ");
1154// DELIMITERS:
1155      mtch = (str.indexOf("\$")==-1 ? false : true);
1156      str = str.replace(/([^\\])\$/g,"$1 \$");
1157      str = str.replace(/^\$/," \$");	// in case \$ at start of string
1158      arr = str.split(" \$");
1159      for (i=0; i<arr.length; i++)
1160         arr[i]=arr[i].replace(/\\\$/g,"\$");
1161         if (arr.length>1 || mtch) {
1162           if (checkForMathML) {
1163             checkForMathML = false;
1164             var nd = AMisMathMLavailable();
1165             AMnoMathML = nd != null;
1166                if (AMnoMathML && notifyIfNoMathML)
1167                   if (alertIfNoMathML)
1168                       alert("To view the ASCIIMathML notation use Internet Explorer 6 +\nMathPlayer (free from www.dessci.com)\n\
1169                              or Firefox/Mozilla/Netscape");
1170            else AMbody.insertBefore(nd,AMbody.childNodes[0]);
1171        }
1172        if (!AMnoMathML) {
1173          frg = AMstrarr2docFrag(arr,n.nodeType==8);
1174          var len = frg.childNodes.length;
1175          n.parentNode.replaceChild(frg,n);
1176          return len-1;
1177        } else return 0;
1178      }
1179    }
1180   } else return 0;
1181  } else if (n.nodeName!="math") {
1182    for (i=0; i<n.childNodes.length; i++)
1183      i += AMprocessNodeR(n.childNodes[i], linebreaks);
1184  }
1185  return 0;
1186}
1187
1188function AMprocessNode(n, linebreaks, spanclassAM) {
1189  var frag,st;
1190  if (spanclassAM!=null) {
1191    frag = document.getElementsByTagName("span")
1192    for (var i=0;i<frag.length;i++)
1193      if (frag[i].className == "AM")
1194        AMprocessNodeR(frag[i],linebreaks);
1195  } else {
1196    try {
1197      st = n.innerHTML;
1198    } catch(err) {}
1199// DELIMITERS:
1200    if (st==null || st.indexOf("\$")!=-1)
1201      AMprocessNodeR(n,linebreaks);
1202  }
1203  if (isIE) { //needed to match size and font of formula to surrounding text
1204    frag = document.getElementsByTagName('math');
1205    for (var i=0;i<frag.length;i++) frag[i].update()
1206  }
1207}
1208
1209/* Below is LaTeX pre-processing to produce CSS supported */
1210/* standard latex structures*/
1211/* Jeff Knisley ([email protected])
1212/* Supported in part by the Howard Hughes Medical Institute */
1213/* as part of the Symbiosis Project: HHMI #52005872 */
1214
1215var inAppendix = false;
1216var sectionCntr = 0;
1217var IEcommentWarning = true;
1218var biblist = [];
1219var bibcntr = 0;
1220
1221var LaTeXCounter = [];
1222LaTeXCounter["definition"] = 0;
1223LaTeXCounter["proposition"] = 0;
1224LaTeXCounter["lemma"] = 0;
1225LaTeXCounter["theorem"] = 0;
1226LaTeXCounter["corollary"] = 0;
1227LaTeXCounter["example"] = 0;
1228LaTeXCounter["exercise"] = 0;
1229LaTeXCounter["subsection"] = 0;
1230LaTeXCounter["subsubsection"] = 0;
1231LaTeXCounter["figure"] = 0;
1232LaTeXCounter["equation"] = 0;
1233LaTeXCounter["table"] = 0;
1234LaTeXCounter["label"] = 0;
1235
1236var LaTeXColor = [];
1237LaTeXColor["greenyellow"]    = "#D9FF4F";
1238LaTeXColor["yellow"]         = "#FFFF00";
1239LaTeXColor["goldenrod"]      = "#FFE529";
1240LaTeXColor["dandelion"]      = "#FFB529";
1241LaTeXColor["apricot"]        = "#FFAD7A";
1242LaTeXColor["peach"]          = "#FF804D";
1243LaTeXColor["melon"]          = "#FF8A80";
1244LaTeXColor["yelloworange"]   = "#FF9400";
1245LaTeXColor["orange"]         = "#FF6321";
1246LaTeXColor["burntorange"]    = "#FF7D00";
1247LaTeXColor["bittersweet"]    = "#C20300";
1248LaTeXColor["redorange"]      = "#FF3B21";
1249LaTeXColor["mahogany"]       = "#A60000";
1250LaTeXColor["maroon"]         = "#AD0000";
1251LaTeXColor["brickred"]       = "#B80000";
1252LaTeXColor["red"]            = "#FF0000";
1253LaTeXColor["orangered"]      = "#FF0080";
1254LaTeXColor["rubinered"]      = "#FF00DE";
1255LaTeXColor["wildstrawberry"] = "#FF0A9C";
1256LaTeXColor["salmon"]         = "#FF789E";
1257LaTeXColor["carnationpink"]  = "#FF5EFF";
1258LaTeXColor["magenta"]        = "#FF00FF";
1259LaTeXColor["violetred"]      = "#FF30FF";
1260LaTeXColor["rhodamine"]      = "#FF2EFF";
1261LaTeXColor["mulberry"]       = "#A314FA";
1262LaTeXColor["redviolet"]      = "#9600A8";
1263LaTeXColor["fuchsia"]        = "#7303EB";
1264LaTeXColor["lavender"]       = "#FF85FF";
1265LaTeXColor["thistle"]        = "#E069FF";
1266LaTeXColor["orchid"]         = "#AD5CFF";
1267LaTeXColor["darkorchid"]     = "#9933CC";
1268LaTeXColor["purple"]         = "#8C24FF";
1269LaTeXColor["plum"]           = "#8000FF";
1270LaTeXColor["violet"]         = "#361FFF";
1271LaTeXColor["royalpurple"]    = "#401AFF";
1272LaTeXColor["blueviolet"]     = "#1A0DF5";
1273LaTeXColor["periwinkle"]     = "#6E73FF";
1274LaTeXColor["cadetblue"]      = "#616EC4";
1275LaTeXColor["cornflowerblue"] = "#59DEFF";
1276LaTeXColor["midnightblue"]   = "#007091";
1277LaTeXColor["navyblue"]       = "#0F75FF";
1278LaTeXColor["royalblue"]      = "#0080FF";
1279LaTeXColor["blue"]           = "#0000FF";
1280LaTeXColor["cerulean"]       = "#0FE3FF";
1281LaTeXColor["cyan"]           = "#00FFFF";
1282LaTeXColor["processblue"]    = "#0AFFFF";
1283LaTeXColor["skyblue"]        = "#61FFE0";
1284LaTeXColor["turquoise"]      = "#26FFCC";
1285LaTeXColor["tealblue"]       = "#1FFAA3";
1286LaTeXColor["aquamarine"]     = "#2EFFB2";
1287LaTeXColor["bluegreen"]      = "#26FFAB";
1288LaTeXColor["emerald"]        = "#00FF80";
1289LaTeXColor["junglegreen"]    = "#03FF7A";
1290LaTeXColor["seagreen"]       = "#4FFF80";
1291LaTeXColor["green"]          = "#00FF00";
1292LaTeXColor["forestgreen"]    = "#00E000";
1293LaTeXColor["pinegreen"]      = "#00BF29";
1294LaTeXColor["limegreen"]      = "#80FF00";
1295LaTeXColor["yellowgreen"]    = "#8FFF42";
1296LaTeXColor["springgreen"]    = "#BDFF3D";
1297LaTeXColor["olivegreen"]     = "#009900";
1298LaTeXColor["rawsienna"]      = "#8C0000";
1299LaTeXColor["sepia"]          = "#4D0000";
1300LaTeXColor["brown"]          = "#660000";
1301LaTeXColor["tan"]            = "#DB9470";
1302LaTeXColor["gray"]           = "#808080";
1303LaTeXColor["grey"]           = "#808080";
1304LaTeXColor["black"]          = "#000000";
1305LaTeXColor["white"]          = "#FFFFFF";
1306
1307var IsColorName = /^(?:greenyellow|yellow|goldenrod|dandelion|apricot|peach|melon|yelloworange|orange|burntorange|bittersweet|redorange|mahogany|maroon|brickred|red|orangered|rubinered|wildstrawberry|salmon|carnationpink|magenta|violetred|rhodamine|mulberry|redviolet|fuchsia|lavender|thistle|orchid|darkorchid|purple|plum|violet|royalpurple|blueviolet|periwinkle|cadetblue|cornflowerblue|midnightblue|navyblue|royalblue|blue|cerulean|cyan|processblue|skyblue|turquoise|tealblue|aquamarine|bluegreen|emerald|junglegreen|seagreen|green|forestgreen|pinegreen|limegreen|yellowgreen|springgreen|olivegreen|rawsienna|sepia|brown|tan|gray|grey|black|white)$/;
1308var IsCounter =  /^(?:definition|proposition|lemma|theorem|corollary|example|exercise|subsection|subsubsection|figure|equation|table)$/ ;
1309var IsLaTeXElement = /^(?:displayequation|title|author|address|date|abstract|keyword|section|subsection|subsubsection|ref|cite|thebibliography|definition|proposition|lemma|theorem|corollary|example|exercise|itemize|enumerate|enddefinition|endproposition|endlemma|endtheorem|endcorollary|endexample|endexercise|enditemize|endenumerate|LaTeXMathMLlabel|LaTeXMathML|smallskip|medskip|bigskip|quote|quotation|endquote|endquotation|center|endcenter|description|enddescription|inlinemath)$/;
1310var IsTextOnlyArea = /^(?:form|textarea|pre)$/i;
1311var tableid = 0;
1312
1313function makeNumberString(cntr) {
1314  if(sectionCntr > 0) {
1315     if(inAppendix) {
1316        return "A"+sectionCntr+"."+cntr;
1317     } else {
1318	return sectionCntr+"."+cntr;
1319     }
1320  } else {
1321     return ""+cntr;
1322  }
1323};
1324
1325
1326function LaTeXpreProcess(thebody) {
1327   var TheBody = thebody;
1328   if(TheBody.hasChildNodes()) {
1329      if(!(IsLaTeXElement.test(TheBody.className)))
1330      {
1331         for(var i=0; i<TheBody.childNodes.length; i++) {
1332            LaTeXpreProcess(TheBody.childNodes[i])  }
1333      }
1334   }
1335   else {
1336      if(  TheBody.nodeType==3 &&
1337	  !(IsTextOnlyArea.test(TheBody.parentNode.nodeName) ) )
1338      {
1339         var str = TheBody.nodeValue;
1340         if( !(str==null)) {
1341
1342	        str = str.replace(/\\%/g, "<per>"); // % sign
1343	        str = str.replace(/%[^\n]*(?=\n)/g,"");
1344	        str = str.replace(/%[^\r]*(?=\r)/g,""); //Used by Explorer
1345	        str = str.replace(/%[^\n]*$/,"") // End of text segment comment
1346
1347	        if(isIE && str.match(/%/g) != null && IEcommentWarning) {
1348	           alert("Comments may not have parsed properly.  Try putting in <pre class='LaTeX><div>..</div></pre> structure.");
1349	           IEcommentWarning = false;
1350	        }
1351	        str = str.replace(/<per>/g,"%");
1352
1353	        //if(str.match(/XXX[\s\S]*/)!=null) {
1354	        //  var tmp = str.match(/XXX[\s\S]*/)[0];
1355	        //  var tmpstr = tmp.charCodeAt(7)+"::"+tmp.charCodeAt(8)+"::"+tmp.charCodeAt(9)+"::"+tmp.charCodeAt(10)+"::"+tmp.charCodeAt(11)+"::"+tmp.charCodeAt(12)+"::"+tmp.charCodeAt(13);
1356	        //  alert(tmpstr);
1357	        //}
1358
1359            //spacing that in LaTeXMathML may cause problems because of our approach. We use purely unicode
1360           //  First we remove singleton / symbols
1361            str = str.replace(/([^\\])\\(\s)/g,"$1\u00A0$2"); // must be a space after \ for it to make an nbsp
1362
1363            str = str.replace(/\\quad/g,"\u2001");
1364            str = str.replace(/\\qquad/g,"\u2001\u2001");
1365            str = str.replace(/\\enspace/g,"\u2002");
1366            str = str.replace(/\\;/g,"\u2004");
1367            str = str.replace(/\\:/g,"\u2005");
1368            str = str.replace(/\\,/g,"\u2006");
1369            str = str.replace(/\\thinspace/g,"\u200A");
1370            str = str.replace(/([^\\])~/g,"$1\u00A0");
1371            str = str.replace(/\\~/g,"~");
1372
1373            //Added \[ ... \] and $$..$$ functionality.
1374            str = str.replace(/\\\[/g," <DEQ> $\\displaystyle{");
1375            str = str.replace(/\\\]/g,"}$ <DEQ> ");
1376            str = str.replace(/\$\$/g,"${$<DEQ>$}$");
1377
1378            // Separate replacements for begin .. end to (eventually) allow LaTeX equations with html internal mixed in
1379            // (as is the case for theorem, etc.
1380            // all variations of spaces with \begin{array} .. \end{array} -- not displayed, however
1381            str = str.replace(/\\begin\s*\{\s*array\s*\}/g,"\\begin{array}");
1382            str = str.replace(/\\end\s*\{\s*array\s*\}/g,"\\end{array}");
1383
1384            // all variations of spaces with \begin{eqnarray} .. \end{eqnarray}
1385            str = str.replace(/\\begin\s*\{\s*eqnarray\s*\}/g,"  <DEQ>eqno$\\begin{eqnarray}");
1386            str = str.replace(/\\end\s*\{\s*eqnarray\s*\}/g,"\\end{eqnarray}$<DEQ>  ");
1387
1388           // all variations of spaces with \begin{eqnarray*} .. \end{eqnarray*}
1389            str = str.replace(/\\begin\s*\{\s*eqnarray\*\s*\}/g,"  <DEQ>$\\begin{eqnarray}");
1390            str = str.replace(/\\end\s*\{\s*eqnarray\*\s*\}/g,"\\end{eqnarray}$<DEQ>  ");
1391
1392            // all variations of spaces with \begin{displaymath} .. \end{displaymath}
1393            str = str.replace(/\\begin\s*\{\s*displaymath\s*\}/g," <DEQ> $\\displaystyle{");
1394            str = str.replace(/\\end\s*\{\s*displaymath\s*\}/g,"}$ <DEQ> ");
1395
1396            // all variations of spaces with \begin{equation*} .. \end{equation*}
1397            str = str.replace(/\\begin\s*\{\s*equation\s*\*\s*\}/g," <DEQ> $\\displaystyle{");
1398            str = str.replace(/\\end\s*\{\s*equation\s*\*\s*\}/g,"}$ <DEQ> ");
1399
1400             // all variations of spaces with \begin{equation} .. \end{equation}
1401            str = str.replace(/\\begin\s*\{\s*equation\s*\}/g," <DEQ>eqno$\\displaystyle{");
1402            str = str.replace(/\\end\s*\{\s*equation\s*\}/g,"}$ <DEQ> ");
1403
1404
1405
1406            //now parse to translate <DEQ> structures to <table class = 'dispeq'> stuff
1407            //and to identify non-display math content (sections, etc).
1408
1409            str = str.split("<DEQ>");
1410            // var ntype = TheBody.nodeType;
1411            var newFrag = document.createDocumentFragment();
1412
1413            for(var i=0;i<str.length;i++) {
1414               if(i % 2) {
1415                  //odd = table of type displayequation
1416                  var DEQtable = document.createElement("table");
1417                  DEQtable.className='displayequation';
1418                  var DEQtbody = document.createElement("tbody");
1419
1420                  var DEQtr = document.createElement("tr");
1421                  var DEQtdeq = document.createElement("td");
1422                      DEQtdeq.className='eq';
1423
1424                  // AfterFix to repair for $$...$$
1425                  str[i] = str[i].replace(/\$\}\$/g,"$\\displaystyle{");
1426                  str[i] = str[i].replace(/\$\{\$/g,"}");
1427
1428                  //check for equation number via either label or eqno at beginning -- \nonumber is removed
1429                  var lbl = str[i].match(/\\label\s*\{\s*(\w+)\s*\}/);
1430                  var ISeqno = str[i].match(/^eqno/);
1431
1432                  // append nodes into row
1433                  str[i] = str[i].replace(/^eqno/," ");
1434                  str[i] = str[i].replace(/\\label\s*\{\s*\w+\s*\}/," ");
1435                  DEQtdeq.appendChild(document.createTextNode( str[i] ) );
1436                  DEQtr.appendChild(DEQtdeq);
1437
1438                  str[i] = str[i].replace(/\\nonumber/g,"");
1439
1440                  if(ISeqno!=null || lbl !=null) {
1441                     var DEQtdno = document.createElement("td");
1442                         DEQtdno.className='eqno';
1443                     LaTeXCounter["equation"]++;
1444		             var eqnoString = makeNumberString(LaTeXCounter["equation"]);
1445
1446		             var DEQanchor = document.createElement("a");
1447		             if(lbl!=null) { DEQanchor.id = lbl[1] };
1448		             DEQanchor.className = "eqno";
1449		             var anchorSpan = document.createElement("span");
1450		             anchorSpan.className = "eqno";
1451		             anchorSpan.style.display = "none";
1452		             anchorSpan.appendChild(document.createTextNode(eqnoString));
1453		             DEQanchor.appendChild(anchorSpan);
1454                     DEQtdno.appendChild(DEQanchor);
1455		             var DEQspan = document.createElement("span");
1456		             DEQspan.className = "eqno";
1457		             DEQspan.appendChild(document.createTextNode("("+eqnoString+")" ));
1458                     DEQtdno.appendChild(DEQspan);
1459                     DEQtr.appendChild(DEQtdno);
1460                  }
1461                  DEQtbody.appendChild(DEQtr);
1462		          DEQtable.appendChild(DEQtbody);
1463                  newFrag.appendChild(DEQtable);
1464               }
1465               else {
1466                  //even = this is text, where we may have sections, labels, subsections, and so on
1467
1468                  // AfterFix to repair for $$...$$
1469                  str[i] = str[i].replace(/\$\}\$/g,"");
1470                  str[i] = str[i].replace(/\$\{\$/g,"");
1471
1472		          //Some stuff we just want to remove
1473                  str[i] = str[i].replace(/\\maketitle/g,"");
1474                  str[i] = str[i].replace(/\\begin\s*\{\s*document\s*\}/g,"");
1475       	    	  str[i] = str[i].replace(/\\end\s*\{\s*document\s*\}/g,"");
1476       	    	  str[i] = str[i].replace(/\\documentclass[^\}]*?\}/g,"");
1477		          str[i] = str[i].replace(/\\usepackage[^\}]*?\}/g,""); //ignores packages and their options
1478		          str[i] = str[i].replace(/\\noindent/g,"");
1479		          str[i] = str[i].replace(/\\notag/g,"");
1480
1481                  //Next: labels, ref's, hrefs, urls, and cites
1482                  str[i] = str[i].replace(/\\ref\s*\{\s*(\w+)\}/g," \\[ref\\]$1\\[ ");
1483		          str[i] = str[i].replace (/\\url\s*\{\s*([^\}\n]+)\}/g," \\[url\\]$1\\[ ");
1484                  str[i] = str[i].replace(/\\href\s*\{\s*([^\}]+)\}\s*\{\s*([^\}]+)\}/g," \\[href\\]$1\\]$2\\[ ");
1485                  str[i] = str[i].replace(/\\cite\s*\{\s*(\w+)\}/g," \\[cite\\]$1\\[ ");
1486
1487		          //Miscellaneous stuff!!
1488		          str[i] = str[i].replace(/\\qed/g,"\u220E");
1489		          str[i] = str[i].replace(/\\endproof/g,"\u220E");
1490		          str[i] = str[i].replace(/\\proof/g,"\\textbf{Proof: }");
1491
1492		          //breaks and skips
1493	              str[i] = str[i].replace(/\\n(?=\s)/g, " \\[br\\] \\[ ");
1494		          str[i] = str[i].replace(/\\newline/g," \\[br\\] \\[ ");
1495		          str[i] = str[i].replace(/\\linebreak/g," \\[br\\] \\[ ");
1496               	  str[i] = str[i].replace(/\\smallskip/g," \\[logicalbreak\\]smallskip\\[ ");
1497	              str[i] = str[i].replace(/\\medskip/g," \\[logicalbreak\\]medskip\\[ ");
1498	              str[i] = str[i].replace(/\\bigskip/g," \\[logicalbreak\\]bigskip\\[ ");
1499		          str[i] = str[i].replace(/[\n\r]+[ \f\n\r\t\v\u2028\u2029]*[\n\r]+/g," \\[logicalbreak\\]LaTeXMathML\\[ ");  // extra return replaced by <p>
1500		          if(isIE) {
1501		             str[i] = str[i].replace(/\r/g," ");  // replace \r by a space to aid spacing!
1502		          }
1503
1504
1505		          //items and appendix
1506		          str[i] = str[i].replace(/\\bibitem\s*([^\{]*\{\s*\w*\s*\})/g," \\[bibitem\\]$1\\[ ");
1507                  str[i] = str[i].replace(/\\bibitem\s*/g," \\[bibitem\\] \\[ ");
1508		          str[i] = str[i].replace(/\\item\s*\[\s*(\w+)\s*\]/g," \\[alistitem\\]$1\\[ ");
1509		          str[i] = str[i].replace(/\\item\s*/g," \\[alistitem\\] \\[ ");
1510  		          str[i] = str[i].replace(/\\appendix/g," \\[appendix\\] \\[ ");
1511
1512
1513                  // \includegraphics[][]{image} -- no processing of options.  This treatment is DANGEROUS.  It assumes no html will be
1514		          // placed within the \begin{figure} ... \end{figure} structure, and the [\s\S] character class could lead to strange matches
1515	              str[i] = str[i].replace(/\\begin\s*\{\s*figure\s*\}([\s\S]+?)\\end\s*\{\s*figure\s*\}/g," \\[figure\\]$1\\[ ");
1516                  str[i] = str[i].replace(/\\begin\s*\{\s*table\s*\}([\s\S]+?)\\end\s*\{\s*table\s*\}/g," \\[table\\]$1\\[ ");
1517		          //str[i] = str[i].replace(/\\begin\s*\{\s*array\s*\}([\s\S]+?)\\end\s*\{\s*array\s*\}/g," \\[array\\]$1\\[ ");
1518                  //goal is to protect array \\ from being converted into linebreaks
1519
1520                  //This construction allows css classes for divs for these elements, but the CSS will have to be supplied through a
1521                  //css file or <script>
1521 .. </script> in the header.  (It makes sense to me that style files in LaTeX should correspond
1522                  //to css and/or xslt when translating to mathml, but \ref's are a problem).
1523                  str[i] = str[i].replace(/\\begin\s*\{\s*theorem\s*\}/g," \\[theorem\\]Theorem \\[ ");
1524                  str[i] = str[i].replace(/\\end\s*\{\s*theorem\s*\}/g," \\[endtheorem\\] \\[ ");
1525
1526                  str[i] = str[i].replace(/\\begin\s*\{\s*definition\s*\}/g," \\[definition\\]Definition \\[ ");
1527                  str[i] = str[i].replace(/\\end\s*\{\s*definition\s*\}/g," \\[enddefinition\\] \\[ ");
1528
1529                  str[i] = str[i].replace(/\\begin\s*\{\s*lemma\s*\}/g," \\[lemma\\]Lemma \\[ ");
1530                  str[i] = str[i].replace(/\\end\s*\{\s*lemma\s*\}/g," \\[endlemma\\] \\[ ");
1531
1532                  str[i] = str[i].replace(/\\begin\s*\{\s*corollary\s*\}/g," \\[corollary\\]Corollary \\[ ");
1533                  str[i] = str[i].replace(/\\end\s*\{\s*corollary\s*\}/g," \\[endcorollary\\] \\[ ");
1534
1535                  str[i] = str[i].replace(/\\begin\s*\{\s*proposition\s*\}/g," \\[proposition\\]Proposition \\[ ");
1536                  str[i] = str[i].replace(/\\end\s*\{\s*proposition\s*\}/g," \\[endproposition\\] \\[ ");
1537
1538                  str[i] = str[i].replace(/\\begin\s*\{\s*example\s*\}/g," \\[example\\]Example \\[ ");
1539                  str[i] = str[i].replace(/\\end\s*\{\s*example\s*\}/g," \\[endexample\\] \\[ ");
1540
1541                  str[i] = str[i].replace(/\\begin\s*\{\s*exercise\s*\}/g," \\[exercise\\]Exercise \\[ ");
1542                  str[i] = str[i].replace(/\\end\s*\{\s*exercise\s*\}/g," \\[endexercise\\] \\[ ");
1543
1544                  str[i] = str[i].replace(/\\begin\s*\{\s*thebibliography\s*\}\s*\{\s*\w+\s*\}/g," \\[thebibliography\\]References \\[ ");
1545                  str[i] = str[i].replace(/\\begin\s*\{\s*thebibliography\s*\}/g," \\[thebibliography\\]References \\[ ");
1546                  str[i] = str[i].replace(/\\end\s*\{\s*thebibliography\s*\}/g," \\[endthebibliography\\]References \\[ ");
1547
1548
1549                  str[i] = str[i].replace(/\\begin\s*\{\s*proof\s*\}/g," \\[proof\\]Proof: \\[ ");
1550                  if(isIE) {  //IE is just so weird
1551                     str[i] = str[i].replace(/\\end\s*\{\s*proof\s*\}/g,"\u220E \\[endproof\\] \\[ ");
1552                  } else {
1553                     str[i] = str[i].replace(/\\end\s*\{\s*proof\s*\}/g," \\[endproof\\] \\[ ");
1554                  }
1555
1556                  //The frontmatter -- all translated to div's to be handled by CSS
1557                  str[i] = str[i].replace(/\\title\s*\{\s*([^\}]+)\}/g," \\[title\\] \\[$1 \\[endtitle\\] \\[ ");
1558                  str[i] = str[i].replace(/\\author\s*\{\s*([^\}]+)\}/g," \\[author\\] \\[$1 \\[endauthor\\] \\[ ");
1559                  str[i] = str[i].replace(/\\address\s*\{\s*([^\}]+)\}/g," \\[address\\] \\[$1 \\[endaddress\\] \\[ ");
1560                  str[i] = str[i].replace(/\\date\s*\{\s*([^\}]+)\}/g," \\[date\\] \\[$1 \\[enddate\\] \\[ ");
1561                  str[i] = str[i].replace(/\\begin\s*\{\s*keyword\s*\}/g," \\[keyword\\] \\[ ");
1562                  str[i] = str[i].replace(/\\end\s*\{\s*keyword\s*\}/g," \\[endkeyword\\] \\[ ");
1563                  str[i] = str[i].replace(/\\begin\s*\{\s*abstract\s*\}/g," \\[abstract\\] \\[ ");
1564	              str[i] = str[i].replace(/\\end\s*\{\s*abstract\s*\}/g," \\[endabstract\\] \\[ ");
1565
1566                  //The rest of the environments -- Users can even "make up their own" -- but it avoids the array and tabular environments
1567                  str[i] = str[i].replace(/\\begin\s*\{\s*(?!array|tabular)(\w+)\s*\}/g," \\[$1\\] \\[ ");
1568                  str[i] = str[i].replace(/\\end\s*\{\s*(?!array|tabular)(\w+)\s*\}/g," \\[end$1\\] \\[ ");
1569
1570                  //Next, we look at section--subsection stuff.  This is nested -- this would be so much better if LaTeX used
1571                  //some type of \begin{sectionhead}...\end{sectionhead} structure
1572                  var sectionIndex = str[i].search(/\\section\s*\{\s*[\s\S]+\}/);
1573
1574                  while(sectionIndex >= 0) {
1575                     str[i] = str[i].replace(/\\section\s*\{/ ," \\[section\\]");
1576                     var delimcnt = 1;
1577                     for(var ii=sectionIndex;ii<str[i].length;ii++) {
1578                        if(str[i].charAt(ii) == "{") { delimcnt++ };
1579                        if(str[i].charAt(ii) == "}") { delimcnt-- };
1580                        if(delimcnt == 0) {
1581                           str[i] = str[i].substring(0,ii)+"\\[ "+str[i].substring(ii+1,str[i].length) ;
1582                           break;
1583                        }
1584                     };
1585                     sectionIndex = str[i].search(/\\section\s*\{\s*[\s\S]+\}/); //look for next
1586                  }
1587
1588	              sectionIndex = str[i].search(/\\subsection\s*\{\s*[\s\S]+\}/);
1589
1590                  while(sectionIndex >= 0) {
1591                     str[i] = str[i].replace(/\\subsection\s*\{/ ," \\[subsection\\]");
1592                     var delimcnt = 1;
1593                     for(var ii=sectionIndex;ii<str[i].length;ii++) {
1594                        if(str[i].charAt(ii) == "{") { delimcnt++ };
1595                        if(str[i].charAt(ii) == "}") { delimcnt-- };
1596                        if(delimcnt == 0) {
1597                           str[i] = str[i].substring(0,ii)+"\\[ "+str[i].substring(ii+1,str[i].length) ;
1598                           break;
1599                        }
1600                     };
1601                     sectionIndex = str[i].search(/\\subsection\s*\{\s*[\s\S]+\}/); //look for next
1602                  }
1603
1604                  sectionIndex = str[i].search(/\\subsubsection\s*\{\s*[\s\S]+\}/);
1605
1606                  while(sectionIndex >= 0) {
1607                     str[i] = str[i].replace(/\\subsubsection\s*\{/ ," \\[subsubsection\\]");
1608                     var delimcnt = 1;
1609                     for(var ii=sectionIndex;ii<str[i].length;ii++) {
1610                        if(str[i].charAt(ii) == "{") { delimcnt++ };
1611                        if(str[i].charAt(ii) == "}") { delimcnt-- };
1612                        if(delimcnt == 0) {
1613                           str[i] = str[i].substring(0,ii)+"\\[ "+str[i].substring(ii+1,str[i].length) ;
1614                           break;
1615                        }
1616                     };
1617                     sectionIndex = str[i].search(/\\subsubsection\s*\{\s*[\s\S]+\}/); //look for next
1618                   }
1619
1620                  var CatToNextEven = "";
1621                  //split into alternating text elements and "marked" elements
1622                  var strtmp = str[i].split("\\[");
1623                  //document.write(strtmp[0]);
1624
1625                  for(var j=0;j<strtmp.length;j++) {
1626                     if(j % 2) {
1627                        //odd = split on \\]
1628                        var strtmparray = strtmp[j].split("\\]");
1629                        switch (strtmparray[0]) {
1630                           case "section":
1631                              var nodeTmp = document.createElement("H2");
1632                              nodeTmp.className = 'section';
1633                              //reset counters
1634                                sectionCntr++;
1635                                for (var div in LaTeXCounter) { LaTeXCounter[div] = 0 };
1636                              //Create Title of section
1637                              var nodeAnchor = document.createElement("a");
1638                              if(inAppendix) {
1639                                 nodeAnchor.className='appendixsection';
1640                              } else {
1641                                 nodeAnchor.className='section';
1642                              }
1643                              var nodeNumString = makeNumberString("");
1644                              var anchorSpan = document.createElement("span");
1645                              anchorSpan.className = "section";
1646                              anchorSpan.style.display = "none";
1647                              anchorSpan.appendChild(document.createTextNode(nodeNumString));
1648                              nodeAnchor.appendChild(anchorSpan);
1649                              nodeTmp.appendChild(nodeAnchor);
1650
1651                              var nodeSpan = document.createElement("span");
1652                              nodeSpan.className = 'section';
1653                              nodeSpan.appendChild(document.createTextNode(nodeNumString+" "));
1654                              nodeTmp.appendChild(nodeSpan);
1655                              nodeTmp.appendChild(document.createTextNode( strtmparray[1] ) );
1656                              newFrag.appendChild(nodeTmp);
1657                           break;
1658                           case "subsection":
1659                              var nodeTmp = document.createElement("H3");
1660                              nodeTmp.className = 'subsection';
1661                              //counters
1662                                LaTeXCounter["subsection"]++;
1663                                LaTeXCounter["subsubsection"]=0;
1664                             //Create Title of section
1665                              var nodeAnchor = document.createElement("a");
1666                              nodeAnchor.className = 'subsection';
1667                              var nodeNumString = makeNumberString(LaTeXCounter["subsection"]);
1668                              var anchorSpan = document.createElement("span");
1669                              anchorSpan.className = "subsection";
1670                              anchorSpan.style.display = "none";
1671                              anchorSpan.appendChild(document.createTextNode(nodeNumString));
1672                              nodeAnchor.appendChild(anchorSpan);
1673                              nodeTmp.appendChild(nodeAnchor);
1674                              var nodeSpan = document.createElement("span");
1675                              nodeSpan.className = 'subsection';
1676                              nodeSpan.appendChild(document.createTextNode(nodeNumString+". "));
1677                              nodeTmp.appendChild(nodeSpan);
1678                              nodeTmp.appendChild(document.createTextNode( strtmparray[1] ) );
1679                              newFrag.appendChild(nodeTmp);
1680                           break;
1681                           case "subsubsection":
1682                              var nodeTmp = document.createElement("H4");
1683                              nodeTmp.className = 'subsubsection';
1684                               //counters
1685                                LaTeXCounter["subsubsection"]++;
1686                              //Create Title of section
1687                              var nodeAnchor = document.createElement("a");
1688                              nodeAnchor.className = 'subsubsection';
1689                              var nodeNumString = makeNumberString(LaTeXCounter["subsection"]+"."+LaTeXCounter["subsubsection"]);
1690                              var anchorSpan = document.createElement("span");
1691                              anchorSpan.className = "subsubsection";
1692                              anchorSpan.style.display = "none";
1693                              anchorSpan.appendChild(document.createTextNode(nodeNumString));
1694                              nodeAnchor.appendChild(anchorSpan);
1695                              nodeTmp.appendChild(nodeAnchor);
1696                              var nodeSpan = document.createElement("span");
1697                              nodeSpan.className = 'subsubsection';
1698                              nodeSpan.appendChild(document.createTextNode(nodeNumString+". "));
1699                              nodeTmp.appendChild(nodeSpan);
1700                              nodeTmp.appendChild(document.createTextNode( strtmparray[1] ) );
1701                              newFrag.appendChild(nodeTmp);
1702                           break;
1703                           case "href":
1704                              var nodeTmp = document.createElement("a");
1705                              nodeTmp.className = 'LaTeXMathML';
1706                              nodeTmp.href = strtmparray[1];
1707                              nodeTmp.appendChild(document.createTextNode( strtmparray[2]));
1708                              newFrag.appendChild(nodeTmp);
1709                           break;
1710                           case "url":
1711                              var nodeTmp = document.createElement("a");
1712                              nodeTmp.className = 'LaTeXMathML';
1713                              nodeTmp.href = strtmparray[1];
1714                              nodeTmp.appendChild(document.createTextNode( strtmparray[1]));
1715                              newFrag.appendChild(nodeTmp);
1716                           break;
1717                           case "figure":
1718                              var nodeTmp = document.createElement("table");
1719                              nodeTmp.className = 'figure';
1720                              var FIGtbody = document.createElement("tbody");
1721
1722                              var FIGlbl = strtmparray[1].match(/\\label\s*\{\s*(\w+)\s*\}/);
1723                              strtmparray[1]=strtmparray[1].replace(/\\label\s*\{\w+\}/g,"");
1724
1725                              var capIndex = strtmparray[1].search(/\\caption\s*\{[\s\S]+\}/);
1726                              var FIGcap = "";
1727
1728                              if(capIndex >= 0) { // caption may contain other {  } structures -- but not displaymath!!
1729                                 var tmp = strtmparray[1];
1730                                 var delimcnt = 0;
1731                              	 var capstart = -1;
1732                                 for(var pos=capIndex;pos<tmp.length;pos++) {
1733                                    if(tmp.charAt(pos) == "{") { delimcnt++ };
1734                                    if(tmp.charAt(pos) == "}") { delimcnt-- };
1735                                    if(delimcnt == 1 && capstart<0) { capstart = pos+1 };
1736                                    if(delimcnt == 0 && capstart>0) {
1737                                       capend = pos-1;
1738                                       FIGcap = tmp.substring(capstart,pos);
1739                                       break
1740                                    }
1741                                 }
1742                              }
1743
1744                              var FIGtr2 = document.createElement("tr");
1745                              var FIGtd2  = document.createElement("td");
1746                              FIGtd2.className="caption";
1747
1748
1749                              var FIGanchor = document.createElement("a");
1750                              FIGanchor.className = "figure";
1751                              if(FIGlbl!=null) {  FIGanchor.id = FIGlbl[1]; }
1752                              LaTeXCounter["figure"]++;
1753                              var fignmbr = makeNumberString(LaTeXCounter["figure"]);
1754                              var anchorSpan = document.createElement("span");
1755                              anchorSpan.className = "figure";
1756                              anchorSpan.style.display = "none";
1757                              anchorSpan.appendChild(document.createTextNode(fignmbr));
1758                              FIGanchor.appendChild(anchorSpan);
1759                              FIGtd2.appendChild(FIGanchor);
1760
1761                              var FIGspan = document.createElement("span");
1762                              FIGspan.className = "figure"; //For CSS counters, comment this line
1763                              FIGspan.appendChild(document.createTextNode("Figure "+fignmbr+". " ) );
1764                              FIGtd2.appendChild(FIGspan);
1765                              FIGtd2.appendChild(document.createTextNode(""+FIGcap));
1766                              FIGtr2.appendChild(FIGtd2);
1767                              FIGtbody.appendChild(FIGtr2);
1768                              var IsSpecial = false;
1769
1770                              var FIGinfo = strtmparray[1].match(/\\includegraphics\s*\{([^\}]+)\}/);
1771                              if(FIGinfo==null) { //options not processed, for now
1772                                 FIGinfo = strtmparray[1].match(/\\includegraphics\s*\[[^\]]*\]\s*\{\s*([^\}]+)\s*\}/);
1773                              }
1774                              if(FIGinfo==null) {
1775                                 FIGinfo = strtmparray[1].match(/\\special\s*\{\s*([^\}]+)\}/);
1776                                 IsSpecial=true //Hook: Later can include "special" graphics commands
1777                              };
1778
1779                              if(FIGinfo!=null) { //Caption will be above the image
1780                                 var FIGtr1 = document.createElement("tr");
1781                                 var FIGtd1  = document.createElement("td");
1782                                 FIGtd1.className="image";
1783                                 var FIGimg = document.createElement("img");
1784                                 var FIGsrc = FIGinfo[1]; //options not processed, for now
1785                                 FIGimg.src = FIGsrc;
1786                                 FIGimg.alt = "Figure "+FIGsrc+" did not load";
1787                                 FIGimg.title = "Figure "+fignmbr+". "+FIGcap;
1788                                 FIGimg.id = "figure"+fignmbr;
1789                                 FIGtd1.appendChild(FIGimg);
1790                                 FIGtr1.appendChild(FIGtd1);
1791                                 FIGtbody.appendChild(FIGtr1);
1792                              }
1793                              nodeTmp.appendChild(FIGtbody);
1794                              newFrag.appendChild(nodeTmp);
1795                           break;
1796                           case "table":
1797                              var nodeTmp = document.createElement("table");
1798                              if(strtmparray[1].search(/\\centering/) >= 0) {
1799                                 nodeTmp.className = 'LaTeXtable centered';
1800                                 nodeTmp.align = "center";
1801                              } else {
1802                                 nodeTmp.className = 'LaTeXtable';
1803                              };
1804                              tableid++;
1805                              nodeTmp.id = "LaTeXtable"+tableid; //unique id for each table
1806
1807                              var TABlbl = strtmparray[1].match(/\\label\s*\{\s*(\w+)\s*\}/);
1808                              strtmparray[1]=strtmparray[1].replace(/\\label\s*\{\w+\}/g,"");
1809
1810                              var capIndex = strtmparray[1].search(/\\caption\s*\{[\s\S]+\}/);
1811                              var TABcap = "";
1812
1813                              if(capIndex >= 0) { // caption may contain other {  } structures -- but not displaymath!!
1814                                 var tmp = strtmparray[1];
1815                                 var delimcnt = 0;
1816                                 var capstart = -1;
1817                                 for(var pos=capIndex;pos<tmp.length;pos++) {
1818                                    if(tmp.charAt(pos) == "{") { delimcnt++ };
1819                                    if(tmp.charAt(pos) == "}") { delimcnt-- };
1820                                    if(delimcnt == 1 && capstart<0) { capstart = pos+1 };
1821                                    if(delimcnt == 0 && capstart>0) {
1822	                                   capend = pos-1;
1823                           		       TABcap = tmp.substring(capstart,pos);
1824								       break
1825								    }
1826								 }
1827			  				  }
1828
1829                              if(TABcap!="") {
1830                                 var TABtbody = document.createElement("tbody");
1831                                 var TABcaption = document.createElement("caption");
1832                                 TABcaption.className="LaTeXtable centered";
1833                                 var TABanchor = document.createElement("a");
1834   			        			 TABanchor.className = "LaTeXtable";
1835                                 if(TABlbl!=null) {  TABanchor.id = TABlbl[1]; }
1836                                 LaTeXCounter["table"]++;
1837	   					         var tabnmbr = makeNumberString(LaTeXCounter["table"]);
1838						         var anchorSpan = document.createElement("span");
1839						         anchorSpan.className = "LaTeXtable";
1840						         anchorSpan.style.display = "none";
1841						         anchorSpan.appendChild(document.createTextNode(tabnmbr));
1842                                 TABanchor.appendChild(anchorSpan);
1843						         TABcaption.appendChild(TABanchor);
1844
1845						         var TABspan = document.createElement("span");
1846                                 TABspan.className = "LaTeXtable"; //For CSS counters, comment this line
1847                                 TABspan.appendChild(document.createTextNode("Table "+tabnmbr+". " ) );
1848						         TABcaption.appendChild(TABspan);
1849						         TABcaption.appendChild(document.createTextNode(""+TABcap));
1850                                 nodeTmp.appendChild(TABcaption);
1851						      }
1852                              var TABinfo = strtmparray[1].match(/\\begin\s*\{\s*tabular\s*\}([\s\S]+)\\end\s*\{\s*tabular\s*\}/);
1853						      if(TABinfo!=null) {
1854								 var TABtbody = document.createElement('tbody');
1855								 var TABrow = null;
1856								 var TABcell = null;
1857								 var row=0;
1858								 var col=0;
1859
1860								 var TABalign = TABinfo[1].match(/^\s*\{([^\}]+)\}/);
1861								 TABinfo = TABinfo[1].replace(/^\s*\{[^\}]+\}/,"");
1862								 TABinfo = TABinfo.replace(/\\hline/g,""); //no horizontal bars
1863								 TABalign[1] = TABalign[1].replace(/\|/g,""); //no vertical bars
1864								 TABalign[1] = TABalign[1].replace(/\s/g,"");
1865								 TABinfo = TABinfo.split("\\\\"); // into rows
1866								 for(row=0;row<TABinfo.length;row++) {
1867						            TABrow = document.createElement("tr");
1868								    TABinfo[row] = TABinfo[row].split("&");
1869								    for(col=0;col<TABinfo[row].length;col++) {
1870								       TABcell = document.createElement("td");
1871								       switch (TABalign[1].charAt(col)) {
1872						                  case "l":
1873										     TABcell.style.textAlign = "left";
1874								          break;
1875						                  case "c":
1876										     TABcell.style.textAlign = "center";
1877								          break;
1878						                  case "r":
1879										     TABcell.style.textAlign = "right";
1880								          break;
1881						                  default :
1882										     TABcell.style.textAlign = "left";
1883								       };
1884								       TABcell.appendChild(document.createTextNode(TABinfo[row][col]));
1885								       TABrow.appendChild(TABcell);
1886								    }
1887								    TABtbody.appendChild(TABrow);
1888						         }
1889						         nodeTmp.appendChild(TABtbody);
1890						      }
1891                              newFrag.appendChild(nodeTmp);
1892                           break;
1893						   case "logicalbreak":
1894                              var nodeTmp = document.createElement("p");
1895                              nodeTmp.className = strtmparray[1];
1896						      nodeTmp.appendChild(document.createTextNode("\u00A0"));
1897						      newFrag.appendChild(nodeTmp);
1898                           break;
1899						   case "appendix":
1900                              inAppendix=true;
1901                              sectionCntr=0;
1902						   break;
1903						   case "alistitem":
1904                              var EndDiv = document.createElement("div");
1905						      EndDiv.className = "endlistitem";
1906                              newFrag.appendChild(EndDiv);
1907						      var BegDiv = document.createElement("div");
1908                              BegDiv.className = "listitem";
1909						      if(strtmparray[1]!=" ") {
1910                                 var BegSpan = document.createElement("span");
1911                                 BegSpan.className="listitemmarker";
1912								 var boldBegSpan = document.createElement("b");
1913								 boldBegSpan.appendChild(document.createTextNode(strtmparray[1]+" "));
1914								 BegSpan.appendChild(boldBegSpan);
1915								 BegDiv.appendChild(BegSpan);
1916                              }
1917						      newFrag.appendChild(BegDiv);
1918                           break;
1919                           case "br":
1920                              newFrag.appendChild(document.createElement("br"));
1921                           break;
1922                           case "bibitem":
1923						      newFrag.appendChild(document.createElement("br"));
1924						      var nodeTmp = document.createElement("a");
1925 						      nodeTmp.className = 'bibitem';
1926  		    			      var nodeSpan = document.createElement("span");
1927 						      nodeSpan.className = 'bibitem';
1928
1929						      bibcntr++;
1930
1931						      var lbl = strtmparray[1].match(/\{\s*(\w+)\s*\}/);
1932						      strtmparray[1] = strtmparray[1].replace(/\s*\{\s*\w+\s*\}/g,"");
1933						      strtmparray[1] = strtmparray[1].replace(/^\s*\[/,"");
1934						      strtmparray[1] = strtmparray[1].replace(/\s*\]$/,"");
1935  		    			      strtmparray[1] = strtmparray[1].replace(/^\s+|\s+$/g,"");
1936						      //We create a list of id's for the bibitems -- it seemed important at one time??
1937						      if(lbl==null) {
1938								 biblist[bibcntr] = "bibitem"+bibcntr
1939						      } else {
1940						         biblist[bibcntr] = lbl[1];
1941						      };
1942						      nodeTmp.name = biblist[bibcntr];
1943						      nodeTmp.id = biblist[bibcntr];
1944						      // We place content into <a> -- access it with \cite, thus allowing appropriate labels!
1945						      if(strtmparray[1]!="") {
1946								 nodeSpan.appendChild(document.createTextNode(strtmparray[1]));
1947                              } else {
1948                                 nodeSpan.appendChild(document.createTextNode("["+bibcntr+"]"));
1949                              }
1950						      nodeTmp.appendChild(nodeSpan);
1951						      newFrag.appendChild(nodeTmp);
1952                           break;
1953                           case "cite":
1954                              var nodeTmp = document.createElement("a");
1955                              nodeTmp.className = 'cite';
1956                              nodeTmp.name = 'cite';
1957                              nodeTmp.href = "#"+strtmparray[1];
1958                              newFrag.appendChild(nodeTmp);
1959                           break;
1960                           case "ref":
1961                              var nodeTmp = document.createElement("a");
1962                              nodeTmp.className = 'ref';
1963                              nodeTmp.name = 'ref';
1964                              nodeTmp.href = "#"+strtmparray[1];
1965                              newFrag.appendChild(nodeTmp);
1966                           break;
1967                           default :
1968                              var nodeTmp = document.createElement("div");
1969                              nodeTmp.className = strtmparray[0];
1970                              if( IsCounter.test(strtmparray[0]) ) {
1971								 LaTeXCounter[strtmparray[0]]++;
1972                                 var nodeAnchor = document.createElement("a");
1973                                 nodeAnchor.className = strtmparray[0];
1974								 var divnum = makeNumberString(LaTeXCounter[strtmparray[0]]);
1975				 				 var anchorSpan = document.createElement("span");
1976								 anchorSpan.className = strtmparray[0];
1977								 anchorSpan.appendChild(document.createTextNode(divnum));
1978								 anchorSpan.style.display="none";
1979								 nodeAnchor.appendChild(anchorSpan);
1980								 nodeTmp.appendChild(nodeAnchor);
1981
1982								 var nodeSpan = document.createElement("span");
1983                                 nodeSpan.className = strtmparray[0];
1984								 nodeSpan.appendChild(document.createTextNode(strtmparray[1]+" "+divnum+". "));
1985                                 nodeTmp.appendChild(nodeSpan);
1986                              }
1987						      if(isIE) { //remove if IE supports :before and :after
1988								 if(strtmparray[0]==("thebibliography"||"abstract"||"keyword"||"proof")) {
1989                                    var nodeSpan = document.createElement("span");
1990                                    nodeSpan.className = strtmparray[0];
1991								    nodeSpan.appendChild(document.createTextNode(strtmparray[1]));
1992                                    nodeTmp.appendChild(nodeSpan);
1993                                 }
1994                              } //end of IE :before and :after fixes
1995			    			  if(strtmparray[0]=="endenumerate" || strtmparray[0]=="enditemize" || strtmparray[0]=="enddescription") {
1996                                 var endDiv = document.createElement("div");
1997                                 endDiv.className = "endlistitem";
1998								 newFrag.appendChild(endDiv);
1999                              }
2000                              newFrag.appendChild(nodeTmp);
2001			    			  if(strtmparray[0]=="enumerate" || strtmparray[0]=="itemize" || strtmparray[0]=="description") {
2002                                 var endDiv = document.createElement("div");
2003                                 endDiv.className = "listitem";
2004								 newFrag.appendChild(endDiv);
2005                              }
2006                         }
2007                      } else {
2008                      	 //even = text, labels, bf, and italics, and linebreaks, and math -- we now remove the math
2009                         strtmp[j] = strtmp[j].replace(/\\\$/g,"<per>");
2010                         strtmp[j] = strtmp[j].replace(/\$([^\$]+)\$/g," \\[$1\\[ ");
2011                         strtmp[j] = strtmp[j].replace(/<per>/g,"\\$");
2012                         strtmp[j] = strtmp[j].replace(/\\begin\s*\{\s*math\s*\}([\s\S]+?)\\end\s*\{\s*math\s*\}/g," \\[$1\\[ ");
2013
2014						 var strtmptmp = strtmp[j].split("\\[");
2015
2016                         for(var jjj=0;jjj<strtmptmp.length;jjj++) {
2017                            if(jjj % 2) { //odd = math
2018                              var nodeTmp = document.createElement("span");
2019                              nodeTmp.className = 'inlinemath';
2020                              nodeTmp.appendChild(document.createTextNode("$"+strtmptmp[jjj]+"$"));
2021                              newFrag.appendChild(nodeTmp);
2022                            } else {
2023		      			 	  //all other tags will be mapped to span's (most should be font-face tags) with class-names matching the tag name.
2024                              //Exceptions will be textcolor, colorbox, textbf, textit, and emph.  These cannot include any html tags.
2025		      			 	    var TagIndex = strtmptmp[jjj].search(/\\\w+/);
2026		      			 	    var tmpIndex = TagIndex;
2027		      			 	    while(tmpIndex>-1) {
2028		      			 	       if(/^\\textcolor/.test(strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length))) {
2029		      			 	          strtmptmp[jjj] = strtmptmp[jjj].replace(/\\textcolor\s*\{\s*(\w+)\s*\}\s*/," \\[textcolor\\]$1\\]|");
2030		      			 	       } else {
2031		      			 	          if(/^\\colorbox/.test(strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length))) {
2032		      			 	             strtmptmp[jjj] = strtmptmp[jjj].replace(/\\colorbox\s*\{\s*(\w+)\s*\}\s*/," \\[colorbox\\]$1\\]|");
2033		      			 	          } else {
2034		      			 	             strtmptmp[jjj] = strtmptmp[jjj].substring(0,TagIndex)+strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).replace(/\\\s*(\w+)\s*/," \\[$1\\]|");
2035		      			 	          }
2036		      			 	       }
2037		      			 	       TagIndex +=strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).search(/\|/);
2038		      			 	       TagIndex++;
2039		      			 	       strtmptmp[jjj] = strtmptmp[jjj].replace(/\\\]\|/,"\\] ");
2040		      			 	       if(strtmptmp[jjj].charAt(TagIndex) == "{") {
2041		      			 	          strtmptmp[jjj] = strtmptmp[jjj].substring(0,TagIndex)+strtmptmp[jjj].substring(TagIndex+1,strtmptmp[jjj].length);
2042		      			 	          var delimcnt = 1;
2043		      			 	          for(var kk = TagIndex;kk<strtmptmp[jjj].length;kk++) {
2044		      			 	             if(strtmptmp[jjj].charAt(kk) == "{") { delimcnt++ };
2045		      			 	             if(strtmptmp[jjj].charAt(kk) == "}") { delimcnt-- };
2046		      			 	             if(delimcnt==0) { break; }
2047		      			 	          }
2048		      			 	             strtmptmp[jjj] = strtmptmp[jjj].substring(0,kk)+"\\[ "+strtmptmp[jjj].substring(kk+1,strtmptmp[jjj].length);
2049		      			 	             TagIndex = kk+3;
2050		      			 	       } else {
2051		      			 	          strtmptmp[jjj] = strtmptmp[jjj].substring(0,TagIndex)+"\\[ "+strtmptmp[jjj].substring(TagIndex+1,strtmptmp[jjj].length);
2052                                      TagIndex = TagIndex + 3;
2053                                   }
2054                                   if(TagIndex<strtmptmp[jjj].length) {
2055                                      tmpIndex = strtmptmp[jjj].substring(TagIndex,strtmptmp[jjj].length).search(/\\\w+/);
2056                                   }
2057		      			 	       else {
2058		      			 	          tmpIndex = -1 };
2059		      			 	       TagIndex += tmpIndex;
2060		      			 	    }
2061
2062
2063                                strtmptmp[jjj] = strtmptmp[jjj].replace(/\\\\\s*\\\\/g,"\\\\");
2064				         		strtmptmp[jjj] = strtmptmp[jjj].replace(/\\\\/g," \\[br\\] \\[ ");
2065						 		strtmptmp[jjj] = strtmptmp[jjj].replace(/\\label\s*\{\s*(\w+)\s*\}/g," \\[label\\]$1\\[ ");
2066						 		var strlbls = strtmptmp[jjj].split("\\[");
2067
2068                         		for(var jj=0;jj<strlbls.length;jj++) {
2069                         		   if(jj % 2) { //odd = labels, boldface, and breaks
2070						 		     var strtmparray = strlbls[jj].split("\\]");
2071						              switch(strtmparray[0]) {
2072								        case "textcolor":
2073        		                            var nodeTmp = document.createElement("span");
2074        		                            nodeTmp.className = 'LaTeXColor';
2075										    if(IsColorName.test(strtmparray[1].toLowerCase())) {
2076   										       nodeTmp.style.color=LaTeXColor[strtmparray[1].toLowerCase()];
2077										    } else {
2078										       nodeTmp.style.color=strtmparray[1];
2079        		                            };
2080        		                            nodeTmp.appendChild(document.createTextNode(strtmparray[2]));
2081        		                            newFrag.appendChild(nodeTmp);
2082        		                         break;
2083        		                         case "colorbox":
2084        		                            var nodeTmp = document.createElement("span");
2085        		                            nodeTmp.className = 'LaTeXColor';
2086										    if(IsColorName.test(strtmparray[1].toLowerCase())) {
2087   										       nodeTmp.style.background=LaTeXColor[strtmparray[1].toLowerCase()];
2088										    } else {
2089										       nodeTmp.style.background=strtmparray[1];
2090        		                            };
2091        		                            nodeTmp.appendChild(document.createTextNode(strtmparray[2]));
2092        		                            newFrag.appendChild(nodeTmp);
2093        		                         break;
2094        		                         case "br":
2095								            newFrag.appendChild(document.createElement("br"));
2096   								         break;
2097					    			     case "label" :
2098								           var nodeTmp = document.createElement("a");
2099								            nodeTmp.className = 'LaTeXMathMLlabel';
2100								            var lblid = strtmparray[1].match(/\s*(\w+)\s*/);
2101								            if(lblid != null) { nodeTmp.id = lblid[1] };
2102								            nodeTmp.style.display = "none";
2103
2104                                            LaTeXCounter['label']++;
2105                                            var lblnum = makeNumberString(LaTeXCounter['label']);
2106
2107								            var anchorSpan = document.createElement("span");
2108								            anchorSpan.className = 'LaTeXMathMLlabel';
2109								            anchorSpan.appendChild(document.createTextNode(lblnum));
2110								            anchorSpan.style.display="none";
2111								            nodeTmp.appendChild(anchorSpan);
2112								            newFrag.appendChild(nodeTmp);
2113								         break;
2114        		                         default :
2115        		                            var nodeTmp = document.createElement("span");
2116        		                            nodeTmp.className = strtmparray[0];
2117        		                            nodeTmp.appendChild(document.createTextNode(strtmparray[1]))
2118        		                            newFrag.appendChild(nodeTmp);
2119					 			       }
2120							         } else {
2121				     		         newFrag.appendChild(document.createTextNode(strlbls[jj]));
2122					 			   }
2123					 			}
2124					 	   }
2125					 	}
2126		      		} // end else for even splits of strtmp
2127		  		 }
2128	           }
2129            }; //else sections and labels
2130            TheBody.parentNode.replaceChild(newFrag,TheBody);
2131         } //str nodevalue is not empty
2132      }
2133   } // split off recursion
2134   return TheBody;
2135}
2136
2137function LaTeXDivsAndRefs(thebody) {
2138   var TheBody = thebody;
2139
2140   var EndDivClass = null;
2141   var AllDivs = TheBody.getElementsByTagName("div");
2142   var lbl2id = "";
2143   var lblnode = null;
2144   for(var i=AllDivs.length-1;i>=0;i--) {
2145      EndDivClass = AllDivs[i].className.match(/end\w+/ );
2146      if(EndDivClass!=null) {
2147         EndDivClass = EndDivClass[0];
2148	 var DivClass = EndDivClass.substring(3,EndDivClass.length);
2149         var EndDivNode = AllDivs[i];
2150         break;
2151      }
2152   }
2153   while(EndDivClass!=null) {
2154      // TrackBack to Beginning, appending to newfrag as we go
2155      var newFrag = document.createDocumentFragment();
2156      var RootNode = EndDivNode.parentNode;
2157      var ClassCount = 1; // because of EndDivNode
2158      while(EndDivNode.previousSibling!=null && ClassCount>0) {
2159	 switch(EndDivNode.previousSibling.className) {
2160	    case EndDivClass:
2161	       ClassCount++;
2162	       newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);
2163	       break;
2164	    case DivClass:
2165	       if(EndDivNode.previousSibling.nodeName=="DIV") {
2166	          ClassCount-- ;
2167		  //Must check to see if we need a label here!
2168		 if(lbl2id !="" ) {
2169		    EndDivNode.previousSibling.id = lbl2id;
2170		    lbl2id = ""
2171		 }
2172		 if(ClassCount==0) {
2173	             RootNode = EndDivNode.previousSibling;
2174		  } else {
2175	             newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);
2176		  }
2177	       };
2178	       break;
2179           case 'LaTeXMathMLlabel':
2180               lbl2id = EndDivNode.previousSibling.id;
2181	          EndDivNode.parentNode.removeChild(EndDivNode.previousSibling);
2182	       break;
2183	    default:
2184	       newFrag.insertBefore(EndDivNode.previousSibling,newFrag.firstChild);
2185            }
2186      }
2187      RootNode.appendChild(newFrag);
2188      EndDivNode.parentNode.removeChild(EndDivNode);
2189
2190      //Look for more end div items
2191      AllDivs = TheBody.getElementsByTagName("DIV");
2192      for(i=AllDivs.length-1;i>=0;i--) {
2193         EndDivClass = AllDivs[i].className.match(/end\w+/ );
2194         if(EndDivClass!=null) {
2195	    ClassCount = 0;
2196            EndDivClass = EndDivClass[0];
2197	    DivClass = EndDivClass.substring(3,EndDivClass.length);
2198            EndDivNode = AllDivs[i];
2199	    RootNode = EndDivNode.parentNode;
2200            break;
2201         }
2202       }
2203   } // end while!
2204
2205
2206
2207
2208   var AllDivs = TheBody.getElementsByTagName("div"); //Convert itemize and enumerate to html lists:
2209   var DIV2LI = null;
2210
2211   for(var i=0;i<AllDivs.length;i++) {
2212      if( AllDivs[i].className=="itemize" || AllDivs[i].className=="enumerate" || AllDivs[i].className=="description")  {
2213 	    if(AllDivs[i].className=="itemize") {
2214		RootNode = document.createElement("UL");
2215            } else {
2216		RootNode = document.createElement("OL");
2217            }
2218	    RootNode.className = 'LaTeXMathML';
2219	    if(AllDivs[i].hasChildNodes()) { AllDivs[i].removeChild(AllDivs[i].firstChild) };
2220	    while(AllDivs[i].hasChildNodes()) {
2221	       if(AllDivs[i].firstChild.hasChildNodes()) {
2222		      DIV2LI = document.createElement("LI");
2223		   while(AllDivs[i].firstChild.hasChildNodes()) {
2224		      DIV2LI.appendChild(AllDivs[i].firstChild.firstChild);
2225		  }
2226		  if(DIV2LI.firstChild.className=="listitemmarker") {
2227		     DIV2LI.style.listStyleType = "none";
2228	          }
2229		  RootNode.appendChild(DIV2LI)
2230	       }
2231	       AllDivs[i].removeChild(AllDivs[i].firstChild);
2232            }
2233	    AllDivs[i].appendChild(RootNode);
2234      }
2235   }
2236
2237   // From here to 'end for AllAnchors is necessary only because CSS3 is not implemented yet.
2238   // Once CSS3 target-text is available, this can be done using CSS
2239   var AllAnchors = TheBody.getElementsByTagName("a");
2240   for(var i=0;i<AllAnchors.length;i++) {
2241      if(AllAnchors[i].className == "ref" || AllAnchors[i].className == "cite" ) {
2242         var label = AllAnchors[i].href.match(/\#(\w+)/);
2243         if(label!=null) {
2244            var labelNode = document.getElementById(label[1]);
2245            if(labelNode!=null) {
2246               var TheSpans = labelNode.getElementsByTagName("SPAN");
2247	       if(TheSpans!=null) {
2248		  var refNode = TheSpans[0].cloneNode(true);
2249    	          refNode.style.display="inline"
2250		  refNode.className = AllAnchors[i].className;
2251		  AllAnchors[i].appendChild(refNode);
2252		  //break;
2253	       }
2254            }
2255         }
2256      }
2257   } // end for AllAnchors
2258
2259   // Eventually: Collapsible Sections
2260
2261   return TheBody;
2262}
2263
2264var AMbody;
2265var AMnoMathML = false, AMtranslated = false;
2266
2267function translate(spanclassAM) {
2268  if (!AMtranslated) { // run this only once
2269     AMtranslated = true;
2270     AMinitSymbols();
2271     var LaTeXContainers = [];
2272     var AllContainers = document.getElementsByTagName('*');
2273     var ExtendName = "";
2274
2275     for (var k = 0,l=0; k < AllContainers.length; k++) {
2276        ExtendName = " "+AllContainers[k].className+" ";
2277        if(ExtendName.match(/\sLaTeX\s/)!=null) {
2278           LaTeXContainers[l] = AllContainers[k];
2279           l++;
2280        }
2281     };
2282     if(LaTeXContainers.length>0) {
2283        for(var m=0;m<LaTeXContainers.length;m++) {
2284           AMbody = LaTeXContainers[m];
2285           try {
2286              AMbody = LaTeXDivsAndRefs(LaTeXpreProcess(AMbody)); //
2287           } catch(err) {
2288               alert("Unknown Error: Defaulting to Original LaTeXMathML");
2289           }
2290           if(AMbody.tagName=="PRE") {
2291              var PreChilds = document.createDocumentFragment();
2292              var DivChilds = document.createElement("DIV");
2293              while(AMbody.hasChildNodes()) {
2294                 DivChilds.appendChild(AMbody.firstChild);
2295              }
2296              PreChilds.appendChild(DivChilds);
2297              AMbody.parentNode.replaceChild(PreChilds,AMbody);
2298              AMbody = DivChilds; //Leaves empty pre -- may be useful??
2299
2300           }
2301           AMprocessNode(AMbody, false, spanclassAM);
2302        }
2303     } else { //Default to entire page
2304        AMbody = document.getElementsByTagName("body")[0];
2305        try {
2306           AMbody = LaTeXDivsAndRefs(LaTeXpreProcess(AMbody)); //
2307        } catch(err) {
2308           alert("Unknown Error: Defaulting to Original LaTeXMathML");
2309        }
2310           AMprocessNode(AMbody, false, spanclassAM);
2311     }
2312  }
2313}
2314
2315if (isIE) {
2316  // avoid adding MathPlayer info explicitly to each webpage
2317  document.write("<object id=\"mathplayer\"\
2318  classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");
2319  document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");
2320}
2321
2322// GO1.1 Generic onload by Brothercake
2323// http://www.brothercake.com/
2324//onload function (replaces the onload="translate()" in the <body> tag)
2325function generic()
2326{
2327  translate();
2328};
2329//setup onload function
2330if(typeof window.addEventListener != 'undefined')
2331{
2332  //.. gecko, safari, konqueror and standard
2333  window.addEventListener('load', generic, false);
2334}
2335else if(typeof document.addEventListener != 'undefined')
2336{
2337  //.. opera 7
2338  document.addEventListener('load', generic, false);
2339}
2340else if(typeof window.attachEvent != 'undefined')
2341{
2342  //.. win/ie
2343  window.attachEvent('onload', generic);
2344}
2345//** remove this condition to degrade older browsers
2346else
2347{
2348  //.. mac/ie5 and anything else that gets this far
2349  //if there's an existing onload function
2350  if(typeof window.onload == 'function')
2351  {
2352    //store it
2353    var existing = onload;
2354    //add new onload handler
2355    window.onload = function()
2356    {
2357      //call existing onload function
2358      existing();
2359      //call generic onload function
2360      generic();
2361    };
2362  }
2363  else
2364  {
2365    //setup onload function
2366    window.onload = generic;
2367  }
2368}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.