main.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. var docFrame;
  2. var logtextbox;
  3. var destFile;
  4. var embedFonts = false;
  5. var finalMathJaxURL = null;
  6. function log(text)
  7. {
  8. logtextbox.setAttribute("value", logtextbox.getAttribute("value") + "\n" + text);
  9. }
  10. function init()
  11. {
  12. try {
  13. docFrame = document.getElementById("docFrame");
  14. logtextbox = document.getElementById("logtextbox");
  15. // parse command line arguments
  16. var cmdLine = window.arguments[0];
  17. cmdLine = cmdLine.QueryInterface(Components.interfaces.nsICommandLine);
  18. embedFonts = cmdLine.handleFlag("embed-fonts", false);
  19. finalMathJaxURL = cmdLine.handleFlagWithParam("final-mathjax-url", false);
  20. if (!embedFonts && !finalMathJaxURL) {
  21. alert("You must eiher specify --embed-fonts or --final-mathjax-url");
  22. window.close();
  23. return;
  24. }
  25. sourceFilePath = cmdLine.getArgument(0);
  26. destFilePath = cmdLine.getArgument(1);
  27. if ( !sourceFilePath || !destFilePath ) {
  28. alert("Not enough parameters, expecting two arguments:\nInput file, output file");
  29. window.close();
  30. return;
  31. }
  32. sourceFile = cmdLine.resolveFile(sourceFilePath);
  33. if (! (sourceFile.exists() && sourceFile.isFile()) ) {
  34. alert("Invalid source file path.");
  35. window.close();
  36. return;
  37. }
  38. sourceURI = cmdLine.resolveURI(sourceFilePath);
  39. // create a nsIFile object for the output file
  40. try{
  41. destFile = cmdLine.resolveURI(destFilePath).QueryInterface(Components.interfaces.nsIFileURL).file;
  42. }catch(e){
  43. alert("Invalid destination file.\n\nException:\n" + e);
  44. window.close();
  45. return;
  46. }
  47. // add iframeLoaded() as an onload event handler, then navigate to the source file
  48. docFrame.addEventListener("DOMContentLoaded", iframeLoaded, true);
  49. docFrame.setAttribute("src", sourceURI.spec);
  50. } catch (e) {
  51. alert("Error in init():\n\n" + e);
  52. window.close();
  53. return;
  54. }
  55. }
  56. function iframeLoaded()
  57. {
  58. /*
  59. // print every MathJax signal to the log
  60. docFrame.contentWindow.MathJax.Hub.Startup.signal.Interest(
  61. function (message) {log("Startup: "+message)}
  62. );
  63. docFrame.contentWindow.MathJax.Hub.signal.Interest(
  64. function (message) {log("Hub: "+message)}
  65. );
  66. */
  67. // tell MathJax to call serialize() when finished
  68. docFrame.contentWindow.MathJax.Hub.Register.StartupHook("End", function() {serialize();});
  69. }
  70. function fileURLtoDataURI(url)
  71. {
  72. var ios = Components.classes["@mozilla.org/network/io-service;1"]
  73. .getService(Components.interfaces.nsIIOService);
  74. var url_object = ios.newURI(url, "", null);
  75. var file = url_object.QueryInterface(Components.interfaces.nsIFileURL).file;
  76. var data = "";
  77. var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
  78. createInstance(Components.interfaces.nsIFileInputStream);
  79. fstream.init(file, -1, -1, false);
  80. var bstream = Components.classes["@mozilla.org/binaryinputstream;1"].
  81. createInstance(Components.interfaces.nsIBinaryInputStream);
  82. bstream.setInputStream(fstream);
  83. var bytes = bstream.readBytes(bstream.available());
  84. b64bytes = btoa(bytes);
  85. return "data:;base64," + b64bytes;
  86. }
  87. function serialize()
  88. {
  89. var MathJaxURL = docFrame.contentWindow.MathJax.Hub.config.root;
  90. var searchURIList = new Array();
  91. var replacementURIList = new Array();
  92. log("serialize: preprocessing");
  93. // remove the MathJax status message window
  94. msgdiv = docFrame.contentDocument.getElementById("MathJax_Message");
  95. msgdiv.parentNode.removeChild(msgdiv);
  96. /* Loop through all CSS rules to find all @font-face rules.
  97. At this point, they refer to local absolute paths using file:// URLs.
  98. Replace them either with appropriate URLs relative to finalMathJaxURL
  99. or with data URIs. */
  100. for (var i = 0; i<docFrame.contentDocument.styleSheets.length; i++) {
  101. var stylesheet = docFrame.contentDocument.styleSheets[i];
  102. for (var j=0; j< stylesheet.cssRules.length; j++) {
  103. var rule = stylesheet.cssRules[j];
  104. if (rule.cssText.match("font-face")) {
  105. url = rule.style.getPropertyValue("src");
  106. url = url.match(/url\(\"(.+)\"\)/)[1];
  107. // Since the properties seem read-only here, we populate
  108. // searchURIList and replacementURIList to do text substitution
  109. // after serialization
  110. searchURIList.push(url);
  111. if (embedFonts) {
  112. replacementURIList.push(fileURLtoDataURI(url));
  113. } else {
  114. replacementURIList.push(url.replace(MathJaxURL, finalMathJaxURL));
  115. }
  116. }
  117. }
  118. }
  119. // find and remove the MathJax <script> tag
  120. try{
  121. var scriptTags = docFrame.contentDocument.getElementsByTagName("script");
  122. for (var i=0; i<scriptTags.length; i++) {
  123. if (scriptTags[i].getAttribute("src") && scriptTags[i].getAttribute("src").match(/MathJax.js/i))
  124. scriptTags[i].parentNode.removeChild(scriptTags[i]);
  125. }
  126. }catch(e){alert(e);}
  127. log("serialize: serializing");
  128. var serializer = new XMLSerializer();
  129. var xhtml = serializer.serializeToString(docFrame.contentDocument);
  130. log("serialize: postprocessing");
  131. // make the MathJax URL relative again
  132. // xhtml = xhtml.replace(findMathJaxURL, "MathJax");
  133. try{
  134. r1 = RegExp("&lt;!--/\\*--&gt;&lt;!\\[CDATA\\[/\\*&gt;&lt;!--\\*/", "g");
  135. xhtml = xhtml.replace(r1, "");
  136. r2 = RegExp("/\\*\\]\\]&gt;\\*/--&gt;", "g");
  137. xhtml = xhtml.replace(r2, "");
  138. r3 = RegExp("/\\*\\]\\]&gt;\\*///--&gt;", "g");
  139. xhtml = xhtml.replace(r3, "");
  140. }catch(e){alert(e);}
  141. for (var i=0; i<searchURIList.length; i++)
  142. xhtml = xhtml.replace(searchURIList[i], replacementURIList[i]);
  143. save(xhtml);
  144. window.close();
  145. }
  146. function save(xhtml)
  147. {
  148. try {
  149. var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
  150. createInstance(Components.interfaces.nsIFileOutputStream);
  151. foStream.init(destFile, 0x02 | 0x08 | 0x20, 0666, 0);
  152. // write, create, truncate
  153. // write in UTF-8 encoding
  154. var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
  155. createInstance(Components.interfaces.nsIConverterOutputStream);
  156. converter.init(foStream, "UTF-8", 0, 0);
  157. converter.writeString(xhtml);
  158. converter.close(); // this closes foStream
  159. } catch (e) {
  160. alert("Error in save():\n\n" + e);
  161. }
  162. }