diff --git a/trypandoc/index.html b/trypandoc/index.html
index 08b1cad95..1b04d6114 100644
--- a/trypandoc/index.html
+++ b/trypandoc/index.html
@@ -99,9 +99,9 @@
       </label>
       <select id="examples">
         <option value="" selected disabled>Select an example</option>
-        <option value="https://pandoc.org/try/?text=%40BOOK%7BWurm2011-ho%2C%0A++title+++++%3D+%22%7BSubstanz+und+Qualität+%3A+Ein+Beitrag+zur+Interpretation+der%0A+++++++++++++++plotinischen+Traktate+VI%2C1%2C+2+und+3%7D%22%2C%0A++author++++%3D+%22Wurm%2C+Klaus%22%2C%0A++publisher+%3D+%22De+Gruyter%22%2C%0A++series++++%3D+%22Quellen+und+Studien+zur+Philosophie%22%2C%0A++edition+++%3D+%22Reprint+2011%22%2C%0A++year++++++%3D++2011%2C%0A++address+++%3D+%22Berlin%22%2C%0A++keywords++%3D+%22%21%21%21+Plotinus+translation%22%2C%0A++language++%3D+%22de%22%0A%7D%0A&from=bibtex&to=csljson&standalone=false&citeproc=true">BibTeX to CSL JSON</option>
+        <option value="https://pandoc.org/try/?text=%40BOOK%7BWurm2011-ho%2C%0A++title+++++%3D+%22%7BSubstanz+und+Qualität+%3A+Ein+Beitrag+zur+Interpretation+der%0A+++++++++++++++plotinischen+Traktate+VI%2C1%2C+2+und+3%7D%22%2C%0A++author++++%3D+%22Wurm%2C+Klaus%22%2C%0A++publisher+%3D+%22De+Gruyter%22%2C%0A++series++++%3D+%22Quellen+und+Studien+zur+Philosophie%22%2C%0A++edition+++%3D+%22Reprint+2011%22%2C%0A++year++++++%3D++2011%2C%0A++address+++%3D+%22Berlin%22%2C%0A++keywords++%3D+%22%21%21%21+Plotinus+translation%22%2C%0A++language++%3D+%22de%22%0A%7D%0A&from=bibtex&to=csljson&standalone=false">BibTeX to CSL JSON</option>
         <option value="https://pandoc.org/try/?text=---%0Areferences%3A%0A-+author%3A%0A++-+family%3A+Salam%0A++++given%3A+Abdus%0A++container-title%3A+%22Elementary+particle+theory%3A+Relativistic+groups+and%0A++++analyticity.+Proceedings+of+the+eighth+Nobel+symposium%22%0A++editor%3A%0A++-+family%3A+Svartholm%0A++++given%3A+Nils%0A++event-date%3A+1968-05-19%2F1968-05-25%0A++event-place%3A+Aspenäsgarden%2C+Lerum%0A++id%3A+salam%0A++issued%3A+1968%0A++page%3A+367-377%0A++publisher%3A+Almquist+%26+Wiksell%0A++publisher-place%3A+Stockholm%0A++title%3A+Weak+and+electromagnetic+interactions%0A++type%3A+paper-conference%0A---%0A%0A%40salam+%5Bp.+370%5D+says+some+interesting+things.%0A&from=markdown&to=man&standalone=false&citeproc=true">Markdown to man with citation</option>
