4This file contains JavaScript functions to convert ASCII math notation
5to Presentation MathML. The conversion is done while the (X)HTML page
6loads, and should work with Firefox/Mozilla/Netscape 7+ and Internet
7Explorer 6+MathPlayer (http://www.dessci.com/en/products/mathplayer/).
8Just add the next line to your (X)HTML page with this file in the same folder:
9<script type="text/javascript" src="ASCIIMathML.js"></script>
10This is a convenient and inexpensive solution for authoring MathML.
12Version 1.4.7 Dec 15, 2005, (c) Peter Jipsen http://www.chapman.edu/~jipsen
13Latest version at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML.js
14For changes see http://www.chapman.edu/~jipsen/mathml/asciimathchanges.txt
15If you use it on a webpage, please send the URL to jipsen@chapman.edu
17Modified July 2006 by John MacFarlane (added CODE to list of contexts
18in which replacement does not occur, modified AMisMathMLAvailable
19to better identify Safari browser).
21This program is free software; you can redistribute it and/or modify
22it under the terms of the GNU General Public License as published by
23the Free Software Foundation; either version 2 of the License, or (at
24your option) any later version.
26This program is distributed in the hope that it will be useful,
27but WITHOUT ANY WARRANTY; without even the implied warranty of
28MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29General Public License (at http://www.gnu.org/copyleft/gpl.html)
33var checkForMathML = true; // check if browser can display MathML
34var notifyIfNoMathML = true; // display note if no MathML capability
35var alertIfNoMathML = false; // show alert box if no MathML capability
36var mathcolor = "red"; // change it to "" (to inherit) or any other color
37var mathfontfamily = "serif"; // change to "" to inherit (works in IE)
38 // or another family (e.g. "arial")
39var displaystyle = true; // puts limits above and below large operators
40var showasciiformulaonhover = true; // helps students learn ASCIIMath
41var decimalsign = "."; // change to "," if you like, beware of `(1,2)`!
42var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters
43var AMdelimiter2 = "$", AMescape2 = "\\\\\\$", AMdelimiter2regexp = "\\$";
44var doubleblankmathdelimiter = false; // if true, x+1 is equal to `x+1`
45 // for IE this works only in <!-- -->
46//var separatetokens;// has been removed (email me if this is a problem)
47var isIE = document.createElementNS==null;
49if (document.getElementById==null)
50 alert("This webpage requires a recent browser such as\
51\nMozilla/Netscape 7+ or Internet Explorer 6+MathPlayer")
53// all further global variables start with "AM"
55function AMcreateElementXHTML(t) {
56 if (isIE) return document.createElement(t);
57 else return document.createElementNS("http://www.w3.org/1999/xhtml",t);
60function AMnoMathMLNote() {
61 var nd = AMcreateElementXHTML("h3");
62 nd.setAttribute("align","center")
63 nd.appendChild(AMcreateElementXHTML("p"));
64 nd.appendChild(document.createTextNode("To view the "));
65 var an = AMcreateElementXHTML("a");
66 an.appendChild(document.createTextNode("ASCIIMathML"));
67 an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html");
69 nd.appendChild(document.createTextNode(" notation use Internet Explorer 6+"));
70 an = AMcreateElementXHTML("a");
71 an.appendChild(document.createTextNode("MathPlayer"));
72 an.setAttribute("href","http://www.dessci.com/en/products/mathplayer/download.htm");
74 nd.appendChild(document.createTextNode(" or Netscape/Mozilla/Firefox"));
75 nd.appendChild(AMcreateElementXHTML("p"));
79function AMisMathMLavailable() {
80 var regex = /KHTML/; /* This line and the next two modified by JM for better Safari detection */
81 if (navigator.appName.slice(0,8)=="Netscape")
82 if (navigator.appVersion.slice(0,1)>="5" && !regex.test(navigator.userAgent)) return null;
83 else return AMnoMathMLNote();
84 else if (navigator.appName.slice(0,9)=="Microsoft")
86 var ActiveX = new ActiveXObject("MathPlayer.Factory.1");
89 return AMnoMathMLNote();
91 else return AMnoMathMLNote();
94// character lists for Mozilla/Netscape fonts
95var AMcal = [0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];
96var AMfrk = [0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];
97var AMbbb = [0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];
99var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,
100 RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,
101 LEFTRIGHT = 9, TEXT = 10; // token types
103var AMsqrt = {input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY},
104 AMroot = {input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY},
105 AMfrac = {input:"frac", tag:"mfrac", output:"/", tex:null, ttype:BINARY},
106 AMdiv = {input:"/", tag:"mfrac", output:"/", tex:null, ttype:INFIX},
107 AMover = {input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},
108 AMsub = {input:"_", tag:"msub", output:"_", tex:null, ttype:INFIX},
109 AMsup = {input:"^", tag:"msup", output:"^", tex:null, ttype:INFIX},
110 AMtext = {input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT},
111 AMmbox = {input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT},
112 AMquote = {input:"\"", tag:"mtext", output:"mbox", tex:null, ttype:TEXT};
116{input:"alpha", tag:"mi", output:"\u03B1", tex:null, ttype:CONST},
117{input:"beta", tag:"mi", output:"\u03B2", tex:null, ttype:CONST},
118{input:"chi", tag:"mi", output:"\u03C7", tex:null, ttype:CONST},
119{input:"delta", tag:"mi", output:"\u03B4", tex:null, ttype:CONST},
120{input:"Delta", tag:"mo", output:"\u0394", tex:null, ttype:CONST},
121{input:"epsi", tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST},
122{input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST},
123{input:"eta", tag:"mi", output:"\u03B7", tex:null, ttype:CONST},
124{input:"gamma", tag:"mi", output:"\u03B3", tex:null, ttype:CONST},
125{input:"Gamma", tag:"mo", output:"\u0393", tex:null, ttype:CONST},
126{input:"iota", tag:"mi", output:"\u03B9", tex:null, ttype:CONST},
127{input:"kappa", tag:"mi", output:"\u03BA", tex:null, ttype:CONST},
128{input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},
129{input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},
130{input:"mu", tag:"mi", output:"\u03BC", tex:null, ttype:CONST},
131{input:"nu", tag:"mi", output:"\u03BD", tex:null, ttype:CONST},
132{input:"omega", tag:"mi", output:"\u03C9", tex:null, ttype:CONST},
133{input:"Omega", tag:"mo", output:"\u03A9", tex:null, ttype:CONST},
134{input:"phi", tag:"mi", output:"\u03C6", tex:null, ttype:CONST},
135{input:"varphi", tag:"mi", output:"\u03D5", tex:null, ttype:CONST},
136{input:"Phi", tag:"mo", output:"\u03A6", tex:null, ttype:CONST},
137{input:"pi", tag:"mi", output:"\u03C0", tex:null, ttype:CONST},
138{input:"Pi", tag:"mo", output:"\u03A0", tex:null, ttype:CONST},
139{input:"psi", tag:"mi", output:"\u03C8", tex:null, ttype:CONST},
140{input:"Psi", tag:"mi", output:"\u03A8", tex:null, ttype:CONST},
141{input:"rho", tag:"mi", output:"\u03C1", tex:null, ttype:CONST},
142{input:"sigma", tag:"mi", output:"\u03C3", tex:null, ttype:CONST},
143{input:"Sigma", tag:"mo", output:"\u03A3", tex:null, ttype:CONST},
144{input:"tau", tag:"mi", output:"\u03C4", tex:null, ttype:CONST},
145{input:"theta", tag:"mi", output:"\u03B8", tex:null, ttype:CONST},
146{input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST},
147{input:"Theta", tag:"mo", output:"\u0398", tex:null, ttype:CONST},
148{input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST},
149{input:"xi", tag:"mi", output:"\u03BE", tex:null, ttype:CONST},
150{input:"Xi", tag:"mo", output:"\u039E", tex:null, ttype:CONST},
151{input:"zeta", tag:"mi", output:"\u03B6", tex:null, ttype:CONST},
153//binary operation symbols
154{input:"*", tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST},
155{input:"**", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST},
156{input:"//", tag:"mo", output:"/", tex:null, ttype:CONST},
157{input:"\\\\", tag:"mo", output:"\\", tex:"backslash", ttype:CONST},
158{input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST},
159{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST},
160{input:"-:", tag:"mo", output:"\u00F7", tex:"divide", ttype:CONST},
161{input:"@", tag:"mo", output:"\u2218", tex:"circ", ttype:CONST},
162{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST},
163{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST},
164{input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST},
165{input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER},
166{input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER},
167{input:"^^", tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST},
168{input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER},
169{input:"vv", tag:"mo", output:"\u2228", tex:"vee", ttype:CONST},
170{input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER},
171{input:"nn", tag:"mo", output:"\u2229", tex:"cap", ttype:CONST},
172{input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER},
173{input:"uu", tag:"mo", output:"\u222A", tex:"cup", ttype:CONST},
174{input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER},
176//binary relation symbols
177{input:"!=", tag:"mo", output:"\u2260", tex:"ne", ttype:CONST},
178{input:":=", tag:"mo", output:":=", tex:null, ttype:CONST},
179{input:"lt", tag:"mo", output:"<", tex:null, ttype:CONST},
180{input:"<=", tag:"mo", output:"\u2264", tex:"le", ttype:CONST},
181{input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST},
182{input:">=", tag:"mo", output:"\u2265", tex:"ge", ttype:CONST},
183{input:"geq", tag:"mo", output:"\u2265", tex:null, ttype:CONST},
184{input:"-<", tag:"mo", output:"\u227A", tex:"prec", ttype:CONST},
185{input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST},
186{input:">-", tag:"mo", output:"\u227B", tex:"succ", ttype:CONST},
187{input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST},
188{input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST},
189{input:"in", tag:"mo", output:"\u2208", tex:null, ttype:CONST},
190{input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST},
191{input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST},
192{input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST},
193{input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST},
194{input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST},
195{input:"-=", tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST},
196{input:"~=", tag:"mo", output:"\u2245", tex:"cong", ttype:CONST},
197{input:"~~", tag:"mo", output:"\u2248", tex:"approx", ttype:CONST},
198{input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST},
201{input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE},
202{input:"or", tag:"mtext", output:"or", tex:null, ttype:SPACE},
203{input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST},
204{input:"=>", tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST},
205{input:"if", tag:"mo", output:"if", tex:null, ttype:SPACE},
206{input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST},
207{input:"AA", tag:"mo", output:"\u2200", tex:"forall", ttype:CONST},
208{input:"EE", tag:"mo", output:"\u2203", tex:"exists", ttype:CONST},
209{input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST},
210{input:"TT", tag:"mo", output:"\u22A4", tex:"top", ttype:CONST},
211{input:"|--", tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST},
212{input:"|==", tag:"mo", output:"\u22A8", tex:"models", ttype:CONST},
215{input:"(", tag:"mo", output:"(", tex:null, ttype:LEFTBRACKET},
216{input:")", tag:"mo", output:")", tex:null, ttype:RIGHTBRACKET},
217{input:"[", tag:"mo", output:"[", tex:null, ttype:LEFTBRACKET},
218{input:"]", tag:"mo", output:"]", tex:null, ttype:RIGHTBRACKET},
219{input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET},
220{input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET},
221{input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT},
222//{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},
223{input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET},
224{input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET},
225{input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET},
226{input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET},
227{input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true},
228{input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true},
230//miscellaneous symbols
231{input:"int", tag:"mo", output:"\u222B", tex:null, ttype:CONST},
232{input:"dx", tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION},
233{input:"dy", tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION},
234{input:"dz", tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION},
235{input:"dt", tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION},
236{input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST},
237{input:"del", tag:"mo", output:"\u2202", tex:"partial", ttype:CONST},
238{input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST},
239{input:"+-", tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST},
240{input:"O/", tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST},
241{input:"oo", tag:"mo", output:"\u221E", tex:"infty", ttype:CONST},
242{input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST},
243{input:"...", tag:"mo", output:"...", tex:"ldots", ttype:CONST},
244{input:":.", tag:"mo", output:"\u2234", tex:"therefore", ttype:CONST},
245{input:"/_", tag:"mo", output:"\u2220", tex:"angle", ttype:CONST},
246{input:"\\ ", tag:"mo", output:"\u00A0", tex:null, ttype:CONST},
247{input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST},
248{input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST},
249{input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST},
250{input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST},
251{input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST},
252{input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST},
253{input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST},
254{input:"|__", tag:"mo", output:"\u230A", tex:"lfloor", ttype:CONST},
255{input:"__|", tag:"mo", output:"\u230B", tex:"rfloor", ttype:CONST},
256{input:"|~", tag:"mo", output:"\u2308", tex:"lceiling", ttype:CONST},
257{input:"~|", tag:"mo", output:"\u2309", tex:"rceiling", ttype:CONST},
258{input:"CC", tag:"mo", output:"\u2102", tex:null, ttype:CONST},
259{input:"NN", tag:"mo", output:"\u2115", tex:null, ttype:CONST},
260{input:"QQ", tag:"mo", output:"\u211A", tex:null, ttype:CONST},
261{input:"RR", tag:"mo", output:"\u211D", tex:null, ttype:CONST},
262{input:"ZZ", tag:"mo", output:"\u2124", tex:null, ttype:CONST},
263{input:"f", tag:"mi", output:"f", tex:null, ttype:UNARY, func:true},
264{input:"g", tag:"mi", output:"g", tex:null, ttype:UNARY, func:true},
267{input:"lim", tag:"mo", output:"lim", tex:null, ttype:UNDEROVER},
268{input:"Lim", tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER},
269{input:"sin", tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true},
270{input:"cos", tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true},
271{input:"tan", tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true},
272{input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true},
273{input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true},
274{input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true},
275{input:"cot", tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true},
276{input:"sec", tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true},
277{input:"csc", tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true},
278{input:"log", tag:"mo", output:"log", tex:null, ttype:UNARY, func:true},
279{input:"ln", tag:"mo", output:"ln", tex:null, ttype:UNARY, func:true},
280{input:"det", tag:"mo", output:"det", tex:null, ttype:UNARY, func:true},
281{input:"dim", tag:"mo", output:"dim", tex:null, ttype:CONST},
282{input:"mod", tag:"mo", output:"mod", tex:null, ttype:CONST},
283{input:"gcd", tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true},
284{input:"lcm", tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true},
285{input:"lub", tag:"mo", output:"lub", tex:null, ttype:CONST},
286{input:"glb", tag:"mo", output:"glb", tex:null, ttype:CONST},
287{input:"min", tag:"mo", output:"min", tex:null, ttype:UNDEROVER},
288{input:"max", tag:"mo", output:"max", tex:null, ttype:UNDEROVER},
291{input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST},
292{input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST},
293{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST},
294{input:"->", tag:"mo", output:"\u2192", tex:"to", ttype:CONST},
295{input:"|->", tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST},
296{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST},
297{input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST},
298{input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST},
299{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST},
300{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST},
302//commands with argument
303AMsqrt, AMroot, AMfrac, AMdiv, AMover, AMsub, AMsup,
304{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true},
305{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true},
306{input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true},
307{input:"dot", tag:"mover", output:".", tex:null, ttype:UNARY, acc:true},
308{input:"ddot", tag:"mover", output:"..", tex:null, ttype:UNARY, acc:true},
309{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true},
310AMtext, AMmbox, AMquote,
311{input:"bb", tag:"mstyle", atname:"fontweight", atval:"bold", output:"bb", tex:null, ttype:UNARY},
312{input:"mathbf", tag:"mstyle", atname:"fontweight", atval:"bold", output:"mathbf", tex:null, ttype:UNARY},
313{input:"sf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY},
314{input:"mathsf", tag:"mstyle", atname:"fontfamily", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY},
315{input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb},
316{input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb},
317{input:"cc", tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal},
318{input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal},
319{input:"tt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"tt", tex:null, ttype:UNARY},
320{input:"mathtt", tag:"mstyle", atname:"fontfamily", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY},
321{input:"fr", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk},
322{input:"mathfrak", tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk}
325function compareNames(s1,s2) {
326 if (s1.input > s2.input) return 1
330var AMnames = []; //list of input symbols
332function AMinitSymbols() {
333 var texsymbols = [], i;
334 for (i=0; i<AMsymbols.length; i++)
335 if (AMsymbols[i].tex)
336 texsymbols[texsymbols.length] = {input:AMsymbols[i].tex,
337 tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype};
338 AMsymbols = AMsymbols.concat(texsymbols);
339 AMsymbols.sort(compareNames);
340 for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;
343var AMmathml = "http://www.w3.org/1998/Math/MathML";
345function AMcreateElementMathML(t) {
346 if (isIE) return document.createElement("m:"+t);
347 else return document.createElementNS(AMmathml,t);
350function AMcreateMmlNode(t,frag) {
351// var node = AMcreateElementMathML(name);
352 if (isIE) var node = document.createElement("m:"+t);
353 else var node = document.createElementNS(AMmathml,t);
354 node.appendChild(frag);
358function newcommand(oldstr,newstr) {
359 AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr,
360 tex:null, ttype:DEFINITION}]);
363function AMremoveCharsAndBlanks(str,n) {
364//remove n characters and any following blanks
366 if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ")
368 else st = str.slice(n);
369 for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);
373function AMposition(arr, str, n) {
374// return position >=n where str appears or would be inserted
375// assumes arr is sorted
382 if (arr[m]<str) n = m; else h = m;
386 for (var i=n; i<arr.length && arr[i]<str; i++);
387 return i; // i=arr.length || arr[i]>=str
390function AMgetSymbol(str) {
391//return maximal initial substring of str that appears in names
392//return null if there is none
400 for (var i=1; i<=str.length && more; i++) {
401 st = str.slice(0,i); //initial substring of length i
403 k = AMposition(AMnames, st, j);
404 if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){
409 more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];
411 AMpreviousSymbol=AMcurrentSymbol;
413 AMcurrentSymbol=AMsymbols[mk].ttype;
414 return AMsymbols[mk];
416// if str[0] is a digit or - return maxsubstring of digits.digits
417 AMcurrentSymbol=CONST;
421 while ("0"<=st && st<="9" && k<=str.length) {
422 st = str.slice(k,k+1);
425 if (st == decimalsign) {
426 st = str.slice(k,k+1);
427 if ("0"<=st && st<="9") {
430 while ("0"<=st && st<="9" && k<=str.length) {
431 st = str.slice(k,k+1);
436 if ((integ && k>1) || k>2) {
437 st = str.slice(0,k-1);
441 st = str.slice(0,1); //take 1 character
442 tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");
444 if (st=="-" && AMpreviousSymbol==INFIX) {
445 AMcurrentSymbol = INFIX; //trick "/" into recognizing "-" on second parse
446 return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};
448 return {input:st, tag:tagst, output:st, ttype:CONST};
451function AMremoveBrackets(node) {
453 if (node.nodeName=="mrow") {
454 st = node.firstChild.firstChild.nodeValue;
455 if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild);
457 if (node.nodeName=="mrow") {
458 st = node.lastChild.firstChild.nodeValue;
459 if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild);
463/*Parsing ASCII math expressions with the following grammar
464v ::= [A-Za-z] | greek letters | numbers | other constant symbols
465u ::= sqrt | text | bb | other unary symbols for font commands
466b ::= frac | root | stackrel binary symbols
467l ::= ( | [ | { | (: | {: left brackets
468r ::= ) | ] | } | :) | :} right brackets
469S ::= v | lEr | uS | bSS Simple expression
470I ::= S_S | S^S | S_S^S | S Intermediate expression
471E ::= IE | I/I Expression
472Each terminal symbol is translated into a corresponding mathml node.*/
474var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;
476function AMparseSexpr(str) { //parses str and returns [node,tailstr]
477 var symbol, node, result, i, st,// rightvert = false,
478 newFrag = document.createDocumentFragment();
479 str = AMremoveCharsAndBlanks(str,0);
480 symbol = AMgetSymbol(str); //either a token or a bracket or empty
481 if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {
484 if (symbol.ttype == DEFINITION) {
485 str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length);
486 symbol = AMgetSymbol(str);
488 switch (symbol.ttype) {
491 str = AMremoveCharsAndBlanks(str,symbol.input.length);
492 return [AMcreateMmlNode(symbol.tag, //its a constant
493 document.createTextNode(symbol.output)),str];
494 case LEFTBRACKET: //read (expr+)
496 str = AMremoveCharsAndBlanks(str,symbol.input.length);
497 result = AMparseExpr(str,true);
499 if (typeof symbol.invisible == "boolean" && symbol.invisible)
500 node = AMcreateMmlNode("mrow",result[0]);
502 node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));
503 node = AMcreateMmlNode("mrow",node);
504 node.appendChild(result[0]);
506 return [node,result[1]];
508 if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);
509 if (str.charAt(0)=="{") i=str.indexOf("}");
510 else if (str.charAt(0)=="(") i=str.indexOf(")");
511 else if (str.charAt(0)=="[") i=str.indexOf("]");
512 else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1;
514 if (i==-1) i = str.length;
516 if (st.charAt(0) == " ") {
517 node = AMcreateElementMathML("mspace");
518 node.setAttribute("width","1ex");
519 newFrag.appendChild(node);
522 AMcreateMmlNode(symbol.tag,document.createTextNode(st)));
523 if (st.charAt(st.length-1) == " ") {
524 node = AMcreateElementMathML("mspace");
525 node.setAttribute("width","1ex");
526 newFrag.appendChild(node);
528 str = AMremoveCharsAndBlanks(str,i+1);
529 return [AMcreateMmlNode("mrow",newFrag),str];
531 str = AMremoveCharsAndBlanks(str,symbol.input.length);
532 result = AMparseSexpr(str);
533 if (result[0]==null) return [AMcreateMmlNode(symbol.tag,
534 document.createTextNode(symbol.output)),str];
535 if (typeof symbol.func == "boolean" && symbol.func) { // functions hack
537 if (st=="^" || st=="_" || st=="/" || st=="|" || st==",") {
538 return [AMcreateMmlNode(symbol.tag,
539 document.createTextNode(symbol.output)),str];
541 node = AMcreateMmlNode("mrow",
542 AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));
543 node.appendChild(result[0]);
544 return [node,result[1]];
547 AMremoveBrackets(result[0]);
548 if (symbol.input == "sqrt") { // sqrt
549 return [AMcreateMmlNode(symbol.tag,result[0]),result[1]];
550 } else if (typeof symbol.acc == "boolean" && symbol.acc) { // accent
551 node = AMcreateMmlNode(symbol.tag,result[0]);
552 node.appendChild(AMcreateMmlNode("mo",document.createTextNode(symbol.output)));
553 return [node,result[1]];
554 } else { // font change command
555 if (!isIE && typeof symbol.codes != "undefined") {
556 for (i=0; i<result[0].childNodes.length; i++)
557 if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {
558 st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:
559 result[0].childNodes[i].firstChild.nodeValue);
561 for (var j=0; j<st.length; j++)
562 if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) newst = newst +
563 String.fromCharCode(symbol.codes[st.charCodeAt(j)-65]);
564 else newst = newst + st.charAt(j);
565 if (result[0].nodeName=="mi")
566 result[0]=AMcreateElementMathML("mo").
567 appendChild(document.createTextNode(newst));
568 else result[0].replaceChild(AMcreateElementMathML("mo").
569 appendChild(document.createTextNode(newst)),result[0].childNodes[i]);
572 node = AMcreateMmlNode(symbol.tag,result[0]);
573 node.setAttribute(symbol.atname,symbol.atval);
574 return [node,result[1]];
577 str = AMremoveCharsAndBlanks(str,symbol.input.length);
578 result = AMparseSexpr(str);
579 if (result[0]==null) return [AMcreateMmlNode("mo",
580 document.createTextNode(symbol.input)),str];
581 AMremoveBrackets(result[0]);
582 var result2 = AMparseSexpr(result[1]);
583 if (result2[0]==null) return [AMcreateMmlNode("mo",
584 document.createTextNode(symbol.input)),str];
585 AMremoveBrackets(result2[0]);
586 if (symbol.input=="root" || symbol.input=="stackrel")
587 newFrag.appendChild(result2[0]);
588 newFrag.appendChild(result[0]);
589 if (symbol.input=="frac") newFrag.appendChild(result2[0]);
590 return [AMcreateMmlNode(symbol.tag,newFrag),result2[1]];
592 str = AMremoveCharsAndBlanks(str,symbol.input.length);
593 return [AMcreateMmlNode("mo",document.createTextNode(symbol.output)),str];
595 str = AMremoveCharsAndBlanks(str,symbol.input.length);
596 node = AMcreateElementMathML("mspace");
597 node.setAttribute("width","1ex");
598 newFrag.appendChild(node);
600 AMcreateMmlNode(symbol.tag,document.createTextNode(symbol.output)));
601 node = AMcreateElementMathML("mspace");
602 node.setAttribute("width","1ex");
603 newFrag.appendChild(node);
604 return [AMcreateMmlNode("mrow",newFrag),str];
606// if (rightvert) return [null,str]; else rightvert = true;
608 str = AMremoveCharsAndBlanks(str,symbol.input.length);
609 result = AMparseExpr(str,false);
612 if (result[0].lastChild!=null)
613 st = result[0].lastChild.firstChild.nodeValue;
614 if (st == "|") { // its an absolute value subterm
615 node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));
616 node = AMcreateMmlNode("mrow",node);
617 node.appendChild(result[0]);
618 return [node,result[1]];
619 } else { // the "|" is a \mid
620 node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));
621 node = AMcreateMmlNode("mrow",node);
626 str = AMremoveCharsAndBlanks(str,symbol.input.length);
627 return [AMcreateMmlNode(symbol.tag, //its a constant
628 document.createTextNode(symbol.output)),str];
632function AMparseIexpr(str) {
633 var symbol, sym1, sym2, node, result, underover;
634 str = AMremoveCharsAndBlanks(str,0);
635 sym1 = AMgetSymbol(str);
636 result = AMparseSexpr(str);
639 symbol = AMgetSymbol(str);
640 if (symbol.ttype == INFIX && symbol.input != "/") {
641 str = AMremoveCharsAndBlanks(str,symbol.input.length);
642// if (symbol.input == "/") result = AMparseIexpr(str); else ...
643 result = AMparseSexpr(str);
644 if (result[0] == null) // show box in place of missing argument
645 result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1"));
646 else AMremoveBrackets(result[0]);
648// if (symbol.input == "/") AMremoveBrackets(node);
649 if (symbol.input == "_") {
650 sym2 = AMgetSymbol(str);
651 underover = (sym1.ttype == UNDEROVER);
652 if (sym2.input == "^") {
653 str = AMremoveCharsAndBlanks(str,sym2.input.length);
654 var res2 = AMparseSexpr(str);
655 AMremoveBrackets(res2[0]);
657 node = AMcreateMmlNode((underover?"munderover":"msubsup"),node);
658 node.appendChild(result[0]);
659 node.appendChild(res2[0]);
660 node = AMcreateMmlNode("mrow",node); // so sum does not stretch
662 node = AMcreateMmlNode((underover?"munder":"msub"),node);
663 node.appendChild(result[0]);
666 node = AMcreateMmlNode(symbol.tag,node);
667 node.appendChild(result[0]);
673function AMparseExpr(str,rightbracket) {
674 var symbol, node, result, i, nodeList = [],
675 newFrag = document.createDocumentFragment();
677 str = AMremoveCharsAndBlanks(str,0);
678 result = AMparseIexpr(str);
681 symbol = AMgetSymbol(str);
682 if (symbol.ttype == INFIX && symbol.input == "/") {
683 str = AMremoveCharsAndBlanks(str,symbol.input.length);
684 result = AMparseIexpr(str);
685 if (result[0] == null) // show box in place of missing argument
686 result[0] = AMcreateMmlNode("mo",document.createTextNode("\u25A1"));
687 else AMremoveBrackets(result[0]);
689 AMremoveBrackets(node);
690 node = AMcreateMmlNode(symbol.tag,node);
691 node.appendChild(result[0]);
692 newFrag.appendChild(node);
693 symbol = AMgetSymbol(str);
695 else if (node!=undefined) newFrag.appendChild(node);
696 } while ((symbol.ttype != RIGHTBRACKET &&
697 (symbol.ttype != LEFTRIGHT || rightbracket)
698 || AMnestingDepth == 0) && symbol!=null && symbol.output!="");
699 if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {
700// if (AMnestingDepth > 0) AMnestingDepth--;
701 var len = newFrag.childNodes.length;
702 if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow" && len>1 &&
703 newFrag.childNodes[len-2].nodeName == "mo" &&
704 newFrag.childNodes[len-2].firstChild.nodeValue == ",") { //matrix
705 var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;
706 if (right==")" || right=="]") {
707 var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;
708 if (left=="(" && right==")" && symbol.output != "}" ||
709 left=="[" && right=="]") {
710 var pos = []; // positions of commas
712 var m = newFrag.childNodes.length;
713 for (i=0; matrix && i<m; i=i+2) {
715 node = newFrag.childNodes[i];
716 if (matrix) matrix = node.nodeName=="mrow" &&
717 (i==m-1 || node.nextSibling.nodeName=="mo" &&
718 node.nextSibling.firstChild.nodeValue==",")&&
719 node.firstChild.firstChild.nodeValue==left &&
720 node.lastChild.firstChild.nodeValue==right;
722 for (var j=0; j<node.childNodes.length; j++)
723 if (node.childNodes[j].firstChild.nodeValue==",")
724 pos[i][pos[i].length]=j;
725 if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;
728 var row, frag, n, k, table = document.createDocumentFragment();
729 for (i=0; i<m; i=i+2) {
730 row = document.createDocumentFragment();
731 frag = document.createDocumentFragment();
732 node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>
733 n = node.childNodes.length;
735 node.removeChild(node.firstChild); //remove (
736 for (j=1; j<n-1; j++) {
737 if (typeof pos[i][k] != "undefined" && j==pos[i][k]){
738 node.removeChild(node.firstChild); //remove ,
739 row.appendChild(AMcreateMmlNode("mtd",frag));
741 } else frag.appendChild(node.firstChild);
743 row.appendChild(AMcreateMmlNode("mtd",frag));
744 if (newFrag.childNodes.length>2) {
745 newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>
746 newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>
748 table.appendChild(AMcreateMmlNode("mtr",row));
750 node = AMcreateMmlNode("mtable",table);
751 if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left");
752 newFrag.replaceChild(node,newFrag.firstChild);
757 str = AMremoveCharsAndBlanks(str,symbol.input.length);
758 if (typeof symbol.invisible != "boolean" || !symbol.invisible) {
759 node = AMcreateMmlNode("mo",document.createTextNode(symbol.output));
760 newFrag.appendChild(node);
763 return [newFrag,str];
766function AMparseMath(str) {
767 var result, node = AMcreateElementMathML("mstyle");
768 if (mathcolor != "") node.setAttribute("mathcolor",mathcolor);
769 if (displaystyle) node.setAttribute("displaystyle","true");
770 if (mathfontfamily != "") node.setAttribute("fontfamily",mathfontfamily);
772 node.appendChild(AMparseExpr(str.replace(/^\s+/g,""),false)[0]);
773 node = AMcreateMmlNode("math",node);
774 if (showasciiformulaonhover) //fixed by djhsu so newline
775 node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko
776 if (mathfontfamily != "" && (isIE || mathfontfamily != "serif")) {
777 var fnode = AMcreateElementXHTML("font");
778 fnode.setAttribute("face",mathfontfamily);
779 fnode.appendChild(node);
785function AMstrarr2docFrag(arr, linebreaks) {
786 var newFrag=document.createDocumentFragment();
788 for (var i=0; i<arr.length; i++) {
789 if (expr) newFrag.appendChild(AMparseMath(arr[i]));
791 var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);
792 newFrag.appendChild(AMcreateElementXHTML("span").
793 appendChild(document.createTextNode(arri[0])));
794 for (var j=1; j<arri.length; j++) {
795 newFrag.appendChild(AMcreateElementXHTML("p"));
796 newFrag.appendChild(AMcreateElementXHTML("span").
797 appendChild(document.createTextNode(arri[j])));
805function AMprocessNodeR(n, linebreaks) {
806 var mtch, str, arr, frg, i;
807 if (n.childNodes.length == 0) {
808 if ((n.nodeType!=8 || linebreaks) &&
809 n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&
810 n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" &&
811 n.parentNode.nodeName!="code" && n.parentNode.nodeName!="CODE" && /* added by JM */
812 n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE") {
814 if (!(str == null)) {
815 str = str.replace(/\r\n\r\n/g,"\n\n");
816 if (doubleblankmathdelimiter) {
817 str = str.replace(/\x20\x20\./g," "+AMdelimiter1+".");
818 str = str.replace(/\x20\x20,/g," "+AMdelimiter1+",");
819 str = str.replace(/\x20\x20/g," "+AMdelimiter1+" ");
821 str = str.replace(/\x20+/g," ");
822 str = str.replace(/\s*\r\n/g," ");
824 str = str.replace(new RegExp(AMescape2, "g"),
825 function(st){mtch=true;return "AMescape2"});
826 str = str.replace(new RegExp(AMescape1, "g"),
827 function(st){mtch=true;return "AMescape1"});
828 str = str.replace(new RegExp(AMdelimiter2regexp, "g"),AMdelimiter1);
829 arr = str.split(AMdelimiter1);
830 for (i=0; i<arr.length; i++)
831 arr[i]=arr[i].replace(/AMescape2/g,AMdelimiter2).
832 replace(/AMescape1/g,AMdelimiter1);
833 if (arr.length>1 || mtch) {
834 if (checkForMathML) {
835 checkForMathML = false;
836 var nd = AMisMathMLavailable();
837 AMnoMathML = nd != null;
838 if (AMnoMathML && notifyIfNoMathML)
840 alert("To view the ASCIIMathML notation use Internet Explorer 6 +\nMathPlayer (free from www.dessci.com)\n\
841 or Firefox/Mozilla/Netscape");
842 else AMbody.insertBefore(nd,AMbody.childNodes[0]);
845 frg = AMstrarr2docFrag(arr,n.nodeType==8);
846 var len = frg.childNodes.length;
847 n.parentNode.replaceChild(frg,n);
853 } else if (n.nodeName!="math") {
854 for (i=0; i<n.childNodes.length; i++)
855 i += AMprocessNodeR(n.childNodes[i], linebreaks);
860function AMprocessNode(n, linebreaks, spanclassAM) {
862 if (spanclassAM!=null) {
863 frag = document.getElementsByTagName("span")
864 for (var i=0;i<frag.length;i++)
865 if (frag[i].className == "AM")
866 AMprocessNodeR(frag[i],linebreaks);
872 st.indexOf(AMdelimiter1)!=-1 || st.indexOf(AMdelimiter2)!=-1)
873 AMprocessNodeR(n,linebreaks);
875 if (isIE) { //needed to match size and font of formula to surrounding text
876 frag = document.getElementsByTagName('math');
877 for (var i=0;i<frag.length;i++) frag[i].update()
882var AMnoMathML = false, AMtranslated = false;
884function translate(spanclassAM) {
885 if (!AMtranslated) { // run this only once
888 AMbody = document.getElementsByTagName("body")[0];
889 AMprocessNode(AMbody, false, spanclassAM);
893if (isIE) { // avoid adding MathPlayer info explicitly to each webpage
894 document.write("<object id=\"mathplayer\"\
895 classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");
896 document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");
899// GO1.1 Generic onload by Brothercake
900// http://www.brothercake.com/
901//onload function (replaces the onload="translate()" in the <body> tag)
906//setup onload function
907if(typeof window.addEventListener != 'undefined')
909 //.. gecko, safari, konqueror and standard
910 window.addEventListener('load', generic, false);
912else if(typeof document.addEventListener != 'undefined')
915 document.addEventListener('load', generic, false);
917else if(typeof window.attachEvent != 'undefined')
920 window.attachEvent('onload', generic);
922//** remove this condition to degrade older browsers
925 //.. mac/ie5 and anything else that gets this far
926 //if there's an existing onload function
927 if(typeof window.onload == 'function')
930 var existing = onload;
931 //add new onload handler
932 window.onload = function()
934 //call existing onload function
936 //call generic onload function
942 //setup onload function
943 window.onload = generic;
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list