Refactor code that builds outerHTML string by hand, since it needs to be used by Opera as well in order to fix unquoted special characters in attributes. This also fixes the self-closing tag problems for IE and Opera. (Resolves issue #106 and issue #99)

This commit is contained in:
Davide P. Cervone 2011-04-21 20:54:12 -04:00
parent bb09608b23
commit 3732851167
8 changed files with 49 additions and 47 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,5 +12,5 @@
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
*/ */
MathJax.Extension.mml2jax={version:"1.1.1",config:{preview:"alttext"},MMLnamespace:"http://www.w3.org/1998/Math/MathML",PreProcess:function(e){if(!this.configured){this.config=MathJax.Hub.CombineConfig("mml2jax",this.config);if(this.config.Augment){MathJax.Hub.Insert(this,this.config.Augment)}this.InitBrowser();this.configured=true}if(typeof(e)==="string"){e=document.getElementById(e)}if(!e){e=document.body}this.ProcessMathArray(e.getElementsByTagName("math"));if(e.getElementsByTagNameNS){this.ProcessMathArray(e.getElementsByTagNameNS(this.MMLnamespace,"math"))}var d=document.getElementsByTagName("html")[0];if(d){for(var c=0,b=d.attributes.length;c<b;c++){var a=d.attributes[c];if(a.nodeName.substr(0,6)==="xmlns:"&&a.nodeValue===this.MMLnamespace){this.ProcessMathArray(e.getElementsByTagName(a.nodeName.substr(6)+":math"))}}}},ProcessMathArray:function(b){var a;if(b.length){if(this.msieMathTagBug){for(a=b.length-1;a>=0;a--){if(b[a].nodeName==="MATH"){this.msieProcessMath(b[a])}else{this.ProcessMath(b[a])}}}else{for(a=b.length-1;a>=0;a--){this.ProcessMath(b[a])}}}},ProcessMath:function(e){var d=e.parentNode;var a=document.createElement("script");a.type="math/mml";d.insertBefore(a,e);if(this.msieScriptBug){var b=this.msieOuterHTML(e);b=b.replace(/<\?import .*?>/i,"").replace(/<\?xml:namespace .*?\/>/i,"");MathJax.HTML.setScript(a,b.replace(/&nbsp;/g,"&#xA0;"));d.removeChild(e)}else{var c=MathJax.HTML.Element("span");c.appendChild(e);MathJax.HTML.setScript(a,c.innerHTML)}if(this.config.preview!=="none"){this.createPreview(e,a)}},msieProcessMath:function(e){var c=e.parentNode;var a=document.createElement("script");a.type="math/mml";c.insertBefore(a,e);var b="",d;while(e&&e.nodeName!=="/MATH"){d=e;e=e.nextSibling;b+=this.msieNodeHTML(d);d.parentNode.removeChild(d)}if(e&&e.nodeName==="/MATH"){e.parentNode.removeChild(e)}a.text=b+"</math>";if(this.config.preview!=="none"){this.createPreview(e,a)}},msieNodeHTML:function(d){var c,b,a;if(d.nodeName==="#text"){c=d.nodeValue.replace(/&/g,"&#x26;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}else{if(d.nodeName==="#comment"){c="<!--"+d.nodeValue+"-->"}else{if(this.msieAttributeBug){c="<"+d.nodeName.toLowerCase();for(b=0,a=d.attributes.length;b<a;b++){if(d.attributes[b].specified){c+=" "+d.attributes[b].nodeName.toLowerCase()+"=";c+='"'+d.attributes[b].nodeValue.replace(/\"/g,'\\"')+'"'}}c+=">"}else{c=this.toLowerCase(d.outerHTML);var e=c.split(/\"/);for(b=0,a=e.length;b<a;b+=2){e[b]=e[b].toLowerCase()}c=e.join('"')}}}return c},msieOuterHTML:function(d){if(d.nodeName.charAt(0)==="#"){return this.msieNodeHTML(d)}if(!this.msieAttributeBug){return d.outerHTML}var c=this.msieNodeHTML(d);for(var b=0,a=d.childNodes.length;b<a;b++){c+=this.msieOuterHTML(d.childNodes[b])}c+="</"+d.nodeName.toLowerCase()+">";return c},createPreview:function(b,a){var c;if(this.config.preview==="alttext"){var d=b.getAttribute("alttext");if(d!=null){c=[this.filterText(d)]}}else{if(this.config.preview instanceof Array){c=this.config.preview}}if(c){c=MathJax.HTML.Element("span",{className:MathJax.Hub.config.preRemoveClass},c);a.parentNode.insertBefore(c,a)}},filterText:function(a){return a},InitBrowser:function(){MathJax.Hub.Browser.Select({MSIE:function(a){var b=MathJax.HTML.Element("span",{className:"mathjax"});MathJax.Hub.Insert(MathJax.Extension.mml2jax,{msieScriptBug:true,msieMathTagBug:(MathJax.HTML.Element("span",{innerHTML:"<math><mi>x</mi></math>"}).childNodes.length!==1),msieAttributeBug:(b.outerHTML.substr(12)!=='"')})}})}};MathJax.Hub.Register.PreProcessor(["PreProcess",MathJax.Extension.mml2jax]);MathJax.Ajax.loadComplete("[MathJax]/extensions/mml2jax.js"); MathJax.Extension.mml2jax={version:"1.1.2",config:{preview:"alttext"},MMLnamespace:"http://www.w3.org/1998/Math/MathML",PreProcess:function(e){if(!this.configured){this.config=MathJax.Hub.CombineConfig("mml2jax",this.config);if(this.config.Augment){MathJax.Hub.Insert(this,this.config.Augment)}this.InitBrowser();this.configured=true}if(typeof(e)==="string"){e=document.getElementById(e)}if(!e){e=document.body}this.ProcessMathArray(e.getElementsByTagName("math"));if(e.getElementsByTagNameNS){this.ProcessMathArray(e.getElementsByTagNameNS(this.MMLnamespace,"math"))}var d=document.getElementsByTagName("html")[0];if(d){for(var c=0,b=d.attributes.length;c<b;c++){var a=d.attributes[c];if(a.nodeName.substr(0,6)==="xmlns:"&&a.nodeValue===this.MMLnamespace){this.ProcessMathArray(e.getElementsByTagName(a.nodeName.substr(6)+":math"))}}}},ProcessMathArray:function(b){var a;if(b.length){if(this.MathTagBug){for(a=b.length-1;a>=0;a--){if(b[a].nodeName==="MATH"){this.ProcessMathFlattened(b[a])}else{this.ProcessMath(b[a])}}}else{for(a=b.length-1;a>=0;a--){this.ProcessMath(b[a])}}}},ProcessMath:function(e){var d=e.parentNode;var a=document.createElement("script");a.type="math/mml";d.insertBefore(a,e);if(this.AttributeBug){var b=this.OuterHTML(e);if(this.CleanupHTML){b=b.replace(/<\?import .*?>/i,"").replace(/<\?xml:namespace .*?\/>/i,"");b=b.replace(/&nbsp;/g,"&#xA0;")}MathJax.HTML.setScript(a,b);d.removeChild(e)}else{var c=MathJax.HTML.Element("span");c.appendChild(e);MathJax.HTML.setScript(a,c.innerHTML)}if(this.config.preview!=="none"){this.createPreview(e,a)}},ProcessMathFlattened:function(e){var c=e.parentNode;var a=document.createElement("script");a.type="math/mml";c.insertBefore(a,e);var b="",d;while(e&&e.nodeName!=="/MATH"){d=e;e=e.nextSibling;b+=this.NodeHTML(d);d.parentNode.removeChild(d)}if(e&&e.nodeName==="/MATH"){e.parentNode.removeChild(e)}a.text=b+"</math>";if(this.config.preview!=="none"){this.createPreview(e,a)}},NodeHTML:function(e){var d,c,a;if(e.nodeName==="#text"){d=this.quoteHTML(e.nodeValue)}else{if(e.nodeName==="#comment"){d="<!--"+e.nodeValue+"-->"}else{d="<"+e.nodeName.toLowerCase();var b=e.attributes;for(c=0,a=b.length;c<a;c++){if(b[c].specified){d+=" "+b[c].nodeName.toLowerCase().replace(/xmlns:xmlns/,"xmlns")+"=";d+='"'+this.quoteHTML(b[c].nodeValue)+'"'}}d+=">"}}return d},OuterHTML:function(d){if(d.nodeName.charAt(0)==="#"){return this.NodeHTML(d)}if(!this.AttributeBug){return d.outerHTML}var c=this.NodeHTML(d);for(var b=0,a=d.childNodes.length;b<a;b++){c+=this.OuterHTML(d.childNodes[b])}c+="</"+d.nodeName.toLowerCase()+">";return c},quoteHTML:function(a){return a.replace(/&/g,"&#x26;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},createPreview:function(b,a){var c;if(this.config.preview==="alttext"){var d=b.getAttribute("alttext");if(d!=null){c=[this.filterText(d)]}}else{if(this.config.preview instanceof Array){c=this.config.preview}}if(c){c=MathJax.HTML.Element("span",{className:MathJax.Hub.config.preRemoveClass},c);a.parentNode.insertBefore(c,a)}},filterText:function(a){return a},InitBrowser:function(){var b=MathJax.HTML.Element("span",{id:"<",className:"mathjax",innerHTML:"<math><mi>x</mi><mspace /></math>"});var a=b.outerHTML||"";this.AttributeBug=a!==""&&!(a.match(/id="&lt;"/)&&a.match(/class="mathjax"/)&&a.match(/<\/math>/));this.MathTagBug=b.childNodes.length>1;this.CleanupHTML=MathJax.Hub.Browser.isMSIE}};MathJax.Hub.Register.PreProcessor(["PreProcess",MathJax.Extension.mml2jax]);MathJax.Ajax.loadComplete("[MathJax]/extensions/mml2jax.js");

View File

@ -24,7 +24,7 @@
*/ */
MathJax.Extension.mml2jax = { MathJax.Extension.mml2jax = {
version: "1.1.1", version: "1.1.2",
config: { config: {
preview: "alttext" // Use the <math> element's alttext as the preview: "alttext" // Use the <math> element's alttext as the
// preview. Set to "none" for no preview, // preview. Set to "none" for no preview,
@ -68,9 +68,9 @@ MathJax.Extension.mml2jax = {
ProcessMathArray: function (math) { ProcessMathArray: function (math) {
var i; var i;
if (math.length) { if (math.length) {
if (this.msieMathTagBug) { if (this.MathTagBug) {
for (i = math.length-1; i >= 0; i--) { for (i = math.length-1; i >= 0; i--) {
if (math[i].nodeName === "MATH") {this.msieProcessMath(math[i])} if (math[i].nodeName === "MATH") {this.ProcessMathFlattened(math[i])}
else {this.ProcessMath(math[i])} else {this.ProcessMath(math[i])}
} }
} else { } else {
@ -84,11 +84,13 @@ MathJax.Extension.mml2jax = {
var script = document.createElement("script"); var script = document.createElement("script");
script.type = "math/mml"; script.type = "math/mml";
parent.insertBefore(script,math); parent.insertBefore(script,math);
if (this.msieScriptBug) { if (this.AttributeBug) {
var html = this.msieOuterHTML(math); var html = this.OuterHTML(math);
html = html.replace(/<\?import .*?>/i,"").replace(/<\?xml:namespace .*?\/>/i,""); if (this.CleanupHTML) {
MathJax.HTML.setScript(script,html.replace(/&nbsp;/g,"&#xA0;")); html = html.replace(/<\?import .*?>/i,"").replace(/<\?xml:namespace .*?\/>/i,"");
parent.removeChild(math); html = html.replace(/&nbsp;/g,"&#xA0;");
}
MathJax.HTML.setScript(script,html); parent.removeChild(math);
} else { } else {
var span = MathJax.HTML.Element("span"); span.appendChild(math); var span = MathJax.HTML.Element("span"); span.appendChild(math);
MathJax.HTML.setScript(script,span.innerHTML); MathJax.HTML.setScript(script,span.innerHTML);
@ -96,7 +98,7 @@ MathJax.Extension.mml2jax = {
if (this.config.preview !== "none") {this.createPreview(math,script)} if (this.config.preview !== "none") {this.createPreview(math,script)}
}, },
msieProcessMath: function (math) { ProcessMathFlattened: function (math) {
var parent = math.parentNode; var parent = math.parentNode;
var script = document.createElement("script"); var script = document.createElement("script");
script.type = "math/mml"; script.type = "math/mml";
@ -104,48 +106,49 @@ MathJax.Extension.mml2jax = {
var mml = "", node; var mml = "", node;
while (math && math.nodeName !== "/MATH") { while (math && math.nodeName !== "/MATH") {
node = math; math = math.nextSibling; node = math; math = math.nextSibling;
mml += this.msieNodeHTML(node); mml += this.NodeHTML(node);
node.parentNode.removeChild(node); node.parentNode.removeChild(node);
} }
if (math && math.nodeName === "/MATH") {math.parentNode.removeChild(math)} if (math && math.nodeName === "/MATH") {math.parentNode.removeChild(math)}
script.text = mml + "</math>"; script.text = mml + "</math>";
if (this.config.preview !== "none") {this.createPreview(math,script)} if (this.config.preview !== "none") {this.createPreview(math,script)}
}, },
msieNodeHTML: function (node) {
NodeHTML: function (node) {
var html, i, m; var html, i, m;
if (node.nodeName === "#text") { if (node.nodeName === "#text") {
html = node.nodeValue.replace(/&/g,"&#x26;").replace(/</g,"&lt;").replace(/>/g,"&gt;"); html = this.quoteHTML(node.nodeValue);
} else if (node.nodeName === "#comment") { } else if (node.nodeName === "#comment") {
html = "<!--" + node.nodeValue + "-->" html = "<!--" + node.nodeValue + "-->"
} } else {
else if (this.msieAttributeBug) {
// In IE, outerHTML doesn't properly quote attributes, so quote them by hand // In IE, outerHTML doesn't properly quote attributes, so quote them by hand
// In Opera, HTML special characters aren't quoted in attributes, so quote them
html = "<"+node.nodeName.toLowerCase(); html = "<"+node.nodeName.toLowerCase();
for (i = 0, m = node.attributes.length; i < m; i++) { var attributes = node.attributes;
if (node.attributes[i].specified) { for (i = 0, m = attributes.length; i < m; i++) {
html += " "+node.attributes[i].nodeName.toLowerCase()+"="; if (attributes[i].specified) {
html += '"'+node.attributes[i].nodeValue.replace(/\"/g,'\\"')+'"'; // Opera 11.5 beta turns xmlns into xmlns:xmlns, so put it back
// *** FIXME: Similar problems may occur for other attributes?
html += " "+attributes[i].nodeName.toLowerCase().replace(/xmlns:xmlns/,"xmlns")+"=";
html += '"'+this.quoteHTML(attributes[i].nodeValue)+'"';
} }
} }
html += ">"; html += ">";
} else {
html = this.toLowerCase(node.outerHTML)
var parts = html.split(/\"/);
for (i = 0, m = parts.length; i < m; i += 2) {parts[i] = parts[i].toLowerCase()}
html = parts.join('"');
} }
return html; return html;
}, },
msieOuterHTML: function (node) { OuterHTML: function (node) {
// IE's outerHTML doesn't properly quote if (node.nodeName.charAt(0) === "#") {return this.NodeHTML(node)}
if (node.nodeName.charAt(0) === "#") {return this.msieNodeHTML(node)} if (!this.AttributeBug) {return node.outerHTML}
if (!this.msieAttributeBug) {return node.outerHTML} var html = this.NodeHTML(node);
var html = this.msieNodeHTML(node);
for (var i = 0, m = node.childNodes.length; i < m; i++) for (var i = 0, m = node.childNodes.length; i < m; i++)
{html += this.msieOuterHTML(node.childNodes[i])} {html += this.OuterHTML(node.childNodes[i]);}
html += "</"+node.nodeName.toLowerCase()+">" html += "</"+node.nodeName.toLowerCase()+">";
return html; return html;
}, },
quoteHTML: function (string) {
return string.replace(/&/g,"&#x26;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");
},
createPreview: function (math,script) { createPreview: function (math,script) {
var preview; var preview;
@ -162,16 +165,15 @@ MathJax.Extension.mml2jax = {
filterText: function (text) {return text}, filterText: function (text) {return text},
InitBrowser: function () { InitBrowser: function () {
MathJax.Hub.Browser.Select({ var test = MathJax.HTML.Element("span",{id:"<", className: "mathjax", innerHTML: "<math><mi>x</mi><mspace /></math>"});
MSIE: function (browser) { var html = test.outerHTML || "";
var test = MathJax.HTML.Element("span",{className:"mathjax"}); this.AttributeBug = html !== "" && !(
MathJax.Hub.Insert(MathJax.Extension.mml2jax,{ html.match(/id="&lt;"/) && // "<" should convert to "&lt;"
msieScriptBug: true, html.match(/class="mathjax"/) && // IE leaves out quotes
msieMathTagBug: (MathJax.HTML.Element("span", {innerHTML:"<math><mi>x</mi></math>"}).childNodes.length !== 1), // IE < 9 corrupts MathML html.match(/<\/math>/) // Opera 9 drops tags after self-closing tags
msieAttributeBug: (test.outerHTML.substr(12) !== '"') // attributes aren't quoted? );
}) this.MathTagBug = test.childNodes.length > 1; // IE < 9 flattens unknown tags
} this.CleanupHTML = MathJax.Hub.Browser.isMSIE; // remove namespace and other added tags
});
} }
}; };