-        <option value="https://pandoc.org/try/?text=%3D%3D+Definition+%3D%3D%0AAlthough+seemingly+different%2C+the+various+approaches+to+defining+tensors+describe+the+same+geometric+concept+using+different+language+and+at+different+levels+of+abstraction.%0A%0A%3D%3D%3D+As+multidimensional+arrays+%3D%3D%3D%0AA+tensor+may+be+represented+as+an+array+%28potentially+multidimensional%29.+Just+as+a+%5B%5BVector+space%7Cvector%5D%5D+in+an+%7B%7Bmvar%7Cn%7D%7D-%5B%5Bdimension+%28vector+space%29%7Cdimensional%5D%5D+space+is+represented+by+a+one-dimensional+array+with+%7B%7Bmvar%7Cn%7D%7D+components+with+respect+to+a+given+%5B%5BBasis+%28linear+algebra%29%23Ordered+bases+and+coordinates%7Cbasis%5D%5D%2C+any+tensor+with+respect+to+a+basis+is+represented+by+a+multidimensional+array.++For+example%2C+a+%5B%5Blinear+operator%5D%5D+is+represented+in+a+basis+as+a+two-dimensional+square+%7B%7Bmath%7C%27%27n%27%27+×+%27%27n%27%27%7D%7D+array.++The+numbers+in+the+multidimensional+array+are+known+as+the+%27%27scalar+components%27%27+of+the+tensor+or+simply+its+%27%27components%27%27.++They+are+denoted+by+indices+giving+their+position+in+the+array%2C+as+%5B%5Bsubscript+and+superscript%7Csubscripts+and+superscripts%5D%5D%2C+following+the+symbolic+name+of+the+tensor.++For+example%2C+the+components+of+an+order+%7B%7Bmath%7C2%7D%7D+tensor+%7B%7Bmvar%7CT%7D%7D+could+be+denoted+%7B%7Bmath%7C%27%27T%27%27%3Csub%3E%27%27ij%27%27%3C%2Fsub%3E%7D%7D%E2%80%AF%2C+where+%7B%7Bmvar%7Ci%7D%7D+and+%7B%7Bmvar%7Cj%7D%7D+are+indices+running+from+%7B%7Bmath%7C1%7D%7D+to+%7B%7Bmvar%7Cn%7D%7D%2C+or+also+by+%7B%7Bmath%7C%27%27T%27%27%26thinsp%3B%7B%7Bsu%7Cb%3D%27%27j%27%27%7Cp%3D%27%27i%27%27%7D%7D%7D%7D.++Whether+an+index+is+displayed+as+a+superscript+or+subscript+depends+on+the+transformation+properties+of+the+tensor%2C+described+below.+Thus+while+%7B%7Bmath%7C%27%27T%27%27%3Csub%3E%27%27ij%27%27%3C%2Fsub%3E%7D%7D+and+%7B%7Bmath%7C%27%27T%27%27%26thinsp%3B%7B%7Bsu%7Cb%3D%27%27j%27%27%7Cp%3D%27%27i%27%27%7D%7D%7D%7D+can+both+be+expressed+as+%27%27n%27%27+by+%27%27n%27%27+matrices%2C+and+are+numerically+related+via+%5B%5BRaising+and+lowering+indices%7Cindex+juggling%5D%5D%2C+the+difference+in+their+transformation+laws+indicates+it+would+be+improper+to+add+them+together.+The+total+number+of+indices+required+to+identify+each+component+uniquely+is+equal+to+the+%5B%5BArray+data+structure%23Dimension%7Cdimension%5D%5D+of+the+array%2C+and+is+called+the+%27%27order%27%27%2C+%27%27degree%27%27+or+%27%27rank%27%27+of+the+tensor.++However%2C+the+term+%22rank%22+generally+has+%5B%5Btensor+rank%7Canother+meaning%5D%5D+in+the+context+of+matrices+and+tensors.%0A%0AJust+as+the+components+of+a+vector+change+when+we+change+the+%5B%5Bbasis+%28linear+algebra%29%7Cbasis%5D%5D+of+the+vector+space%2C+the+components+of+a+tensor+also+change+under+such+a+transformation.++Each+type+of+tensor+comes+equipped+with+a+%27%27transformation+law%27%27+that+details+how+the+components+of+the+tensor+respond+to+a+%5B%5Bchange+of+basis%5D%5D.++The+components+of+a+vector+can+respond+in+two+distinct+ways+to+a+%5B%5Bchange+of+basis%5D%5D+%28see+%5B%5Bcovariance+and+contravariance+of+vectors%5D%5D%29%2C+where+the+new+%5B%5Bbasis+vectors%5D%5D+%3Cmath%3E%5Cmathbf%7B%5Chat%7Be%7D%7D_i%3C%2Fmath%3E+are+expressed+in+terms+of+the+old+basis+vectors+%3Cmath%3E%5Cmathbf%7Be%7D_j%3C%2Fmath%3E+as%2C%0A%3A%3Cmath%3E%5Cmathbf%7B%5Chat%7Be%7D%7D_i+%3D+%5Csum_%7Bj%3D1%7D%5En+%5Cmathbf%7Be%7D_j+R%5Ej_i+%3D+%5Cmathbf%7Be%7D_j+R%5Ej_i+.%3C%2Fmath%3E%0A%0AHere+%27%27R%27%27%3Csup%3E%27%27+j%27%27%3C%2Fsup%3E%3Csub%3E%27%27i%27%27%3C%2Fsub%3E+are+the+entries+of+the+change+of+basis+matrix%2C+and+in+the+rightmost+expression+the+%5B%5Bsummation%5D%5D+sign+was+suppressed%3A+this+is+the+%5B%5BEinstein+summation+convention%5D%5D%2C+which+will+be+used+throughout+this+article.%3Cref+group%3D%22Note%22%3EThe+Einstein+summation+convention%2C+in+brief%2C+requires+the+sum+to+be+taken+over+all+values+of+the+index+whenever+the+same+symbol+appears+as+a+subscript+and+superscript+in+the+same+term.++For+example%2C+under+this+convention+%3Cmath%3EB_i+C%5Ei+%3D+B_1+C%5E1+%2B+B_2+C%5E2+%2B+%5Ccdots+B_n+C%5En%3C%2Fmath%3E%3C%2Fref%3E++The+components+%27%27v%27%27%3Csup%3E%27%27i%27%27%3C%2Fsup%3E+of+a+column+vector+%27%27%27v%27%27%27+transform+with+the+%5B%5Bmatrix+inverse%7Cinverse%5D%5D+of+the+matrix+%27%27R%27%27%2C%0A%3A%3Cmath%3E%5Chat%7Bv%7D%5Ei+%3D+%5Cleft%28R%5E%7B-1%7D%5Cright%29%5Ei_j+v%5Ej%2C%3C%2Fmath%3E%0A%0Awhere+the+hat+denotes+the+components+in+the+new+basis.++This+is+called+a+%27%27contravariant%27%27+transformation+law%2C+because+the+vector+components+transform+by+the+%27%27inverse%27%27+of+the+change+of+basis.++In+contrast%2C+the+components%2C+%27%27w%27%27%3Csub%3E%27%27i%27%27%3C%2Fsub%3E%2C+of+a+covector+%28or+row+vector%29%2C+%27%27%27w%27%27%27%2C+transform+with+the+matrix+%27%27R%27%27+itself%2C%0A%3A%3Cmath%3E%5Chat%7Bw%7D_i+%3D+w_j+R%5Ej_i+.%3C%2Fmath%3E&from=mediawiki&to=docx&standalone=false&citeproc=true">MediaWiki to docx with equations</option>
+        <option value="https://pandoc.org/try/?text=%3D%3D+Definition+%3D%3D%0AAlthough+seemingly+different%2C+the+various+approaches+to+defining+tensors+describe+the+same+geometric+concept+using+different+language+and+at+different+levels+of+abstraction.%0A%0A%3D%3D%3D+As+multidimensional+arrays+%3D%3D%3D%0AA+tensor+may+be+represented+as+an+array+%28potentially+multidimensional%29.+Just+as+a+%5B%5BVector+space%7Cvector%5D%5D+in+an+%7B%7Bmvar%7Cn%7D%7D-%5B%5Bdimension+%28vector+space%29%7Cdimensional%5D%5D+space+is+represented+by+a+one-dimensional+array+with+%7B%7Bmvar%7Cn%7D%7D+components+with+respect+to+a+given+%5B%5BBasis+%28linear+algebra%29%23Ordered+bases+and+coordinates%7Cbasis%5D%5D%2C+any+tensor+with+respect+to+a+basis+is+represented+by+a+multidimensional+array.++For+example%2C+a+%5B%5Blinear+operator%5D%5D+is+represented+in+a+basis+as+a+two-dimensional+square+%7B%7Bmath%7C%27%27n%27%27+×+%27%27n%27%27%7D%7D+array.++The+numbers+in+the+multidimensional+array+are+known+as+the+%27%27scalar+components%27%27+of+the+tensor+or+simply+its+%27%27components%27%27.++They+are+denoted+by+indices+giving+their+position+in+the+array%2C+as+%5B%5Bsubscript+and+superscript%7Csubscripts+and+superscripts%5D%5D%2C+following+the+symbolic+name+of+the+tensor.++For+example%2C+the+components+of+an+order+%7B%7Bmath%7C2%7D%7D+tensor+%7B%7Bmvar%7CT%7D%7D+could+be+denoted+%7B%7Bmath%7C%27%27T%27%27%3Csub%3E%27%27ij%27%27%3C%2Fsub%3E%7D%7D%E2%80%AF%2C+where+%7B%7Bmvar%7Ci%7D%7D+and+%7B%7Bmvar%7Cj%7D%7D+are+indices+running+from+%7B%7Bmath%7C1%7D%7D+to+%7B%7Bmvar%7Cn%7D%7D%2C+or+also+by+%7B%7Bmath%7C%27%27T%27%27%26thinsp%3B%7B%7Bsu%7Cb%3D%27%27j%27%27%7Cp%3D%27%27i%27%27%7D%7D%7D%7D.++Whether+an+index+is+displayed+as+a+superscript+or+subscript+depends+on+the+transformation+properties+of+the+tensor%2C+described+below.+Thus+while+%7B%7Bmath%7C%27%27T%27%27%3Csub%3E%27%27ij%27%27%3C%2Fsub%3E%7D%7D+and+%7B%7Bmath%7C%27%27T%27%27%26thinsp%3B%7B%7Bsu%7Cb%3D%27%27j%27%27%7Cp%3D%27%27i%27%27%7D%7D%7D%7D+can+both+be+expressed+as+%27%27n%27%27+by+%27%27n%27%27+matrices%2C+and+are+numerically+related+via+%5B%5BRaising+and+lowering+indices%7Cindex+juggling%5D%5D%2C+the+difference+in+their+transformation+laws+indicates+it+would+be+improper+to+add+them+together.+The+total+number+of+indices+required+to+identify+each+component+uniquely+is+equal+to+the+%5B%5BArray+data+structure%23Dimension%7Cdimension%5D%5D+of+the+array%2C+and+is+called+the+%27%27order%27%27%2C+%27%27degree%27%27+or+%27%27rank%27%27+of+the+tensor.++However%2C+the+term+%22rank%22+generally+has+%5B%5Btensor+rank%7Canother+meaning%5D%5D+in+the+context+of+matrices+and+tensors.%0A%0AJust+as+the+components+of+a+vector+change+when+we+change+the+%5B%5Bbasis+%28linear+algebra%29%7Cbasis%5D%5D+of+the+vector+space%2C+the+components+of+a+tensor+also+change+under+such+a+transformation.++Each+type+of+tensor+comes+equipped+with+a+%27%27transformation+law%27%27+that+details+how+the+components+of+the+tensor+respond+to+a+%5B%5Bchange+of+basis%5D%5D.++The+components+of+a+vector+can+respond+in+two+distinct+ways+to+a+%5B%5Bchange+of+basis%5D%5D+%28see+%5B%5Bcovariance+and+contravariance+of+vectors%5D%5D%29%2C+where+the+new+%5B%5Bbasis+vectors%5D%5D+%3Cmath%3E%5Cmathbf%7B%5Chat%7Be%7D%7D_i%3C%2Fmath%3E+are+expressed+in+terms+of+the+old+basis+vectors+%3Cmath%3E%5Cmathbf%7Be%7D_j%3C%2Fmath%3E+as%2C%0A%3A%3Cmath%3E%5Cmathbf%7B%5Chat%7Be%7D%7D_i+%3D+%5Csum_%7Bj%3D1%7D%5En+%5Cmathbf%7Be%7D_j+R%5Ej_i+%3D+%5Cmathbf%7Be%7D_j+R%5Ej_i+.%3C%2Fmath%3E%0A%0AHere+%27%27R%27%27%3Csup%3E%27%27+j%27%27%3C%2Fsup%3E%3Csub%3E%27%27i%27%27%3C%2Fsub%3E+are+the+entries+of+the+change+of+basis+matrix%2C+and+in+the+rightmost+expression+the+%5B%5Bsummation%5D%5D+sign+was+suppressed%3A+this+is+the+%5B%5BEinstein+summation+convention%5D%5D%2C+which+will+be+used+throughout+this+article.%3Cref+group%3D%22Note%22%3EThe+Einstein+summation+convention%2C+in+brief%2C+requires+the+sum+to+be+taken+over+all+values+of+the+index+whenever+the+same+symbol+appears+as+a+subscript+and+superscript+in+the+same+term.++For+example%2C+under+this+convention+%3Cmath%3EB_i+C%5Ei+%3D+B_1+C%5E1+%2B+B_2+C%5E2+%2B+%5Ccdots+B_n+C%5En%3C%2Fmath%3E%3C%2Fref%3E++The+components+%27%27v%27%27%3Csup%3E%27%27i%27%27%3C%2Fsup%3E+of+a+column+vector+%27%27%27v%27%27%27+transform+with+the+%5B%5Bmatrix+inverse%7Cinverse%5D%5D+of+the+matrix+%27%27R%27%27%2C%0A%3A%3Cmath%3E%5Chat%7Bv%7D%5Ei+%3D+%5Cleft%28R%5E%7B-1%7D%5Cright%29%5Ei_j+v%5Ej%2C%3C%2Fmath%3E%0A%0Awhere+the+hat+denotes+the+components+in+the+new+basis.++This+is+called+a+%27%27contravariant%27%27+transformation+law%2C+because+the+vector+components+transform+by+the+%27%27inverse%27%27+of+the+change+of+basis.++In+contrast%2C+the+components%2C+%27%27w%27%27%3Csub%3E%27%27i%27%27%3C%2Fsub%3E%2C+of+a+covector+%28or+row+vector%29%2C+%27%27%27w%27%27%27%2C+transform+with+the+matrix+%27%27R%27%27+itself%2C%0A%3A%3Cmath%3E%5Chat%7Bw%7D_i+%3D+w_j+R%5Ej_i+.%3C%2Fmath%3E&from=mediawiki&to=docx&standalone=false">MediaWiki to docx with equations</option>
       </select>
 
     </div>
