diff --git a/unpacked/extensions/TeX/AMSmath.js b/unpacked/extensions/TeX/AMSmath.js index d2a0a380d..4615be6de 100644 --- a/unpacked/extensions/TeX/AMSmath.js +++ b/unpacked/extensions/TeX/AMSmath.js @@ -256,9 +256,14 @@ MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { if (thick !== "") {frac.linethickness = thick} if (left || right) { var mrow = MML.mrow(); - if (left) {mrow.Append(MML.mo(left))} + mrow.open = left; mrow.close = right; + if (left) { + mrow.Append(MML.mo(left).With({fence: "true"})); + } mrow.Append(frac); - if (right) {mrow.Append(MML.mo(right))} + if (right) { + mrow.Append(MML.mo(right).With({fence: "true"})); + } frac = mrow; } if (style !== "") { diff --git a/unpacked/jax/input/MathML/jax.js b/unpacked/jax/input/MathML/jax.js index 1270eefb7..4fb758992 100644 --- a/unpacked/jax/input/MathML/jax.js +++ b/unpacked/jax/input/MathML/jax.js @@ -1,3 +1,5 @@ +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ /************************************************************* * * MathJax/jax/input/MathML/jax.js @@ -158,6 +160,14 @@ {mml.Append.apply(mml,cmml.data); cmml.data = []} } } + if (mml.type === "mrow" && mml.data.length >= 2) { + var first = mml.data[0], last = mml.data[mml.data.length-1]; + if (first.type === "mo" && first.fence && + last.type === "mo" && last.fence) { + mml.open = first.data[0].data[0]; + mml.close = last.data[0].data[0]; + } + } }, // diff --git a/unpacked/jax/input/TeX/jax.js b/unpacked/jax/input/TeX/jax.js index 5a6004435..b6cd72018 100644 --- a/unpacked/jax/input/TeX/jax.js +++ b/unpacked/jax/input/TeX/jax.js @@ -178,9 +178,14 @@ mml.texClass = MML.TEXCLASS.INNER; mml.texWithDelims = true; var mrow = MML.mrow(); - if (this.open) {mrow.Append(MML.mo(this.open))} + mrow.open = this.open; mrow.close = this.close; + if (this.open) { + mrow.Append(MML.mo(this.open).With({fence: "true"})); + } mrow.Append(mml); - if (this.close) {mrow.Append(MML.mo(this.close))} + if (this.close) { + mrow.Append(MML.mo(this.close).With({fence: "true"})); + } mml = mrow; } return [STACKITEM.mml(mml), item]; @@ -196,9 +201,16 @@ checkItem: function (item) { if (item.type === "right") { var mml = MML.mrow(); - if (this.delim) {mml.Append(MML.mo(this.delim))} - mml.Append(this.data.length === 1 ? this.data[0] : this.data); - if (item.delim) {mml.Append(MML.mo(item.delim))} + mml.open = this.delim; mml.close = item.delim; + if (this.delim) { + mml.Append(MML.mo(this.delim).With({fence: "true"})); + } + for (var i in this.data) { + mml.Append(this.data[i]); + } + if (item.delim) { + mml.Append(MML.mo(item.delim).With({fence: "true"})); + } return STACKITEM.mml(mml); } return this.SUPER(arguments).checkItem.call(this,item); @@ -277,9 +289,14 @@ } if (this.open || this.close) { var mrow = MML.mrow(); - if (this.open) {mrow.Append(MML.mo(this.open))} + mrow.open = this.open; mrow.close = this.close; + if (this.open) { + mrow.Append(MML.mo(this.open).With({fence: "true"})) + } mrow.Append(mml); - if (this.close) {mrow.Append(MML.mo(this.close))} + if (this.close) { + mrow.Append(MML.mo(this.close).With({fence: "true"})) + } mml = mrow; } mml = STACKITEM.mml(mml); diff --git a/unpacked/jax/output/NativeMML/jax.js b/unpacked/jax/output/NativeMML/jax.js index e47e45304..5ed69d2da 100644 --- a/unpacked/jax/output/NativeMML/jax.js +++ b/unpacked/jax/output/NativeMML/jax.js @@ -1,3 +1,5 @@ +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ /************************************************************* * * MathJax/jax/output/NativeMML/jax.js @@ -467,7 +469,28 @@ if (this.data[i]) {this.data[i].toNativeMML(parent)} else {parent.appendChild(this.NativeMMLelement("mrow"))} } - } else { + } else if (nMML.stretchyMoBug && (this.open || this.close)) { + // This element contains opening and/or closing fences. Opera is not + // able to stretch operators, so let's use an element + // instead. + var mfenced = this.NativeMMLelement("mfenced"); + this.NativeMMLattributes(mfenced); + var i = 0, m = this.data.length; + if (this.open) { mfenced.setAttribute("open", this.open); i++; } + if (this.close) { mfenced.setAttribute("close", this.close); m--; } + var tag = mfenced; + if (m - i + 1 > 1) { + // If there are several children, put them in an + tag = this.NativeMMLelement("mrow"); + parent.appendChild(mfenced); + parent = mfenced; + } + for (; i < m; i++) { + if (this.data[i]) {this.data[i].toNativeMML(tag)} + else {tag.appendChild(this.NativeMMLelement("mrow"))} + } + parent.appendChild(tag); + } else { this.SUPER(arguments).toNativeMML.call(this,parent); } } @@ -619,6 +642,95 @@ } }); + MML.mfenced.Augment({ + toNativeMML: function (parent) { + if (!nMML.mfencedBug) { + this.SUPER(arguments).toNativeMML.call(this,parent); + return; + } + + // Some browsers do not handle very well. The MathML spec + // suggests this equivalent construction instead, so let's use it: + // open, child1, sep1, child2, ... sep(N-1), childN, close + // Opera is a bit special: it does not support stretchy , does not + // parse mfenced@open/mfenced@close very well, does not support + // mfenced@separators and only displays the first child of the + // element... For this browser, we will use this construction: + // + // child1, sep1, child2, sep2, ..., sep(N-1), childN + // + var isOpera = HUB.Browser.isOpera; + + // parse the open, close and separators attributes. + var values = this.getValues("open","close","separators"); + values.open = values.open.trim(); + values.close = values.close.trim(); + values.separators = values.separators.replace(/\s+/g,"").split(""); + if (values.separators.length == 0) { + // No separators specified, do not use separators at all. + values.separators = null; + } else if (values.separators.length < this.data.length-1) { + // There are not enough separators, repeat the last one. + for (var s = values.separators[values.separators.length-1], + i = this.data.length-1-values.separators.length; i > 0; i--) { + values.separators.push(s) + } + } + + // create an container and attach the attributes of the + // element to it. Note: removeAttribute does not raise any + // exception when the attributes is absent. + var tag = this.NativeMMLelement(isOpera ? this.type : "mrow"); + this.NativeMMLattributes(tag); + tag.removeAttribute("separators"); + if (isOpera) { + tag.setAttribute("open", values.open); + tag.setAttribute("close", values.close); + if (this.data.length > 1) { + parent.appendChild(tag); + parent = tag; + tag = this.NativeMMLelement("mrow"); + } + } else { + tag.removeAttribute("open"); + tag.removeAttribute("close"); + } + + if (!isOpera) { + // append the opening fence + var operator = this.NativeMMLelement("mo"); + operator.setAttribute("fence", "true"); + operator.textContent = values.open; + tag.appendChild(operator); + } + + // append the content of the + for (var i = 0, m = this.data.length; i < m; i++) { + if (values.separators && i > 0) { + var operator = this.NativeMMLelement("mo"); + operator.setAttribute("separator", "true"); + operator.textContent = values.separators[i-1]; + tag.appendChild(operator); + } + if (this.data[i]) { + this.data[i].toNativeMML(tag); + } + else {tag.appendChild(this.NativeMMLelement("mrow"))} + } + + if (!isOpera) { + // append the closing fence + var operator = this.NativeMMLelement("mo"); + operator.setAttribute("fence", "true"); + operator.textContent = values.close; + tag.appendChild(operator); + } + + // finally, append the new element to the parent. + parent.appendChild(tag); + } + }); + MML.TeXAtom.Augment({ // // Convert TeXatom to an mrow @@ -689,10 +801,19 @@ }, Opera: function (browser) { nMML.operaPositionBug = true; + nMML.stretchyMoBug = true; + nMML.mfencedBug = true; }, Firefox: function (browser) { nMML.forceReflow = true; nMML.widthBug = true; + nMML.mfencedBug = true; + }, + Safari: function (browser) { + nMML.mfencedBug = true; + }, + Chrome: function (browser) { + nMML.mfencedBug = true; } });