X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?a=blobdiff_plain;f=jsMath%2Fextensions%2FAMSmath.js;fp=jsMath%2Fextensions%2FAMSmath.js;h=19cac042612f6ef48395247435f2b00fb06f81db;hb=f084723ab17e56d39e05a8a8da8d976e670dfd42;hp=0000000000000000000000000000000000000000;hpb=b3b3c1c988e48e53f295529431d640528bb17927;p=lambda.git diff --git a/jsMath/extensions/AMSmath.js b/jsMath/extensions/AMSmath.js new file mode 100644 index 00000000..19cac042 --- /dev/null +++ b/jsMath/extensions/AMSmath.js @@ -0,0 +1,293 @@ +/* + * extensions/AMSmath.js + * + * Part of the jsMath package for mathematics on the web. + * + * This file defines most of the macros and environments from + * the amsmath LaTeX package. You can activate it by calling + * + * jsMath.Extension.Require('AMSmath'); + * + * once jsMath.js has been loaded, or by adding "extensions/AMSmath.js" + * to the loadFiles array in jsMath/easy/load.js. + * + * You may wish to load AMSsymbols.js as well, but note that it + * requires the extra msam10 and msb10 fonts that you will have + * to install on your server first. + * + * --------------------------------------------------------------------- + * + * Copyright 2007 by Davide P. Cervone + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/********************************************************************/ + +jsMath.Extension.Require("moreArrows"); + +jsMath.Package(jsMath.Parser,{ + macros: { + intI: ['Macro','\\mathchoice{\\!}{}{}{}\\!\\!\\int'], + iint: ['Macro','\\!\\!\\!\\mathop{\\,\\,\\,\\int\\intI}'], + iiint: ['Macro','\\!\\!\\!\\mathop{\\,\\,\\,\\int\\intI\\intI}'], + iiiint: ['Macro','\\!\\!\\!\\mathop{\\,\\,\\,\\int\\intI\\intI\\intI}'], + idotsint: ['Macro','\\!\\!\\mathop{\\,\\,\\int\\cdots\\int}'], + + dddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle ...}',1], + ddddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle ....}',1], + + sideset: ['Macro','\\mathop{\\rlap{\\phantom{#3}}}#1\\!{#3}#2',3], + stackrel: ['Macro','\\mathrel{\\mathop{#2}\\limits^{#1}}',2], + + boxed: ['Macro','\\fbox{$\\displaystyle{#1}$}',1], + + tag: 'HandleTag', + notag: ['Macro',''], + + substack: ['Macro','\\begin{subarray}{c}#1\\end{subarray}',1], + + varliminf: ['Macro','\\mathop{\\underline{\\raise1.5pt{\\rule{0pt}{.6em}{0pt}\\smash{\\lower1.5pt{\\rm lim}}}}}'], + varlimsup: ['Macro','\\mathop{\\overline{\\rule{0pt}{.6em}{0pt}\\smash{\\rm lim}}}'], + varinjlim: ['Macro','\\mathop{\\underrightarrow{\\rm lim}}'], + varprojlim: ['Macro','\\mathop{\\underleftarrow{\\rm lim}}'], + + DeclareMathOperator: 'HandleDeclareOp', + operatorname: 'HandleOperatorName', + + genfrac: 'Genfrac', + frac: ['Genfrac',"","","",""], + tfrac: ['Genfrac',"","","","1"], + dfrac: ['Genfrac',"","","","0"], + binom: ['Genfrac',"(",")","0pt",""], + tbinom: ['Genfrac',"(",")","0pt","1"], + dbinom: ['Genfrac',"(",")","0pt","0"], + + cfrac: 'CFrac', + + shoveleft: ['HandleShove','left'], + shoveright: ['HandleShove','right'] + }, + + environments: { + align: ['Array',null,null,'rlrlrlrlrlrl',[5/18,2,5/18,2,5/18,2,5/18,2,5/18,2,5/18],1,'D'], + 'align*': ['Array',null,null,'rlrlrlrlrlrl',[5/18,2,5/18,2,5/18,2,5/18,2,5/18,2,5/18],1,'D'], + aligned: ['Array',null,null,'rlrlrlrlrlrl',[5/18,2,5/18,2,5/18,2,5/18,2,5/18,2,5/18],1,'D'], + multline: 'Multline', + 'multline*': 'Multline', + split: ['Array',null,null,'rl',[5/18],1,'D'], + gather: ['Array',null,null,'c',null,1,'D'], + 'gather*': ['Array',null,null,'c',null,1,'D'], + gathered: ['Array',null,null,'c',null,1,'D'], + subarray: ['Array',null,null,null,[0,0,0,0],1,'S',0,.25], + smallmatrix: ['Array',null,null,'cccccccccc',[1/3,1/3,1/3,1/3,1/3,1/3,1/3,1/3,1/3,1/3],1,'S',0] + }, + + delimiter: { + '\\lvert': [4,2,0x6A,3,0x0C], + '\\rvert': [5,2,0x6A,3,0x0C], + '\\lVert': [4,2,0x6B,3,0x0D], + '\\rVert': [5,2,0x6B,3,0x0D] + }, + + /* + * Ignore the tag for now + */ + HandleTag: function (name) { + var arg = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return; + if (arg == "*") this.GetArgument(this.cmd+name); + }, + + /* + * Handle \DeclareMathOperator + */ + HandleDeclareOp: function (name) { + var limits = ""; + var cs = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return; + if (cs == "*") { + limits = "\\limits"; + cs = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return; + } + if (cs.charAt(0) == "\\") {cs = cs.substr(1)} + var op = this.GetArgument(this.cmd+name); if (this.error) return; + op = op.replace(/\*/g,'\\char{cmr10}{0x2A}').replace(/-/g,'\\char{cmr10}{0x2D}'); + jsMath.Parser.prototype.macros[cs] = ['Macro','\\mathop{\\rm '+op+'}'+limits]; + }, + + HandleOperatorName: function (name) { + var limits = "\\nolimits"; + var op = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return; + if (op == "*") { + limits = "\\limits"; + op = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return; + } + op = op.replace(/\*/g,'\\char{cmr10}{0x2A}').replace(/-/g,'\\char{cmr10}{0x2D}'); + this.string = '\\mathop{\\rm '+op+'}'+limits+this.string.slice(this.i); + this.i = 0; + }, + + /* + * Record presence of \shoveleft and \shoveright + */ + HandleShove: function (name,data) { + if (this.mlist.data.entry == null) {this.mlist.data.entry = {}} + this.mlist.data.entry.shove = data[0]; + }, + + /* + * Handle \cfrac + */ + CFrac: function (name) { + var lr = this.GetBrackets(this.cmd+name); if (this.error) return; + var num = this.GetArgument(this.cmd+name); if (this.error) return; + var den = this.GetArgument(this.cmd+name); if (this.error) return; + + num = this.Process('\\strut\\textstyle{'+num+'}'); if (this.error) return; + den = this.Process('\\strut\\textstyle{'+den+'}'); if (this.error) return; + var data = this.mlist.data; + var TeX = jsMath.Typeset.TeX(data.style,data.size); + + if (lr != "") { + if (lr != 'l' && lr != 'r') {this.Error("Illegal alignment specified in "+this.cmd+name); return} + num = jsMath.Box.Set(num,data.style,data.size); + den = jsMath.Box.Set(den,data.style,data.size); + if (num.w > den.w) { + if (lr == 'l') {den.html += jsMath.HTML.Spacer(num.w-den.w)} + else {den.html = jsMath.HTML.Spacer(num.w-den.w) + den.html} + den.w = num.w; + } else if (num.w < den.w) { + if (lr == 'l') {num.html += jsMath.HTML.Spacer(den.w-num.w)} + else {num.html = jsMath.HTML.Spacer(den.w-num.w) + num.html} + num.w = den.w; + } + } + + this.mlist.Add(jsMath.mItem.Fraction(name,num,den,TeX.default_rule_thickness)); + }, + + /* + * Implement AMS generalized fraction + */ + Genfrac: function (name,data) { + var left = data[0]; var right = data[1]; + var thickness = data[2]; var style = data[3]; + + if (left != null) {left = this.delimiter[left]} else + {left = this.GetDelimiterArg(this.cmd+name); if (this.error) return} + if (right != null) {right = this.delimiter[right]} else + {right = this.GetDelimiterArg(this.cmd+name); if (this.error) return} + if (thickness == null) {thickness = this.GetArgument(this.cmd+name); if (this.error) return} + if (style == null) {style = this.GetArgument(this.cmd+name); if (this.error) return} + + var num = this.ProcessArg(this.cmd+name); if (this.error) return; + var den = this.ProcessArg(this.cmd+name); if (this.error) return; + + if (left == "") {left = null}; if (right == "") {right = null} + if (thickness == "") { + var TeX =jsMath.Typeset.TeX(this.mlist.data.style,this.mlist.data.size); + thickness = TeX.default_rule_thickness; + } else { + thickness = this.ParseDimen(thickness,this.cmd+name,0,0); + } + + var frac = jsMath.mItem.Fraction(name,num,den,thickness,left,right); + + if (style != "") { + style = (["D","T","S","SS"])[style]; + if (style == null) {this.Error("Bad math style for "+this.cmd+name); return} + var mlist = new jsMath.mList([new jsMath.mItem('style',{style:style}),frac]); + this.mlist.Add(jsMath.mItem.Atom('inner',{type:'mlist',mlist: mlist})); + } else { + this.mlist.Add(frac); + } + }, + + /* + * Implements the multline environment + */ + Multline: function (name,delim) { + var data = this.mlist.data; + var width = this.GetBrackets(this.cmd+'begin{'+name+'}'); if (this.error) return; + var arg = this.GetEnd(name); if (this.error) return; + + var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,'D'); + parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = []; + parse.Parse(); if (parse.error) {this.Error(parse); return} + parse.HandleRow(name,1); // be sure the last row is recorded + + // + // check rows for extra columns and maximum width + // + var i; var row; var W = 0; + for (i = 0; i < parse.table.length; i++) { + row = parse.table[i]; + if (row.length > 1) { + this.Error("Rows can contain only one equation in '"+name+"' environment"); + return; + } + if (row[0].w > W) {W = row[0].w} + } + + // + // Determine width of display + // + if (width == "") {width = W+2} else { + width = this.ParseDimen(width,name,0,0); + if (width < W) {width = W} + } + + // + // Shove the top and bottom lines + // + if (parse.table.length > 1) { + parse.table[0][0].entry.shove = 'left'; + row = parse.table[parse.table.length-1]; + if (!row[0].entry.shove) {row[0].entry.shove = 'right'} + } + // + // Adjust widths of shoved lines + // + for (i = 0; i < parse.table.length; i++) { + row = parse.table[i][0]; + if (row.entry.shove && row.w < width) { + switch (row.entry.shove) { + case 'left': + row.html += jsMath.HTML.Spacer(width-row.w); + break; + + case 'right': + row.html = jsMath.HTML.Spacer(width-row.w)+row.html; + break; + } + row.w = width; + } + } + + // + // Do the layout + // + var box = jsMath.Box.Layout(data.size,parse.table); + this.mlist.Add(jsMath.mItem.Atom('ord',box)); + }, + + /* + * Get a delimiter or empty argument + */ + GetDelimiterArg: function (name) { + var c = this.trimSpaces(this.GetArgument(name)); if (this.error) return null; + if (c == "") return null; + if (this.delimiter[c]) return this.delimiter[c]; + this.Error("Missing or unrecognized delimiter for "+name); + return null; + } +}); \ No newline at end of file