@@ -176,166 +176,7 @@
   </div>
 </div>
 
-<script>
-"use strict";
-
-var params = {
-  text: '"hello *world*"',
-  to: 'html5',
-  from: 'markdown',
-  standalone: false,
-  citeproc: false };
-
-function permalink() {
-  let input = document.getElementById("text").value;
-  let from = document.getElementById("from").value;
-  let to = document.getElementById("to").value;
-  let standalone = document.getElementById("standalone").checked ? true : false;
-  let citeproc = document.getElementById("citeproc").checked ? true : false;
-  let href = window.location.href;
-  const URLparams = new URLSearchParams(Object.entries({text: input, from: from, to: to, standalone: standalone, citeproc: citeproc}));
-  return href.replace(/([?].*)?$/,"?" + URLparams);
-}
-
-const binaryFormats = {
-   docx: { extension: "docx",
-           mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" },
-    odt: { extension: "odt",
-           mime: "application/vnd.oasis.opendocument.text" },
-    pptx: { extension: "pptx",
-            mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation" },
-    epub:  { extension: "epub",
-             mime: "application/epub+zip" },
-    epub2: { extension: "epub",
-             mime: "application/epub+zip" },
-    epub3: { extension: "epub",
-             mime: "application/epub+zip" }
-};
-
-const binaryMimeTypes = {
-  ["application/epub+zip"]: true,
-  ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"]: true,
-  ["application/vnd.openxmlformats-officedocument.presentationml.presentation"]: true,
-  ["application/vnd.oasis.opendocument.text"]: true
-};
-
-function paramsFromURL() {
-  if (window.location.search.length > 0) {
-    const uparams = new URLSearchParams(window.location.search);
-    params.text = uparams.get("text") || "";
-    params.from = uparams.get("from") || "markdown";
-    params.to = uparams.get("to") || "html5";
-    params.standalone = uparams.get("standalone") === "true";
-    params.citeproc = uparams.get("citeproc") === "true";
-  }
-}
-
-function handleErrors(response) {
-    if (!response.ok) {
-        throw Error(response.statusText);
-    }
-    return response;
-}
-
-function convert() {
-    let text = document.getElementById("text").value;
-    let from = document.getElementById("from").value;
-    let to = document.getElementById("to").value;
-    let standalone = document.getElementById("standalone").checked;
-    let citeproc = document.getElementById("citeproc").checked;
-    params = { text: text, from: from, to: to, standalone: standalone,
-               citeproc: citeproc };
-
-    if (text && text != "") {
-       fetch("/cgi-bin/pandoc-server.cgi/version")
-          .then(handleErrors)
-          .catch(error =>
-            document.getElementById("results").textContent = error
-            )
-          .then(response => response.text())
-          .then(restext =>
-              document.getElementById("version").textContent = restext
-            );
-
-       // console.log(JSON.stringify(params));
-       let commandString = "pandoc"
-         + " --from " + from + " --to " + to
-         + (standalone ? " --standalone" : "")
-         + (citeproc ? " --citeproc" : "") ;
-       document.getElementById("command").textContent = commandString;
-       fetch("/cgi-bin/pandoc-server.cgi", {
-         method: "POST",
-         headers: {"Content-Type": "application/json"},
-         body: JSON.stringify(params)
-        })
-       .then(response => response.text())
-       .then(restext => {
-            let binary = binaryFormats[to];
-            if (binary) {
-            document.getElementById("results").innerHTML =
-                '<a download="trypandoc.' + binary.extension +
-                '" href="data:' + binary.mime + ';base64,' + restext +
-                '">click to download trypandoc.' + binary.extension + '</a>';
-          } else {
-            document.getElementById("results").textContent = restext;
-          }
-          document.getElementById("permalink").href = permalink();
-       });
-    };
-}
-
-(function() {
-    paramsFromURL();
-    document.getElementById("text").value = params.text;
-    document.getElementById("from").value = params.from;
-    document.getElementById("to").value = params.to;
-    document.getElementById("standalone").checked = params.standalone;
-    document.getElementById("citeproc").checked = params.citeproc;
-
-    document.getElementById("convert").onclick = convert;
-    document.getElementById("from").onchange = convert;
-    document.getElementById("to").onchange = convert;
-    document.getElementById("standalone").onchange = convert;
-    document.getElementById("citeproc").onchange = convert;
-
-    document.getElementById("examples").onchange =
-      (e => window.location.href = e.target.value );
-
-    const fileInput = document.getElementById('loadfile');
-
-    // Listen for the change event so we can capture the file
-    fileInput.addEventListener('change', (e) => {
-      // Get a reference to the file
-      const file = e.target.files[0];
-      const mimetype = file.type;
-      let binary = binaryMimeTypes[mimetype];
-
-      // Encode the file using the FileReader API
-      const reader = new FileReader();
-      let inputtext = document.getElementById("text");
-      reader.onloadend = () => {
-        // Use a regex to remove data url part
-        console.log(mimetype);
-        if (binary) {
-          const base64String = reader.result
-           .replace('data:', '')
-           .replace(/^.+,/, '');
-          inputtext.value = base64String;
-	} else {
-          inputtext.value = reader.result;
-        }
-      };
-      if (binary) {
-        reader.readAsDataURL(file);
-      } else {
-        reader.readAsText(file);
-      }
-    });
-
-    convert();
-
-})();
-  </script>
+<script src="trypandoc.js"></script>
 
 </body>
 </html>
diff --git a/trypandoc/trypandoc.js b/trypandoc/trypandoc.js
new file mode 100644
index 000000000..59f606f03
--- /dev/null
+++ b/trypandoc/trypandoc.js
@@ -0,0 +1,159 @@
+"use strict";
+
+var params = {
+  text: '"hello *world*"',
+  to: 'html5',
+  from: 'markdown',
+  standalone: false,
+  citeproc: false };
+
+function permalink() {
+  let input = document.getElementById("text").value;
+  let from = document.getElementById("from").value;
+  let to = document.getElementById("to").value;
+  let standalone = document.getElementById("standalone").checked ? true : false;
+  let citeproc = document.getElementById("citeproc").checked ? true : false;
+  let href = window.location.href;
+  const URLparams = new URLSearchParams(Object.entries({text: input, from: from, to: to, standalone: standalone, citeproc: citeproc}));
+  return href.replace(/([?].*)?$/,"?" + URLparams);
+}
+
+const binaryFormats = {
+   docx: { extension: "docx",
+           mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" },
+    odt: { extension: "odt",
+           mime: "application/vnd.oasis.opendocument.text" },
+    pptx: { extension: "pptx",
+            mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation" },
+    epub:  { extension: "epub",
+             mime: "application/epub+zip" },
+    epub2: { extension: "epub",
+             mime: "application/epub+zip" },
+    epub3: { extension: "epub",
+             mime: "application/epub+zip" }
+};
+
+const binaryMimeTypes = {
+  ["application/epub+zip"]: true,
+  ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"]: true,
+  ["application/vnd.openxmlformats-officedocument.presentationml.presentation"]: true,
+  ["application/vnd.oasis.opendocument.text"]: true
+};
+
+function paramsFromURL() {
+  if (window.location.search.length > 0) {
+    const uparams = new URLSearchParams(window.location.search);
+    params.text = uparams.get("text") || "";
+    params.from = uparams.get("from") || "markdown";
+    params.to = uparams.get("to") || "html5";
+    params.standalone = uparams.get("standalone") === "true";
+    params.citeproc = uparams.get("citeproc") === "true";
+  }
+}
+
+function handleErrors(response) {
+    if (!response.ok) {
+        throw Error(response.statusText);
+    }
+    return response;
+}
+
+function convert() {
+    let text = document.getElementById("text").value;
+    let from = document.getElementById("from").value;
+    let to = document.getElementById("to").value;
+    let standalone = document.getElementById("standalone").checked;
+    let citeproc = document.getElementById("citeproc").checked;
+    params = { text: text, from: from, to: to, standalone: standalone,
+               citeproc: citeproc };
+
+    if (text && text != "") {
+       fetch("/cgi-bin/pandoc-server.cgi/version")
+          .then(handleErrors)
+          .catch(error =>
+            document.getElementById("results").textContent = error
+            )
+          .then(response => response.text())
+          .then(restext =>
+              document.getElementById("version").textContent = restext
+            );
+
+       // console.log(JSON.stringify(params));
+       let commandString = "pandoc"
+         + " --from " + from + " --to " + to
+         + (standalone ? " --standalone" : "")
+         + (citeproc ? " --citeproc" : "") ;
+       document.getElementById("command").textContent = commandString;
+       fetch("/cgi-bin/pandoc-server.cgi", {
+         method: "POST",
+         headers: {"Content-Type": "application/json"},
+         body: JSON.stringify(params)
+        })
+       .then(response => response.text())
+       .then(restext => {
+            let binary = binaryFormats[to];
+            if (binary) {
+            document.getElementById("results").innerHTML =
+                '<a download="trypandoc.' + binary.extension +
+                '" href="data:' + binary.mime + ';base64,' + restext +
+                '">click to download trypandoc.' + binary.extension + '</a>';
+          } else {
+            document.getElementById("results").textContent = restext;
+          }
+          document.getElementById("permalink").href = permalink();
+       });
+    };
+}
+
+(function() {
+    paramsFromURL();
+    document.getElementById("text").value = params.text;
+    document.getElementById("from").value = params.from;
+    document.getElementById("to").value = params.to;
+    document.getElementById("standalone").checked = params.standalone;
+    document.getElementById("citeproc").checked = params.citeproc;
+
+    document.getElementById("convert").onclick = convert;
+    document.getElementById("from").onchange = convert;
+    document.getElementById("to").onchange = convert;
+    document.getElementById("standalone").onchange = convert;
+    document.getElementById("citeproc").onchange = convert;
+
+    document.getElementById("examples").onchange =
+      (e => window.location.href = e.target.value );
+
+    const fileInput = document.getElementById('loadfile');
+
+    // Listen for the change event so we can capture the file
+    fileInput.addEventListener('change', (e) => {
+      // Get a reference to the file
+      const file = e.target.files[0];
+      const mimetype = file.type;
+      let binary = binaryMimeTypes[mimetype];
+
+      // Encode the file using the FileReader API
+      const reader = new FileReader();
+      let inputtext = document.getElementById("text");
+      reader.onloadend = () => {
+        // Use a regex to remove data url part
+        console.log(mimetype);
+        if (binary) {
+          const base64String = reader.result
+           .replace('data:', '')
+           .replace(/^.+,/, '');
+          inputtext.value = base64String;
+	} else {
+          inputtext.value = reader.result;
+        }
+      };
+      if (binary) {
+        reader.readAsDataURL(file);
+      } else {
+        reader.readAsText(file);
+      }
+    });
+
+    convert();
+
+})();
+