commit 64a9eb05060c746f53ed60227f620ef53c8d2a94
parent 5a5205e0131c56c46930d2cac44cb3da1f723042
Author: Frédéric Wang <fred.wang@free.fr>
Date: Mon, 4 Feb 2013 12:55:49 +0100
Workaround mfenced support for Opera too ; add open/close properties on the element jax generated by the TeX/MathML input jax ; generate mfenced element for <mrow> elements with open/close properties.
Diffstat:
4 files changed, 163 insertions(+), 10 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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 <mo> operators, so let's use an <mfenced> 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 <mrow>
+ 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 <mfenced> very well. The MathML spec
+ // suggests this equivalent construction instead, so let's use it:
+ // <mrow> open, child1, sep1, child2, ... sep(N-1), childN, close</mrow>
+ // Opera is a bit special: it does not support stretchy <mo>, does not
+ // parse mfenced@open/mfenced@close very well, does not support
+ // mfenced@separators and only displays the first child of the <mfenced>
+ // element... For this browser, we will use this construction:
+ // <mfenced open="open" close="close">
+ // <mrow>child1, sep1, child2, sep2, ..., sep(N-1), childN</mrow>
+ // </mfenced>
+ 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 <mrow> container and attach the attributes of the
+ // <mfenced> 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 <mfenced>
+ 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;
}
});