UNPKG

smartdown

Version:

A library for translating, rendering and interacting with Smartdown documents. Smartdown is an extension of Markdown that provides richer media support and reactive programming capability.

1,721 lines (1,657 loc) 566 kB
/************************************************************* * * MathJax/extensions/TeX/xypic.js * * Implements Xy-pic environment. * * --------------------------------------------------------------------- * * Copyright (c) 2011-2014 Isao Sonobe <sonoisa@gmail.com>. * * 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. */ (function () { var FP = MathJax.Extension.fp = { version: "0.1" }; /************ Matcher **************/ FP.Matcher = MathJax.Object.Subclass({ Init: function () { this.cases = []; }, Case: function (klass, f) { this.cases.push([klass, f]); return this; }, match: function (x) { if (x instanceof Object && "isa" in x) { var i, count, klass, op; i = 0; count = this.cases.length; while (i < count) { klass = this.cases[i][0]; if (x.isa(klass)) { op = klass.unapply(x); if (op.isDefined) { return this.cases[i][1](op.get); } } i = i + 1; } } throw FP.MatchError(x); } }); /************ Option **************/ FP.Option = MathJax.Object.Subclass({}); FP.Option.Some = FP.Option.Subclass({ Init: function (value) { this.get = value; }, isEmpty: false, isDefined: true, getOrElse: function (ignore) { return this.get; }, flatMap: function (k) { return k(this.get); }, map: function (f) { return FP.Option.Some(f(this.get)); }, foreach: function (f) { f(this.get); }, toString: function () { return "Some(" + this.get + ")"; } }, { unapply: function (x) { return FP.Option.Some(x.get); } }); FP.Option.None = FP.Option.Subclass({ Init: function () {}, isEmpty: true, isDefined: false, getOrElse: function (value) { return value; }, flatMap: function (k) { return this; }, foreach: function (f) {}, map: function (k) { return this; }, toString: function () { return "None"; } }, { unapply: function (x) { return FP.Option.Some(x); } }); FP.Option.Augment({}, { empty: FP.Option.None() }); /************ List **************/ FP.List = MathJax.Object.Subclass({}); FP.List.Cons = FP.List.Subclass({ Init: function (head, tail) { this.head = head; this.tail = tail; }, isEmpty: false, at: function (index) { if (index < 0 || index >= this.length()) { throw Error("no such element at " + index + ". index must be lower than " + this.length() + "."); } var t = this; for (var i = 0; i < index; i++) { t = t.tail; } return t.head; }, length: function () { var t = this; var l = 0; while (!t.isEmpty) { l++; t = t.tail; } return l; }, prepend: function (element) { return FP.List.Cons(element, this); }, append: function (element) { var result = FP.List.Cons(element, FP.List.empty); this.reverse().foreach(function (e) { result = FP.List.Cons(e, result); }); return result; }, concat: function (that) { var result = that; this.reverse().foreach(function (e) { result = FP.List.Cons(e, result); }); return result; }, foldLeft: function (x0, f) { var r, c; r = f(x0, this.head); c = this.tail; while (!c.isEmpty) { r = f(r, c.head); c = c.tail; } return r; }, foldRight: function (x0, f) { if (this.tail.isEmpty) { return f(this.head, x0); } else { return f(this.head, this.tail.foldRight(x0, f)); } }, map: function (f) { return FP.List.Cons(f(this.head), this.tail.map(f)); }, flatMap: function (k) { return k(this.head).concat(this.tail.flatMap(k)); }, foreach: function (f) { var e = this; while (!e.isEmpty) { f(e.head); e = e.tail; } }, reverse: function () { var r = FP.List.empty; this.foreach(function (c) { r = FP.List.Cons(c, r); }); return r; }, mkString: function () { var open, delim, close; switch (arguments.length) { case 0: open = delim = close = ""; break; case 1: delim = arguments[0]; open = close = ""; break; case 2: open = arguments[0]; delim = arguments[1]; close = ""; break; default: open = arguments[0]; delim = arguments[1]; close = arguments[2]; break; } var desc, nxt; desc = open + this.head.toString(); nxt = this.tail; while (nxt.isa(FP.List.Cons)) { desc += delim + nxt.head.toString(); nxt = nxt.tail; } desc += close; return desc; }, toString: function () { return this.mkString("[", ", ", "]"); } }, { unapply: function (x) { return FP.Option.Some([x.head, x.tail]); } }); FP.List.Nil = FP.List.Subclass({ isEmpty: true, at: function (index) { throw Error("cannot get element from an empty list."); }, length: function () { return 0; }, prepend: function (element) { return FP.List.Cons(element, FP.List.empty); }, append: function (element) { return FP.List.Cons(element, FP.List.empty); }, concat: function (that) { return that; }, foldLeft: function (x0, f) { return x0; }, foldRight: function (x0, f) { return x0; }, flatMap: function (f) { return this; }, map: function (f) { return this; }, foreach: function (f) {}, reverse: function () { return this; }, mkString: function () { switch (arguments.length) { case 0: case 1: return ""; case 2: return arguments[0] default: return arguments[0]+arguments[2]; } }, toString: function () { return '[]'; } }, { unapply: function (x) { return FP.Option.Some(x); } }); FP.List.Augment({}, { empty: FP.List.Nil(), fromArray: function (as) { var list, i; list = FP.List.empty; i = as.length - 1; while (i >= 0) { list = FP.List.Cons(as[i], list); i -= 1; } return list; } }); /************ MatchError **************/ FP.MatchError = MathJax.Object.Subclass({ Init: function (obj) { this.obj = obj; }, // getMessage: function () { // if (this.obj === null) { // return "null" // } else { // return obj.toString() + " (of class " + obj. + ")" // } // } toString: function () { return "MatchError(" + this.obj + ")"; } }); /************ OffsetPosition **************/ FP.OffsetPosition = MathJax.Object.Subclass({ Init: function (source, offset) { // assert(source.length >= offset) this.source = source; if (offset === undefined) { this.offset = 0; } else { this.offset = offset; } this._index = null; this._line = null; }, index: function () { if (this._index !== null) { return this._index; } this._index = []; this._index.push(0); var i = 0; while (i < this.source.length) { if (this.source.charAt(i) === '\n') { this._index.push(i + 1); } i += 1; } this._index.push(this.source.length); return this._index; }, line: function () { var lo, hi, mid; if (this._line !== null) { return this._line; } lo = 0; hi = this.index().length - 1; while (lo + 1 < hi) { mid = (hi + lo) >> 1; if (this.offset < this.index()[mid]) { hi = mid; } else { lo = mid; } } this._line = lo + 1; return this._line; }, column: function () { return this.offset - this.index()[this.line() - 1] + 1; }, lineContents: function () { var i, l; i = this.index(); l = this.line(); return this.source.substring(i[l - 1], i[l]); }, toString: function () { return this.line().toString() + '.' + this.column(); }, longString: function () { var desc, i; desc = this.lineContents() + '\n'; i = 0; while (i < this.column()) { if (this.lineContents().charAt(i) === '\t') { desc += '\t'; } else { desc += ' '; } i += 1; } desc += '^'; return desc; }, isLessThan: function (that) { if (that.isa(FP.OffsetPosition)) { return this.offset < that.offset; } else { return ( this.line() < that.line() || (this.line() === that.line() && this.column() < that.column()) ); } } }); /************ StringReader **************/ FP.StringReader = MathJax.Object.Subclass({ Init: function (source, offset, context) { this.source = source; this.offset = offset; this.context = context; }, first: function () { if (this.offset < this.source.length) { return this.source.charAt(this.offset); } else { return FP.StringReader.EofCh; } }, rest: function () { if (this.offset < this.source.length) { return FP.StringReader(this.source, this.offset + 1, this.context); } else { return this; } }, pos: function () { return FP.OffsetPosition(this.source, this.offset); }, atEnd: function () { return this.offset >= this.source.length; }, drop: function (n) { var r, count; r = this; count = n; while (count > 0) { r = r.rest(); count -= 1; } return r; } }, { EofCh: '\x03' }); /************ Parsers **************/ FP.Parsers = MathJax.Object.Subclass({}, { parse: function (p, input) { return p.apply(input); }, parseAll: function (p, input) { return p.andl(function () { return FP.Parsers.eos(); }).apply(input); }, parseString: function (p, str) { var input = FP.StringReader(str, 0, { lastNoSuccess: undefined }); return FP.Parsers.parse(p, input); }, parseAllString: function (p, str) { var input = FP.StringReader(str, 0, { lastNoSuccess: undefined }); return FP.Parsers.parseAll(p, input); }, _handleWhiteSpace: function (input) { var whiteSpaceRegex = input.context.whiteSpaceRegex; var source = input.source; var offset = input.offset; var m = whiteSpaceRegex.exec(source.substring(offset, source.length)); if (m !== null) { return offset + m[0].length; } else { return offset; } }, literal: function (str) { return FP.Parsers.Parser(function (input) { var source, offset, start, i, j, found; source = input.source; offset = input.offset; start = FP.Parsers._handleWhiteSpace(input); i = 0; j = start; while (i < str.length && j < source.length && str.charAt(i) === source.charAt(j)) { i += 1; j += 1; } if (i === str.length) { return FP.Parsers.Success(str, input.drop(j - offset)); } else { if (start === source.length) { found = "end of source"; } else { found = "`" + source.charAt(start) + "'"; } return FP.Parsers.Failure( "`" + str + "' expected but " + found + " found", input.drop(start - offset) ); } }); }, regex: function (rx /* must start with ^ */) { if (rx.toString().substring(0, 2) !== "/^") { throw ("regex must start with `^' but " + rx); } return FP.Parsers.Parser(function (input) { var source, offset, m, found; source = input.source; offset = input.offset; m = rx.exec(source.substring(offset, source.length)); if (m !== null) { return FP.Parsers.Success(m[0], input.drop(m[0].length)); } else { if (offset === source.length) { found = "end of source"; } else { found = "`" + source.charAt(offset) + "'"; } return FP.Parsers.Failure( "string matching regex " + rx + " expected but " + found + " found", input ); } }); }, regexLiteral: function (rx /* must start with ^ */) { if (rx.toString().substring(0, 2) !== "/^") { throw ("regex must start with `^' but " + rx); } return FP.Parsers.Parser(function (input) { var source, offset, start, m, found; source = input.source; offset = input.offset; start = FP.Parsers._handleWhiteSpace(input); m = rx.exec(source.substring(start, source.length)); if (m !== null) { return FP.Parsers.Success(m[0], input.drop(start + m[0].length - offset)); } else { if (start === source.length) { found = "end of source"; } else { found = "`" + source.charAt(start) + "'"; } return FP.Parsers.Failure( "string matching regex " + rx + " expected but " + found + " found", input.drop(start - offset) ); } }); }, eos: function () { return FP.Parsers.Parser(function (input) { var source, offset, start; source = input.source; offset = input.offset; start = FP.Parsers._handleWhiteSpace(input); if (source.length === start) { return FP.Parsers.Success("", input); } else { return FP.Parsers.Failure("end of source expected but `" + source.charAt(start) + "' found", input); } }); }, commit: function (/*lazy*/ p) { return FP.Parsers.Parser(function (input) { var res = p()(input); return (FP.Matcher() .Case(FP.Parsers.Success, function (x) { return res; }) .Case(FP.Parsers.Error, function (x) { return res; }) .Case(FP.Parsers.Failure, function (x) { return FP.Parsers.Error(x[0], x[1]); }).match(res) ); }); }, //elem: function (kind, p) elem: function (e) { return FP.Parsers.accept(e).named('"' + e + '"'); }, accept: function (e) { return FP.Parsers.acceptIf( function (x) { return x === e; }, function (x) { return "`" + e + "' expected but `" + x + "' found"; } ); }, acceptIf: function (p, err) { return FP.Parsers.Parser(function (input) { if (p(input.first())) { return FP.Parsers.Success(input.first(), input.rest()); } else { return FP.Parsers.Failure(err(input.first()), input); } }); }, //acceptMatch: function (expected, f) //acceptSeq: function (es) failure: function (msg) { return FP.Parsers.Parser(function (input) { return FP.Parsers.Failure(msg, input); }); }, err: function (msg) { return FP.Parsers.Parser(function (input) { return FP.Parsers.Error(msg, input); }); }, success: function (v) { return FP.Parsers.Parser(function (input) { return FP.Parsers.Success(v, input); }); }, log: function (/*lazy*/ p, name) { return FP.Parsers.Parser(function (input) { console.log("trying " + name + " at " + input); var r = p().apply(input); console.log(name + " --> " + r); return r; }); }, rep: function (/*lazy*/ p) { var s = FP.Parsers.success(FP.List.empty); return FP.Parsers.rep1(p).or(function () { return s; }); }, rep1: function (/*lazy*/ p) { return FP.Parsers.Parser(function (input) { var elems, i, p0, res; elems = []; i = input; p0 = p(); res = p0.apply(input); if (res.isa(FP.Parsers.Success)) { while (res.isa(FP.Parsers.Success)) { elems.push(res.result); i = res.next; res = p0.apply(i); } return FP.Parsers.Success(FP.List.fromArray(elems), i); } else { return res; } }); }, //rep1: function (/*lazy*/ first, /*lazy*/ p) repN: function (num, /*lazy*/ p) { if (num === 0) { return FP.Parsers.success(FP.List.empty); } return FP.Parsers.Parser(function (input) { var elems, i, p0, res; elems = []; i = input; p0 = p(); res = p0.apply(i); while (res.isa(FP.Parsers.Success)) { elems.push(res.result); i = res.next; if (num === elems.length) { return FP.Parsers.Success(FP.List.fromArray(elems), i); } res = p0.apply(i); } return res; // NoSuccess }); }, repsep: function (/*lazy*/ p, /*lazy*/ q) { var s = FP.Parsers.success(FP.List.empty); return FP.Parsers.rep1sep(p, q).or(function () { return s; }); }, rep1sep: function (/*lazy*/ p, /*lazy*/ q) { return p().and(FP.Parsers.rep(q().andr(p))).to(function (res) { return FP.List.Cons(res.head, res.tail); }); }, // chainl1: function (/*lazy*/ p, /*lazy*/ q) { // return this.chainl1(p, p, q) // }, chainl1: function (/*lazy*/ first, /*lazy*/ p, /*lazy*/ q) { return first().and(FP.Parsers.rep(q().and(p))).to(function (res) { return res.tail.foldLeft(res.head, function (a, fb) { return fb.head(a, fb.tail); }); }); }, chainr1: function (/*lazy*/ p, /*lazy*/ q, combine, first) { return p().and(this.rep(q().and(p))).to(function (res) { return FP.List.Cons(FP.Parsers.Pair(combine, res.head), res.tail).foldRight(first, function (fa, b) { return fa.head(fa.tail, b); } ); }); }, opt: function (/*lazy*/ p) { return p().to(function (x) { return FP.Option.Some(x); }).or(function () { return FP.Parsers.success(FP.Option.empty); }); }, not: function (/*lazy*/ p) { return FP.Parsers.Parser(function (input) { var r = p().apply(input); if (r.successful) { return FP.Parsers.Failure("Expected failure", input); } else { return FP.Parsers.Success(FP.Option.empty, input); } }); }, guard: function (/*lazy*/ p) { return FP.Parsers.Parser(function (input) { var r = p().apply(input); if (r.successful) { return FP.Parsers.Success(r.result, input); } else { return r; } }); }, //positioned: function (/*lazy*/ p) //phrase: function (p) mkList: function (pair) { return FP.List.Cons(pair.head, pair.tail); }, fun: function (x) { return function () { return x; }; }, lazyParser: function (x) { var lit, r; if (x instanceof String || (typeof x) === "string") { lit = FP.Parsers.literal(x); return function () { return lit; }; } else if (x instanceof Function) { // x is deemed to be a function which has the return value as Parser. return x; } else if (x instanceof Object) { if("isa" in x && x.isa(FP.Parsers.Parser)) { return function () { return x; }; } else if (x instanceof RegExp) { r = FP.Parsers.regexLiteral(x); return function () { return r; }; } else { return FP.Parsers.err("unhandlable type"); } } else { return FP.Parsers.err("unhandlable type"); } }, seq: function () { var count, parser, i; count = arguments.length; if (count === 0) { return FP.Parsers.err("at least one element must be specified"); } parser = FP.Parsers.lazyParser(arguments[0])(); i = 1; while (i < count) { parser = parser.and(FP.Parsers.lazyParser(arguments[i])); i += 1; } return parser; }, or: function () { var count, parser, i; count = arguments.length; if (count === 0) { return FP.Parsers.err("at least one element must be specified"); } parser = FP.Parsers.lazyParser(arguments[0])(); i = 1; while (i < count) { parser = parser.or(FP.Parsers.lazyParser(arguments[i])); i += 1; } return parser; } }); /************ Pair **************/ FP.Parsers.Pair = MathJax.Object.Subclass({ Init: function (head, tail) { this.head = head; this.tail = tail; }, toString: function () { return '(' + this.head + '~' + this.tail + ')'; } }, { unapply: function (x) { return FP.Option.Some([x.head, x.tail]); } }); /************ ParseResult **************/ FP.Parsers.ParseResult = MathJax.Object.Subclass({ Init: function () {}, isEmpty: function () { return !this.successful; }, getOrElse: function (/*lazy*/ defaultValue) { if (this.isEmpty) { return defaultValue(); } else { return this.get(); } } }); /************ Success **************/ FP.Parsers.Success = FP.Parsers.ParseResult.Subclass({ Init: function (result, next) { this.result = result; this.next = next; }, map: function (f) { return FP.Parsers.Success(f(this.result), this.next); }, mapPartial: function (f, err) { try { return FP.Parsers.Success(f(this.result), this.next); } catch (e) { if ("isa" in e && e.isa(FP.MatchError)) { return FP.Parsers.Failure(err(this.result), this.next); } else { throw e; } } }, flatMapWithNext: function (f) { return f(this.result).apply(this.next); }, append: function (/*lazy*/ a) { return this; }, get: function () { return this.result; }, successful: true, toString: function () { return '[' + this.next.pos() + '] parsed: ' + this.result; } }, { unapply: function (x) { return FP.Option.Some([x.result, x.next]); } }); /************ NoSuccess **************/ FP.Parsers.NoSuccess = FP.Parsers.ParseResult.Subclass({ Init: function () {}, _setLastNoSuccess: function () { var context = this.next.context; if (context.lastNoSuccess === undefined || !this.next.pos().isLessThan(context.lastNoSuccess.next.pos())) { context.lastNoSuccess = this; } }, map: function (f) { return this; }, mapPartial: function (f, error) { return this; }, flatMapWithNext: function (f) { return this; }, get: function () { return FP.Parsers.error("No result when parsing failed"); }, successful: false }); /************ Failure **************/ FP.Parsers.Failure = FP.Parsers.NoSuccess.Subclass({ Init: function (msg, next) { this.msg = msg; this.next = next; this._setLastNoSuccess(); }, append: function (/*lazy*/ a) { var alt = a(); if (alt.isa(FP.Parsers.Success)) { return alt; } else if (alt.isa(FP.Parsers.NoSuccess)) { if (alt.next.pos().isLessThan(this.next.pos())) { return this; } else { return alt; } } else { throw FP.MatchError(alt); } }, toString: function () { return ('[' + this.next.pos() + '] failure: ' + this.msg + '\n\n' + this.next.pos().longString()); } }, { unapply: function (x) { return FP.Option.Some([x.msg, x.next]); } }); /************ Error **************/ FP.Parsers.Error = FP.Parsers.NoSuccess.Subclass({ Init: function (msg, next) { this.msg = msg; this.next = next; this._setLastNoSuccess(); }, append: function (/*lazy*/ a) { return this; }, toString: function () { return ('[' + this.next.pos() + '] error: ' + this.msg + '\n\n' + this.next.pos().longString()); } }, { unapply: function (x) { return FP.Option.Some([x.msg, x.next]); } }); /************ Parser **************/ FP.Parsers.Parser = MathJax.Object.Subclass({ Init: function (f) { this.apply = f; }, name: '', named: function (name) { this.name = name; return this; }, toString: function () { return 'Parser (' + this.name + ')'; }, flatMap: function (f) { var app = this.apply; return FP.Parsers.Parser(function (input) { return app(input).flatMapWithNext(f); }); }, map: function (f) { var app = this.apply; return FP.Parsers.Parser(function (input) { return app(input).map(f); }); }, append: function (/*lazy*/ p) { var app = this.apply; return FP.Parsers.Parser(function (input) { return app(input).append(function () { return p().apply(input); }); }); }, and: function (/*lazy*/ p) { return this.flatMap(function (a) { return p().map(function (b) { return FP.Parsers.Pair(a, b); }); }).named('~'); }, andr: function (/*lazy*/ p) { return this.flatMap(function (a) { return p().map(function (b) { return b; }); }).named('~>'); }, andl: function (/*lazy*/ p) { return this.flatMap(function (a) { return p().map(function (b) { return a; }); }).named('<~'); }, or: function (/*lazy*/ q) { return this.append(q).named("|"); }, andOnce: function (/*lazy*/ p) { var flatMap = this.flatMap; return FP.Parsers.OnceParser(function () { return flatMap(function (a) { return FP.Parsers.commit(p).map(function (b) { return FP.Parsers.Pair(a, b); }); }).named('~!'); }); }, longestOr: function (/*lazy*/ q0) { var app = this.apply; return FP.Parsers.Parser(function (input) { var res1, res2; res1 = app(input); res2 = q0()(input); if (res1.successful) { if (res2.successful) { if (res2.next.pos().isLessThan(res1.next.pos())) { return res1; } else { return res2; } } else { return res1; } } else if (res2.successful) { return res2; } else if (res1.isa(FP.Parsers.Error)) { return res1; } else { if (res2.next.pos().isLessThan(res1.next.pos())) { return res1; } else { return res2; } } }).named("|||"); }, to: function (f) { return this.map(f).named(this.toString() + '^^'); }, ret: function (/*lazy*/ v) { var app = this.apply; return FP.Parsers.Parser(function (input) { return app(input).map(function (x) { return v(); }); }).named(this.toString() + "^^^"); }, toIfPossible: function (f, error) { if (error === undefined) { error = function (r) { return "Constructor function not defined at " + r; }; } var app = this.apply; return FP.Parsers.Parser(function (input) { return app(input).mapPartial(f, error); }).named(this.toString() + "^?"); }, into: function (fq) { return this.flatMap(fq); }, rep: function () { var p = this; return FP.Parsers.rep(function () { return p; }); }, chain: function (/*lazy*/ sep) { var p, lp; p = this; lp = function () { return p; }; return FP.Parsers.chainl1(lp, lp, sep); }, rep1: function () { var p = this; return FP.Parsers.rep1(function () { return p; }); }, opt: function () { var p = this; return FP.Parsers.opt(function () { return p; }); } }); /************ OnceParser **************/ FP.Parsers.OnceParser = FP.Parsers.Parser.Subclass({ Init: function (f) { this.apply = f; }, and: function (p) { var flatMap = this.flatMap; return FP.Parsers.OnceParser(function () { return flatMap(function (a) { return FP.Parsers.commit(p).map(function (b) { return FP.Parsers.Pair(a, b); }); }); }).named('~'); } }); MathJax.Hub.Startup.signal.Post("Functional Programming library Ready"); })(); MathJax.Extension.xypic = { version: "0.1", constants: { whiteSpaceRegex: /^(\s+|%[^\r\n]*(\r\n|\r|\n)?)+/, unsupportedBrowserErrorMessage: "Unsupported Browser. Please open with Firefox/Safari/Chrome/Opera" }, signalHandler: { signals: [], hookedSignals: [], chains: [], chainSignal: function (successor, predecessors) { for (var i = 0; i < predecessors.length; i++) { MathJax.Extension.xypic.signalHandler.addSignal(predecessors[i]); } MathJax.Extension.xypic.signalHandler.chains.push({succ:successor, pred:predecessors}); }, addSignal: function (signal) { var signals = MathJax.Extension.xypic.signalHandler.signals; for (var i = 0; i < signals.length; i++) { if (signals[i] === signal) { return; } } MathJax.Extension.xypic.signalHandler.signals.push(signal); var handler = MathJax.Extension.xypic.signalHandler.handleSignal(signal); MathJax.Hub.Register.StartupHook(signal, handler); }, handleSignal: function (signal) { return function () { MathJax.Extension.xypic.signalHandler.hookedSignals.push(signal); MathJax.Extension.xypic.signalHandler.handleChains(); } }, handleChains: function () { var i = 0; var chains = MathJax.Extension.xypic.signalHandler.chains; var remainingChains = []; var invokableSignals = []; while (i < chains.length) { var c = chains[i]; var pred = c.pred; var invokable = true; for (var j = 0; j < pred.length; j++) { var p = pred[j]; if (!MathJax.Extension.xypic.signalHandler.listenedSignal(p)) { invokable = false; break; } } if (invokable) { invokableSignals.push(c.succ); } else { remainingChains.push(c); } i++; } MathJax.Extension.xypic.signalHandler.chains = remainingChains; for (i = 0; i < invokableSignals.length; i++) { MathJax.Hub.Startup.signal.Post(invokableSignals[i]); } }, listenedSignal: function (signal) { var signals = MathJax.Extension.xypic.signalHandler.hookedSignals; for (var i = 0; i < signals.length; i++) { if (signals[i] === signal) { return true; } } return false; } } } // "TeX Xy-pic" depends on "Functional Programming library" and "TeX Jax". MathJax.Extension.xypic.signalHandler.chainSignal("TeX Xy-pic Require", ["Functional Programming library Ready", "TeX Jax Ready"]); // "HTML-CSS Xy-pic Config" depends on "TeX Xy-pic" and "HTML-CSS Jax". MathJax.Extension.xypic.signalHandler.chainSignal("HTML-CSS Xy-pic Config Require", ["TeX Xy-pic Ready", "HTML-CSS Jax Ready"]); // "SVG Xy-pic Config" depends on "TeX Xy-pic" and "SVG Jax". MathJax.Extension.xypic.signalHandler.chainSignal("SVG Xy-pic Config Require", ["TeX Xy-pic Ready", "SVG Jax Ready"]); // "Device-Independent Xy-pic" depends on "TeX Xy-pic" OR "SVG Jax". MathJax.Extension.xypic.signalHandler.chainSignal("Device-Independent Xy-pic Require", ["HTML-CSS Xy-pic Config Ready"]); MathJax.Extension.xypic.signalHandler.chainSignal("Device-Independent Xy-pic Require", ["SVG Xy-pic Config Ready"]); // "HTML-CSS Xy-pic" depends on "HTML-CSS Xy-pic Config" and "Device-Independent Xy-pic". MathJax.Extension.xypic.signalHandler.chainSignal("HTML-CSS Xy-pic Require", ["HTML-CSS Xy-pic Config Ready", "Device-Independent Xy-pic Ready"]); // "SVG Xy-pic" depends on "SVG Xy-pic Config" and "Device-Independent Xy-pic". MathJax.Extension.xypic.signalHandler.chainSignal("SVG Xy-pic Require", ["SVG Xy-pic Config Ready", "Device-Independent Xy-pic Ready"]); MathJax.Hub.Register.StartupHook("TeX Xy-pic Require",function () { var FP = MathJax.Extension.fp; var MML = MathJax.ElementJax.mml; var TEX = MathJax.InputJax.TeX; var TEXDEF = TEX.Definitions; var xypic = MathJax.Extension.xypic; var AST = xypic.AST = MathJax.Object.Subclass({}); MathJax.Hub.Insert(TEXDEF, { macros: { //hole: ['Macro', '{\\bbox[3pt]{}}'] hole: ['Macro', '{\\style{visibility:hidden}{x}}'], objectstyle: ['Macro', '\\textstyle'], labelstyle: ['Macro', '\\scriptstyle'], twocellstyle: ['Macro', '\\scriptstyle'], xybox: 'Xybox', xymatrix: 'Xymatrix', newdir: 'XypicNewdir', includegraphics: 'Xyincludegraphics' }, environment: { xy: ['ExtensionEnv', null, 'XYpic'] } }); // override MathJax.InputJax.TeX.formatError function to display parse error. var tex_formatError = TEX.formatError; TEX.formatError = function (err, math, displaystyle, script) { if (err.xyjaxError !== undefined) { return err.toMML(); } else { return tex_formatError(err, math, displaystyle, script); } } xypic.memoize = function (object, funcName) { var func = object[funcName]; var memo = function () { var value = func.call(this); var constFunc = function () { return value; } constFunc.reset = reset; object[funcName] = constFunc; return value; } var reset = function () { object[funcName] = memo; } memo.reset = reset; reset(); }; AST.xypic = MML.mbase.Subclass({ Init: function (cmd) { this.data = []; this.cmd = cmd; }, type: "xypic", inferRow: false, defaults: { mathbackground: MML.INHERIT, mathcolor: MML.INHERIT, notation: MML.NOTATION.LONGDIV, texClass: MML.TEXCLASS.ORD }, setTeXclass: MML.mbase.setSeparateTeXclasses, toString: function () { return this.type + "(" + this.cmd + ")"; } }); AST.xypic.newdir = MML.mbase.Subclass({ Init: function (cmd) { this.data = []; this.cmd = cmd; }, type: "newdir", inferRow: false, defaults: { mathbackground: MML.INHERIT, mathcolor: MML.INHERIT, notation: MML.NOTATION.LONGDIV, texClass: MML.TEXCLASS.ORD }, setTeXclass: MML.mbase.setSeparateTeXclasses, toString: function () { return this.type + "(" + this.cmd + ")"; } }); AST.xypic.includegraphics = MML.mbase.Subclass({ Init: function (cmd) { this.data = []; this.cmd = cmd; }, type: "includegraphics", inferRow: false, defaults: { mathbackground: MML.INHERIT, mathcolor: MML.INHERIT, notation: MML.NOTATION.LONGDIV, texClass: MML.TEXCLASS.ORD }, setTeXclass: MML.mbase.setSeparateTeXclasses, toString: function () { return this.type + "(" + this.cmd + ")"; } }); // <pos-decor> ::= <pos> <decor> AST.PosDecor = MathJax.Object.Subclass({ Init: function (pos, decor) { this.pos = pos; this.decor = decor; }, toString: function () { return this.pos.toString() + " " + this.decor; } }); // <pos> AST.Pos = MathJax.Object.Subclass({}); // <pos> ::= <coord> <pos2>* AST.Pos.Coord = MathJax.Object.Subclass({ Init: function (coord, pos2s) { this.coord = coord; this.pos2s = pos2s; }, toString: function () { return this.coord.toString() + " " + this.pos2s.mkString(" "); } }); // <pos2> ::= '+' <coord> AST.Pos.Plus = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return "+(" + this.coord + ")"; } }); // <pos2> ::= '-' <coord> AST.Pos.Minus = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return "-(" + this.coord + ")"; } }); // <pos2> ::= '!' <coord> AST.Pos.Skew = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return "!(" + this.coord + ")"; } }); // <pos2> ::= '.' <coord> AST.Pos.Cover = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return ".(" + this.coord + ")"; } }); // <pos2> ::= ',' <coord> AST.Pos.Then = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return ",(" + this.coord + ")"; } }); // <pos2> ::= ';' <coord> AST.Pos.SwapPAndC = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return ";(" + this.coord + ")"; } }); // <pos2> ::= ':' <coord> AST.Pos.SetBase = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return ":(" + this.coord + ")"; } }); // <pos2> ::= '::' <coord> AST.Pos.SetYBase = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return "::(" + this.coord + ")"; } }); // <pos2> ::= '**' <object> AST.Pos.ConnectObject = MathJax.Object.Subclass({ Init: function (object) { this.object = object; }, toString: function () { return "**(" + this.object + ")"; } }); // <pos2> ::= '*' <object> AST.Pos.DropObject = MathJax.Object.Subclass({ Init: function (object) { this.object = object; }, toString: function () { return "*(" + this.object + ")"; } }); // <pos2> ::= '?' <place> AST.Pos.Place = MathJax.Object.Subclass({ Init: function (place) { this.place = place; }, toString: function () { return "?(" + this.place + ")"; } }); // <pos2> ::= '@+' <coord> AST.Pos.PushCoord = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return "@+(" + this.coord + ")"; } }); // <pos2> ::= '@-' <coord> AST.Pos.EvalCoordThenPop = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return "@-(" + this.coord + ")"; } }); // <pos2> ::= '@=' <coord> AST.Pos.LoadStack = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return "@=(" + this.coord + ")"; } }); // <pos2> ::= '@@' <coord> AST.Pos.DoCoord = MathJax.Object.Subclass({ Init: function (coord) { this.coord = coord; }, toString: function () { return "@@(" + this.coord + ")"; } }); // <pos2> ::= '@i' AST.Pos.InitStack = MathJax.Object.Subclass({ Init: function () { }, toString: function () { return "@i"; } }); // <pos2> ::= '@(' AST.Pos.EnterFrame = MathJax.Object.Subclass({ Init: function () { }, toString: function () { return "@("; } }); // <pos2> ::= '@)' AST.Pos.LeaveFrame = MathJax.Object.Subclass({ Init: function () { }, toString: function () { return "@)"; } }); // <pos2> ::= '=' '"' <id> '"' AST.Pos.SavePos = MathJax.Object.Subclass({ Init: function (id) { this.id = id; }, toString: function () { return '="' + this.id + '"'; } }); // <pos2> ::= '=' <coord> '"' <id> '"' AST.Pos.SaveMacro = MathJax.Object.Subclass({ Init: function (macro, id) { this.macro = macro; this.id = id; }, toString: function () { return "=(" + this.macro + ' "' + this.id + '")'; } }); // <pos2> ::= '=:' '"' <id> '"' AST.Pos.SaveBase = MathJax.Object.Subclass({ Init: function (id) { this.id = id; }, toString: function () { return '=:"' + this.id + '"'; } }); // <pos2> ::= '=@' '"' <id> '"' AST.Pos.SaveStack = MathJax.Object.Subclass({ Init: function (id) { this.id = id; }, toString: function () { return '=@"' + this.id + '"'; } }); // <coord> AST.Coord = MathJax.Object.Subclass({}); // <coord> ::= <vector> AST.Coord.Vector = MathJax.Object.Subclass({ Init: function (vector) { this.vector = vector; }, toString: function () { return this.vector.toString(); } }); // <coord> ::= <empty> | 'c' AST.Coord.C = MathJax.Object.Subclass({ toString: function () { return "c"; } }); // <coord> ::= 'p' AST.Coord.P = MathJax.Object.Subclass({ toString: function () { return "p"; } }); // <coord> ::= 'x' AST.Coord.X = MathJax.Object.Subclass({ toString: function () { return "x"; } }); // <coord> ::= 'y' AST.Coord.Y = MathJax.Object.Subclass({ toString: function () { return "y"; } }); // <coord> ::= '"' <id> '"' AST.Coord.Id = MathJax.Object.Subclass({ Init: function (id) { this.id = id; }, toString: function () { return '"' + this.id + '"'; } }); // <coord> ::= '{' <pos> <decor> '}' AST.Coord.Group = MathJax.Object.Subclass({ Init: function (posDecor) { this.posDecor = posDecor; }, toString: function () { return '{' + this.posDecor + '}'; } }); // <coord> ::= 's' <digit> // <coord> ::= 's' '{' <nonnegative-number> '}' AST.Coord.StackPosition = MathJax.Object.Subclass({ Init: function (number) { this.number = number; }, toString: function () { return 's{' + this.number + '}'; } }); // coordinate for xymatrix // <coord> ::= '[' ('"'<prefix>'"')? <number> ',' <number> ']' AST.Coord.DeltaRowColumn = MathJax.Object.Subclass({ /** * @param {String} prefix name of the xymatrix * @param {Number} dr rows below * @param {Number} dc columns right */ Init: function (prefix, dr, dc) { this.prefix = prefix; this.dr = dr; this.dc = dc; }, toString: function () { return '[' + (this.prefix === ''? '' : '"' + this.prefix + '"') + this.dr + "," + this.dc + "]"; } }); // coordinate for xymatrix // <coord> ::= '[' ('"'<prefix>'"')? ( 'l' | 'r' | 'u' | 'd' )* ']' AST.Coord.Hops = MathJax.Object.Subclass({ /** * @param {String} prefix name of the xymatrix * @param {List[String]} hops hops */ Init: function (prefix, hops) { this.prefix = prefix; this.hops = hops; }, toString: function () { return '[' + (this.prefix === ''? '' : '"' + this.prefix + '"') + this.hops.mkString("") + "]"; } }); // coordinate for xymatrix // <coord> ::= '[' ('"'<prefix>'"')? ( 'l' | 'r' | 'u' | 'd' )+ <place> ']' AST.Coord.HopsWithPlace = MathJax.Object.Subclass({ /** * @param {String} prefix name of the xymatrix * @param {List[String]} hops hops * @param {AST.Pos.Place} place place */ Init: function (prefix, hops, place) { this.prefix = prefix; this.hops = hops; this.place = place; }, toString: function () { return '[' + (this.prefix === ''? '' : '"' + this.prefix + '"') + this.hops.mkString("") + this.place + "]"; } }); // <vector> AST.Vector = MathJax.Object.Subclass({}); // <vector> ::= '(' <factor> ',' <factor> ')' AST.Vector.InCurBase = MathJax.Object.Subclass({ Init: function (x, y) { this.x = x; this.y = y; }, toString: function () { return "(" + this.x + ", " + this.y + ")"; } }); // <vector> ::= '<' <dimen> ',' <dimen> '>' // <vector> ::= '<' <dimen> '>' AST.Vector.Abs = MathJax.Object.Subclass({ Init: function (x, y) { this.x = x; this.y = y; }, toString: function () { return "<" + this.x + ", " + this.y + ">"; } }); // <vector> ::= 'a' '(' <number> ')' AST.Vector.Angle = MathJax.Object.Subclass({ Init: function (degree) { this.degree = degree; }, toString: function () { return "a(" + this.degree + ")"; } }); // <vector> ::= '/' <direction> <dimen> '/' AST.Vector.Dir = MathJax.Object.Subclass({ Init: function (dir, dimen) { this.dir = dir; this.dimen = dimen; }, toString: function () { return "/" + this.dir + " " + this.dimen + "/"; } }); // <vector> ::= <corner> // | <corner> '(' <factor> ')' AST.Vector.Corner = MathJax.Object.Subclass({ Init: function (corner, factor) { this.corner = corner; this.factor = factor; }, toString: function () { return this.corner.toString() + "(" + this.factor + ")"; } }); // <corner> ::= 'L' | 'R' | 'D' | 'U' // | 'CL' | 'CR' | 'CD' | 'CU' // | 'LD' | 'RD' | 'LU' | 'RU' // | 'E' | 'P' // | 'A' AST.Corner = MathJax.Object.Subclass({}); AST.Corner.L = MathJax.Object.Subclass({ toString: function () { return "L"; } }); AST.Corner.R = MathJax.Object.Subclass({ toString: function () { return "R"; } }); AST.Corner.D = MathJax.Object.Subclass({ toString: function () { return "D"; } }); AST.Corner.U = MathJax.Object.Subclass({ toString: function () { return "U"; } }); AST.Corner.CL = MathJax.Object.Subclass({ toString: function () { return "CL"; } }); AST.Corner.CR = MathJax.Object.Subclass({ toString: function () { return "CR"; } }); AST.Corner.CD = MathJax.Object.Subclass({ toString: function () { return "CD"; } }); AST.Corner.CU = MathJax.Object.Subclass({ toString: function () { return "CU"; } }); AST.Corner.LD = MathJax.Object.Subclass({ toString: function () { return "LD"; } }); AST.Corner.RD = MathJax.Object.Subclass({ toString: function () { return "RD"; } }); AST.Corner.LU = MathJax.Object.Subclass({ toString: function () { return "LU"; } }); AST.Corner.RU = MathJax.Object.Subclass({ toString: function () { return "RU"; } }); AST.Corner.NearestEdgePoint = MathJax.Object.Subclass({ toString: function () { return "E"; } }); AST.Corner.PropEdgePoint = MathJax.Object.Subclass({ toString: function () { return "P"; } }); AST.Corner.Axis = MathJax.Object.Subclass({ toString: function () { return "A"; } }); // <place> ::= '<' <place> // <place> ::= '>' <place> // <place> ::= '(' <factor> ')' <place> // <place> ::= '!' '{' <pos> '}' <slide> // <place> ::= <slide> AST.Place = MathJax.Object.Subclass({ Init: function (shaveP, shaveC, factor, slide) { this.shaveP = shaveP; this.shaveC = shaveC; this.factor = factor; this.slide = slide; }, compound: function (that) { return AST.Place( this.shaveP + that.shaveP, this.shaveC + that.shaveC, that.factor === undefined? this.factor : that.factor, that.slide); }, toString: function () { var desc = ""; for (var l = 0; l < this.shaveP; l++) { desc += "<"; } for (var r = 0; r < this.shaveC; r++) { desc += ">"; } if (this.factor !== undefined) { desc += "(" + this.factor + ")"; } this.slide.dimen.foreach(function (d) { desc += "/" + d + "/"; }); return desc; } }); AST.Place.Factor = MathJax.Object.Subclass({ Init: function (factor) { this.factor = factor; }, isIntercept: false, toString: function () { return this.factor.toString(); } }); AST.Place.Intercept = MathJax.Object.Subclass({ Init: function (pos) { this.pos = pos; }, isIntercept: true, toString: function () { return "!{" + this.pos + "}"; } }); // <slide> ::= <empty> // <slide> ::= '/' <dimen> '/' AST.Slide = MathJax.Object.Subclass({ Init: function (dimen) { this.dimen = dimen; }, toString: function () { return this.dimen.getOrElse(""); } }); // <object> ::= <modifier>* <objectbox> AST.Object = MathJax.Object.Subclass({ Init: function (modifiers, object) { this.modifiers = modifiers; this.object = object; }, dirVariant: function () { return this.object.dirVariant(); }, dirMain: function () { return this.object.dirMain(); }, isDir: function () { return this.object.isDir(); }, toString: function () { return this.modifiers.mkString() + this.object.toString(); } }); // <objectbox> AST.ObjectBox = MathJax.Object.Subclass({ dirVariant: function () { return undefined; }, dirMain: function () { return undefined; }, isDir: function () { return false; }, isEmpty: false }); // <objectbox> ::= '{' <text> '}' // <objectbox> ::= <TeX box> '{' <text> '}' AST.ObjectBox.Text = AST.ObjectBox.Subclass({ Init: function (math) { this.math = math; }, toString: function () { return "{" + this.math.toString() + "}"; } }); AST.ObjectBox.Empty = AST.ObjectBox.Subclass({ isEmpty: true, toString: function () { return "{}"; } }); // <objectbox> ::= 'xymatrix' <xymatrix> AST.ObjectBox.Xymatrix = AST.ObjectBox.Subclass({ /** * @param {AST.Command.Xymatrix} xymatrix xymatrix */ Init: function (xymatrix) { this.xymatrix = xymatrix; }, toString: function () { return this.xymatrix.toString(); } }); // <objectbox> ::= '\txt' <width> <styl