+++ /dev/null
-/*
- * extensions/newcommand.js
- *
- * Part of the jsMath package for mathematics on the web.
- *
- * This file implements the \newcommand and \def macros. It will be
- * loaded automatically when needed, or can be loaded by
- *
- * jsMath.Extension.Require('newcommand');
- *
- * ---------------------------------------------------------------------
- *
- * Copyright 2005-2006 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.Package(jsMath.Parser,{
-
- macros: {
- newcommand: 'NewCommand',
- newenvironment: 'NewEnvironment',
- def: 'MacroDef'
- },
-
- /*
- * Implement \newcommand{\name}[n]{...}
- */
- NewCommand: function (name) {
- var cs = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
- var n = this.trimSpaces(this.GetBrackets(this.cmd+name)); if (this.error) return;
- var def = this.GetArgument(this.cmd+name); if (this.error) return;
- if (n == '') {n = null}
- if (cs.charAt(0) == this.cmd) {cs = cs.substr(1)}
- if (!cs.match(/^(.|[a-z]+)$/i)) {this.Error("Illegal control sequence name for "+this.cmd+name); return}
- if (n != null && !n.match(/^[0-9]+$/)) {this.Error("Illegal number of parameters specified in "+this.cmd+name); return}
- jsMath.Parser.prototype.macros[cs] = ['Macro',def,n];
- },
-
- /*
- * Implement \newenvironment{name}[n]{begincmd}{endcmd}
- */
- NewEnvironment: function (name) {
- var env = this.trimSpaces(this.GetArgument(this.cmd+name)); if (this.error) return;
- var n = this.trimSpaces(this.GetBrackets(this.cmd+name)); if (this.error) return;
- var bdef = this.GetArgument(this.cmd+name); if (this.error) return;
- var edef = this.GetArgument(this.cmd+name); if (this.error) return;
- if (n == '') {n = null}
- if (n != null && !n.match(/^[0-9]+$/)) {this.Error("Illegal number of parameters specified in "+this.cmd+name); return}
- jsMath.Parser.prototype.environments[env] = ['Environment',bdef,edef,n];
- },
-
- /*
- * Implement \def command
- */
- MacroDef: function (name) {
- var cs = this.GetCSname(this.cmd+name); if (this.error) return;
- var params = this.GetTemplate(this.cmd+name); if (this.error) return;
- var def = this.GetArgument(this.cmd+name); if (this.error) return;
- if (typeof(params) == 'number') {
- jsMath.Parser.prototype.macros[cs] = ['Macro',def,params];
- } else {
- jsMath.Parser.prototype.macros[cs] = ['MacroWithTemplate',def,params[0],params[1]];
- }
- },
-
- /*
- * Get a CS name or give an error
- */
- GetCSname: function (cmd) {
- var c = this.GetNext();
- if (c != this.cmd) {this.Error(cmd+" must be followed by a control sequence"); return null}
- var cs = this.trimSpaces(this.GetArgument(cmd)); if (this.error) {return null};
- return cs.substr(1);
- },
-
- /*
- * Get a \def parameter template
- */
- GetTemplate: function (cmd) {
- var c; var params = []; var n = 0;
- c = this.GetNext(); var i = this.i;
- while (this.i < this.string.length) {
- c = this.GetNext();
- if (c == '#') {
- if (i != this.i) {params[n] = this.string.substr(i,this.i-i)}
- c = this.string.charAt(++this.i);
- if (!c.match(/[1-9]/)) {this.Error("Illegal use of # in "+cmd); return null}
- if (1*c != ++n) {this.Error("Parameters must be numbered sequentially"); return null}
- i = this.i+1;
- } else if (c == '{') {
- if (i != this.i) {params[n] = this.string.substr(i,this.i-i)}
- if (params.length > 0) {return [n,params]} else {return n}
- }
- this.i++;
- }
- this.Error("Missing replacement string for definition of "+cmd);
- return null;
- },
-
- /*
- * Process a macro with a parameter template
- */
- MacroWithTemplate: function (name,data) {
- var text = data[0];
- var n = data[1]; var params = data[2];
- if (n) {
- var args = []; var c = this.GetNext();
- if (params[0] && !this.MatchParam(params[0]))
- {this.Error("Use of "+this.cmd+name+" doesn't match its definition"); return}
- for (var i = 0; i < n; i++) {
- args[args.length] = this.GetParameter(this.cmd+name,params[i+1]);
- if (this.error) return;
- }
- text = this.SubstituteArgs(args,text);
- }
- this.string = this.AddArgs(text,this.string.slice(this.i));
- this.i = 0;
- },
-
- /*
- * Process a user-defined environment
- */
- Environment: function (name,data) {
- var bdef = data[0]; var edef = data[1]; var n = data[2];
- if (n) {
- var args = [];
- for (var i = 0; i < n; i++) {
- args[args.length] = this.GetArgument(this.cmd+"begin{"+name+"}"); if (this.error) return;
- }
- bdef = this.SubstituteArgs(args,bdef);
- }
- var text = this.GetEnd(name); if (this.error) return;
- text = this.AddArgs(this.AddArgs(bdef,text),edef);
- this.string = this.AddArgs(text,this.string.slice(this.i));
- this.i = 0;
- },
-
- /*
- * Find a single parameter delimited by a trailing template
- */
- GetParameter: function (name,param) {
- if (param == null) {return this.GetArgument(name)}
- var i = this.i; var j = 0; var hasBraces = 0;
- while (this.i < this.string.length) {
- if (this.string.charAt(this.i) == '{') {
- if (this.i == i) {hasBraces = 1}
- this.GetArgument(name); j = this.i - i;
- } else if (this.MatchParam(param)) {
- if (hasBraces) {i++; j -= 2}
- return this.string.substr(i,j);
- } else {
- this.i++; j++; hasBraces = 0;
- }
- }
- this.Error("Runaway argument for "+name+"?");
- return null;
- },
-
- /*
- * Check if a template is at the current location.
- * (The match must be exact, with no spacing differences. TeX is
- * a little more forgiving about spaces after macro names)
- */
- MatchParam: function (param) {
- if (this.string.substr(this.i,param.length) != param) {return 0}
- this.i += param.length;
- return 1;
- }
-
-});
-
-/*
- * Define a jsMath.Environment() command similar to the
- * jsMath.Macro() command.
- *
- * Usage: jsMath.Environment(name,begin,end[,n])
- *
- * where "name" is the name of the environment, "begin" is the
- * text that replaces the \begin{name} and "end" is the text that
- * replaces the \end{name}. If "n" is provided, it is the number
- * of parameters that the \begin{name} accepts, and these are
- * used to replace #1, #2, etc within the "begin" text.
- */
-
-jsMath.Add(jsMath,{
- Environment: function (name) {
- var environments = jsMath.Parser.prototype.environments;
- environments[name] = ['Environment'];
- for (var i = 1; i < arguments.length; i++)
- {environments[name][environments[name].length] = arguments[i]}
- }
-});