changeset 946:420ad90116e6 draft

MathJax preview initial version
author HIROSE Yuuji <yuuji@gentei.org>
date Tue, 26 Oct 2021 13:16:29 +0900
parents 29342754a2d0
children b7f9c4ce8cbd
files s4-blog.sh s4-funcs.sh s4-main.js
diffstat 3 files changed, 106 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/s4-blog.sh	Mon Oct 25 23:25:56 2021 +0900
+++ b/s4-blog.sh	Tue Oct 26 13:16:29 2021 +0900
@@ -270,7 +270,7 @@
 	;;
     esac
   fi
-  href4="${blog_math:+Math} <a href=\"#bottom\" accesskey=\"b\" title=\"Shortcut: B${nl}to the Bottom\"> 末尾へ</a>"
+  href4="${blog_math:+<span id=\"mathjax\">Math</span>} <a href=\"#bottom\" accesskey=\"b\" title=\"Shortcut: B${nl}to the Bottom\"> 末尾へ</a>"
   $isgrpadmin &&
       href5="<a href=\"?blogseen+$rowid\" accesskey=\"s\" title=\"Shortcut: S${nl}State of Accesses\"> 読刻</a>"
   quizmodefile=$tmpd/quiz; rm -f "$quizmodefile"	# XXX: Global state
@@ -417,7 +417,7 @@
     echo "時間をおいてください(Visit later please)." | html p
     return
   fi
-  echo "${blog_math:+$mathjax}"
+  printf '%s' "${blog_math:+$mathjax}"
   echo '<table class="blog_replies"> <!-- blog:blog_showentry() main table -->'
   # If, nLimit = 50
   # show article:1, hide(2, 3), show(4, ...)
--- a/s4-funcs.sh	Mon Oct 25 23:25:56 2021 +0900
+++ b/s4-funcs.sh	Tue Oct 26 13:16:29 2021 +0900
@@ -3502,6 +3502,7 @@
   owner=`getvalbyid blog owner $blogrowid`
   title=`getvalbyid blog title $blogrowid`
   author=`getvalbyid article author $rowid`
+  math=`getvalbyid blog mathjax $blogrowid`
   ## err EDITart: owner=$owner, author=$author
   if isgrpowner "$user" "$owner"; then
     : EDIT OK
@@ -3514,7 +3515,7 @@
   GF_ACTION="?replyblog+$blogrowid#$aid" \
 	   edittable $formdir/article.def article $rowid \
 	   > $tmpout
-  rm -f /tmp/editart.out
+  printf '%s' "${math:+$mathjax}" >> $tmpout
   # Cannot use pipelining to m4 with genform() because of stdin stack
   _m4 -D_TITLE_="コメントの修正" -D_DIARY_="" \
       -D_FORM_="syscmd(cat $tmpout)" \
--- a/s4-main.js	Mon Oct 25 23:25:56 2021 +0900
+++ b/s4-main.js	Tue Oct 26 13:16:29 2021 +0900
@@ -6,6 +6,7 @@
     var myurl = document.URL,
 	mypath = myurl.substring(myurl.lastIndexOf("/"));
     var art_m_list = [];
+    var mathjax = false;
     let input_pdfsw = 'input[name="comppdf"]';
     if (mypath.match(/(.*)\/(.*)/)) {
 	mypath = RegExp.$2;
@@ -114,6 +115,14 @@
 		if (RegExp.lastMatch == i.innerHTML)
 		    i.addEventListener("click", insertRedirect, false)
     }
+    function mathjaxUpdate(arg) {
+	try {
+	    if (MathJax && MathJax.typesetPromise) {
+		MathJax.texReset();		// Reset Math counters
+		MathJax.typesetPromise(arg); // MathJax v3
+	    }
+	} catch (err) {console.log(err);}
+    }
     var ajaxSubmit;
     function replAddNews(newtable) {
 	let newids = [], idlist=[];
@@ -176,11 +185,7 @@
 	    }, 100);
 	    cnt++;
 	}
