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.

This commit is contained in:
Frédéric Wang 2013-02-04 12:55:49 +01:00
parent 5a5205e013
commit 64a9eb0506
4 changed files with 163 additions and 10 deletions

View File

@ -256,9 +256,14 @@ MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
if (thick !== "") {frac.linethickness = thick} if (thick !== "") {frac.linethickness = thick}
if (left || right) { if (left || right) {
var mrow = MML.mrow(); 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); mrow.Append(frac);
if (right) {mrow.Append(MML.mo(right))} if (right) {
mrow.Append(MML.mo(right).With({fence: "true"}));
}
frac = mrow; frac = mrow;
} }
if (style !== "") { if (style !== "") {

View File

@ -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 * MathJax/jax/input/MathML/jax.js
@ -158,6 +160,14 @@
{mml.Append.apply(mml,cmml.data); cmml.data = []} {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];
}
}
}, },
// //

View File

@ -178,9 +178,14 @@
mml.texClass = MML.TEXCLASS.INNER; mml.texClass = MML.TEXCLASS.INNER;
mml.texWithDelims = true; mml.texWithDelims = true;
var mrow = MML.mrow(); 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); 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 = mrow;
} }
return [STACKITEM.mml(mml), item]; return [STACKITEM.mml(mml), item];
@ -196,9 +201,16 @@
checkItem: function (item) { checkItem: function (item) {
if (item.type === "right") { if (item.type === "right") {
var mml = MML.mrow(); var mml = MML.mrow();
if (this.delim) {mml.Append(MML.mo(this.delim))} mml.open = this.delim; mml.close = item.delim;
mml.Append(this.data.length === 1 ? this.data[0] : this.data); if (this.delim) {
if (item.delim) {mml.Append(MML.mo(item.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 STACKITEM.mml(mml);
} }
return this.SUPER(arguments).checkItem.call(this,item); return this.SUPER(arguments).checkItem.call(this,item);
@ -277,9 +289,14 @@
} }
if (this.open || this.close) { if (this.open || this.close) {
var mrow = MML.mrow(); 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); 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 = mrow;
} }
mml = STACKITEM.mml(mml); mml = STACKITEM.mml(mml);

View File

@ -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 * MathJax/jax/output/NativeMML/jax.js
@ -467,7 +469,28 @@
if (this.data[i]) {this.data[i].toNativeMML(parent)} if (this.data[i]) {this.data[i].toNativeMML(parent)}
else {parent.appendChild(this.NativeMMLelement("mrow"))} 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); 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({ MML.TeXAtom.Augment({
// //
// Convert TeXatom to an mrow // Convert TeXatom to an mrow
@ -689,10 +801,19 @@
}, },
Opera: function (browser) { Opera: function (browser) {
nMML.operaPositionBug = true; nMML.operaPositionBug = true;
nMML.stretchyMoBug = true;
nMML.mfencedBug = true;
}, },
Firefox: function (browser) { Firefox: function (browser) {
nMML.forceReflow = true; nMML.forceReflow = true;
nMML.widthBug = true; nMML.widthBug = true;
nMML.mfencedBug = true;
},
Safari: function (browser) {
nMML.mfencedBug = true;
},
Chrome: function (browser) {
nMML.mfencedBug = true;
} }
}); });