-	try {
-	    if (MathJax && MathJax.typesetPromise) {
-		MathJax.typesetPromise(); // MathJax v3
-	    }
-	} catch (err) {}
+	mathjaxUpdate(newids);
 	console.log("Update "+cnt+"rows");
 	if (cnt>0 && ntr.scrollIntoView) {
 	    let option = {behavior: "smooth"};
@@ -454,6 +459,9 @@
 	bt.focus();
 	setTimeout(() => {box.classList.add("pjaxview2");}, 10);
 	// Finally update history stack
+	pjaxHistoryPush(box);
+    }
+    function pjaxHistoryPush(box) {
 	if (history.pushState) {
 	    let h = location.href.replace(/#.*/, '')+"#pjaxview";
 	    history.pushState({url: h}, null, h);
@@ -591,10 +599,84 @@
 	    
 	}
     }
+    var helpParenPreview = 0;
+    function helpMarkdownParen(e) {
+	if (!mathjax) return;
+	var area = e.target, pos = area.selectionStart, text = area.value;
+	if (pos<2) return;
+	if (text[pos-1] == "\\") {
+	    let ins="(  \\)";
+	    if (text[pos-2] == "\\") ins="(  \\\\)";
+	    area.setRangeText(ins, pos, pos);
+	    area.selectionStart = pos+2;
+	    if (helpParenPreview++ < 1) {
+		dispInfoMomentary("Preview formula by Meta-p\n"+
+				  "Meta-p で数式プレビュー", e.target.parentNode);
+	    }
+	    e.preventDefault();
+	}
+    }
+    function textInsert(area, pos, string) {
+	
+    }
+    function helpMarkdownBrace(e) {
+	if (!mathjax) return;
+	var area = e.target, pos = area.selectionStart, text = area.value,
+	    begin = "\\begin", end = "\\end";
+	if (pos < end.length) return;
+	if (text.substr(pos-end.length).startsWith(end)) {
+	    let beg = text.lastIndexOf(begin, pos);
+	    if (beg >= 0) {
+		let env = text.substr(beg).search(/\\begin{(.*?)}/);
+		if (env >= 0) {
+		    let endenv = "{"+RegExp.$1+"}";
+		    area.setRangeText(endenv, pos, pos);
+		    area.selectionStart += endenv.length;
+		    e.preventDefault();
+		}
+	    }
+	}
+    }
+    function helpMarkdownPreview(area) {
+	if (!mathjax) {
+	    alert("no"+e.target)
+	    dispInfoMomentary("This board has no MathJax mode.\n"+
+			      "この掲示板は数式モードOFFです。",
+			      e.target.parentNode);
+	    return;
+	}
+	let text = area.value;
+	let preview = document.createElement("div");
+	let bp = document.createElement("p");
+	let btn = document.createElement("button");
+	btn.innerText = "Click or ESC to Dissmiss / クリックかESCで戻る";
+	bp.classList.add("c");
+	preview.classList.add("pjaxview");
+	preview.classList.add("pjaxview2");
+	let pre = document.createElement("p");
+	bp.appendChild(btn);
+	preview.appendChild(bp);
+	preview.appendChild(pre);
+	pre.innerText = text;
+	document.body.appendChild(preview);
+	function dismiss(t) {
+	    history.back();
+	    preview.remove();
+	    area.focus();
+	}
+	preview.addEventListener("click", dismiss, false);
+	preview.addEventListener("keydown", dismiss, false);
+	MathJax.typesetPromise([pre]);
+	pjaxHistoryPush(preview);
+	btn.focus();
+    }
     function helpMarkdown(e) {
 	switch (e.key) {
 	case "Backspace": helpMarkdownBS(e); break;
 	case "Enter":  helpMarkdownEnter(e); break;
+	case "(":  helpMarkdownParen(e); break;
+	case "p":  if (e.metaKey) helpMarkdownPreview(e.target); break;
+	case "{":  helpMarkdownBrace(e); break;
 	}
     }
     /* Init event listeners */
@@ -843,6 +925,20 @@
 	    }
 	}
     }
+    function initMath() {
+	mathjax = MathJax||document.getElementById("mathjax");
+	if (!mathjax) return;
+	let ta = document.querySelector("textarea");
+	if (!ta) return;
+	let btn = document.createElement("button");
+	btn.innerHTML = "MathJax<br>Preview";
+	btn.addEventListener('click', (e) => {
+	    e.preventDefault();
+	    ta.focus();
+	    helpMarkdownPreview(ta);
+	});
+	ta.insertAdjacentElement('afterend', btn);
+    }
     function init() {
 	isOlderJS = !("insertAdjacentElement" in document.body);
 	initGrpAction();
@@ -850,6 +946,7 @@
 	initFileInput();
 	initTextarea();
 	initGrphome();
+	initMath();
     }
     document.addEventListener('DOMContentLoaded', init, null);
 })();

yatex.org