s4

changeset 946:420ad90116e6

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 diff
     1.1 --- a/s4-blog.sh	Mon Oct 25 23:25:56 2021 +0900
     1.2 +++ b/s4-blog.sh	Tue Oct 26 13:16:29 2021 +0900
     1.3 @@ -270,7 +270,7 @@
     1.4  	;;
     1.5      esac
     1.6    fi
     1.7 -  href4="${blog_math:+Math} <a href=\"#bottom\" accesskey=\"b\" title=\"Shortcut: B${nl}to the Bottom\"> 末尾へ</a>"
     1.8 +  href4="${blog_math:+<span id=\"mathjax\">Math</span>} <a href=\"#bottom\" accesskey=\"b\" title=\"Shortcut: B${nl}to the Bottom\"> 末尾へ</a>"
     1.9    $isgrpadmin &&
    1.10        href5="<a href=\"?blogseen+$rowid\" accesskey=\"s\" title=\"Shortcut: S${nl}State of Accesses\"> 読刻</a>"
    1.11    quizmodefile=$tmpd/quiz; rm -f "$quizmodefile"	# XXX: Global state
    1.12 @@ -417,7 +417,7 @@
    1.13      echo "時間をおいてください(Visit later please)." | html p
    1.14      return
    1.15    fi
    1.16 -  echo "${blog_math:+$mathjax}"
    1.17 +  printf '%s' "${blog_math:+$mathjax}"
    1.18    echo '<table class="blog_replies"> <!-- blog:blog_showentry() main table -->'
    1.19    # If, nLimit = 50
    1.20    # show article:1, hide(2, 3), show(4, ...)
     2.1 --- a/s4-funcs.sh	Mon Oct 25 23:25:56 2021 +0900
     2.2 +++ b/s4-funcs.sh	Tue Oct 26 13:16:29 2021 +0900
     2.3 @@ -3502,6 +3502,7 @@
     2.4    owner=`getvalbyid blog owner $blogrowid`
     2.5    title=`getvalbyid blog title $blogrowid`
     2.6    author=`getvalbyid article author $rowid`
     2.7 +  math=`getvalbyid blog mathjax $blogrowid`
     2.8    ## err EDITart: owner=$owner, author=$author
     2.9    if isgrpowner "$user" "$owner"; then
    2.10      : EDIT OK
    2.11 @@ -3514,7 +3515,7 @@
    2.12    GF_ACTION="?replyblog+$blogrowid#$aid" \
    2.13  	   edittable $formdir/article.def article $rowid \
    2.14  	   > $tmpout
    2.15 -  rm -f /tmp/editart.out
    2.16 +  printf '%s' "${math:+$mathjax}" >> $tmpout
    2.17    # Cannot use pipelining to m4 with genform() because of stdin stack
    2.18    _m4 -D_TITLE_="コメントの修正" -D_DIARY_="" \
    2.19        -D_FORM_="syscmd(cat $tmpout)" \
     3.1 --- a/s4-main.js	Mon Oct 25 23:25:56 2021 +0900
     3.2 +++ b/s4-main.js	Tue Oct 26 13:16:29 2021 +0900
     3.3 @@ -6,6 +6,7 @@
     3.4      var myurl = document.URL,
     3.5  	mypath = myurl.substring(myurl.lastIndexOf("/"));
     3.6      var art_m_list = [];
     3.7 +    var mathjax = false;
     3.8      let input_pdfsw = 'input[name="comppdf"]';
     3.9      if (mypath.match(/(.*)\/(.*)/)) {
    3.10  	mypath = RegExp.$2;
    3.11 @@ -114,6 +115,14 @@
    3.12  		if (RegExp.lastMatch == i.innerHTML)
    3.13  		    i.addEventListener("click", insertRedirect, false)
    3.14      }
    3.15 +    function mathjaxUpdate(arg) {
    3.16 +	try {
    3.17 +	    if (MathJax && MathJax.typesetPromise) {
    3.18 +		MathJax.texReset();		// Reset Math counters
    3.19 +		MathJax.typesetPromise(arg); // MathJax v3
    3.20 +	    }
    3.21 +	} catch (err) {console.log(err);}
    3.22 +    }
    3.23      var ajaxSubmit;
    3.24      function replAddNews(newtable) {
    3.25  	let newids = [], idlist=[];
    3.26 @@ -176,11 +185,7 @@
    3.27  	    }, 100);
    3.28  	    cnt++;
    3.29  	}
    3.30 -	try {
    3.31 -	    if (MathJax && MathJax.typesetPromise) {
    3.32 -		MathJax.typesetPromise(); // MathJax v3
    3.33 -	    }
    3.34 -	} catch (err) {}
    3.35 +	mathjaxUpdate(newids);
    3.36  	console.log("Update "+cnt+"rows");
    3.37  	if (cnt>0 && ntr.scrollIntoView) {
    3.38  	    let option = {behavior: "smooth"};
    3.39 @@ -454,6 +459,9 @@
    3.40  	bt.focus();
    3.41  	setTimeout(() => {box.classList.add("pjaxview2");}, 10);
    3.42  	// Finally update history stack
    3.43 +	pjaxHistoryPush(box);
    3.44 +    }
    3.45 +    function pjaxHistoryPush(box) {
    3.46  	if (history.pushState) {
    3.47  	    let h = location.href.replace(/#.*/, '')+"#pjaxview";
    3.48  	    history.pushState({url: h}, null, h);
    3.49 @@ -591,10 +599,84 @@
    3.50  	    
    3.51  	}
    3.52      }
    3.53 +    var helpParenPreview = 0;
    3.54 +    function helpMarkdownParen(e) {
    3.55 +	if (!mathjax) return;
    3.56 +	var area = e.target, pos = area.selectionStart, text = area.value;
    3.57 +	if (pos<2) return;
    3.58 +	if (text[pos-1] == "\\") {
    3.59 +	    let ins="(  \\)";
    3.60 +	    if (text[pos-2] == "\\") ins="(  \\\\)";
    3.61 +	    area.setRangeText(ins, pos, pos);
    3.62 +	    area.selectionStart = pos+2;
    3.63 +	    if (helpParenPreview++ < 1) {
    3.64 +		dispInfoMomentary("Preview formula by Meta-p\n"+
    3.65 +				  "Meta-p で数式プレビュー", e.target.parentNode);
    3.66 +	    }
    3.67 +	    e.preventDefault();
    3.68 +	}
    3.69 +    }
    3.70 +    function textInsert(area, pos, string) {
    3.71 +	
    3.72 +    }
    3.73 +    function helpMarkdownBrace(e) {
    3.74 +	if (!mathjax) return;
    3.75 +	var area = e.target, pos = area.selectionStart, text = area.value,
    3.76 +	    begin = "\\begin", end = "\\end";
    3.77 +	if (pos < end.length) return;
    3.78 +	if (text.substr(pos-end.length).startsWith(end)) {
    3.79 +	    let beg = text.lastIndexOf(begin, pos);
    3.80 +	    if (beg >= 0) {
    3.81 +		let env = text.substr(beg).search(/\\begin{(.*?)}/);
    3.82 +		if (env >= 0) {
    3.83 +		    let endenv = "{"+RegExp.$1+"}";
    3.84 +		    area.setRangeText(endenv, pos, pos);
    3.85 +		    area.selectionStart += endenv.length;
    3.86 +		    e.preventDefault();
    3.87 +		}
    3.88 +	    }
    3.89 +	}
    3.90 +    }
    3.91 +    function helpMarkdownPreview(area) {
    3.92 +	if (!mathjax) {
    3.93 +	    alert("no"+e.target)
    3.94 +	    dispInfoMomentary("This board has no MathJax mode.\n"+
    3.95 +			      "この掲示板は数式モードOFFです。",
    3.96 +			      e.target.parentNode);
    3.97 +	    return;
    3.98 +	}
    3.99 +	let text = area.value;
   3.100 +	let preview = document.createElement("div");
   3.101 +	let bp = document.createElement("p");
   3.102 +	let btn = document.createElement("button");
   3.103 +	btn.innerText = "Click or ESC to Dissmiss / クリックかESCで戻る";
   3.104 +	bp.classList.add("c");
   3.105 +	preview.classList.add("pjaxview");
   3.106 +	preview.classList.add("pjaxview2");
   3.107 +	let pre = document.createElement("p");
   3.108 +	bp.appendChild(btn);
   3.109 +	preview.appendChild(bp);
   3.110 +	preview.appendChild(pre);
   3.111 +	pre.innerText = text;
   3.112 +	document.body.appendChild(preview);
   3.113 +	function dismiss(t) {
   3.114 +	    history.back();
   3.115 +	    preview.remove();
   3.116 +	    area.focus();
   3.117 +	}
   3.118 +	preview.addEventListener("click", dismiss, false);
   3.119 +	preview.addEventListener("keydown", dismiss, false);
   3.120 +	MathJax.typesetPromise([pre]);
   3.121 +	pjaxHistoryPush(preview);
   3.122 +	btn.focus();
   3.123 +    }
   3.124      function helpMarkdown(e) {
   3.125  	switch (e.key) {
   3.126  	case "Backspace": helpMarkdownBS(e); break;
   3.127  	case "Enter":  helpMarkdownEnter(e); break;
   3.128 +	case "(":  helpMarkdownParen(e); break;
   3.129 +	case "p":  if (e.metaKey) helpMarkdownPreview(e.target); break;
   3.130 +	case "{":  helpMarkdownBrace(e); break;
   3.131  	}
   3.132      }
   3.133      /* Init event listeners */
   3.134 @@ -843,6 +925,20 @@
   3.135  	    }
   3.136  	}
   3.137      }
   3.138 +    function initMath() {
   3.139 +	mathjax = MathJax||document.getElementById("mathjax");
   3.140 +	if (!mathjax) return;
   3.141 +	let ta = document.querySelector("textarea");
   3.142 +	if (!ta) return;
   3.143 +	let btn = document.createElement("button");
   3.144 +	btn.innerHTML = "MathJax<br>Preview";
   3.145 +	btn.addEventListener('click', (e) => {
   3.146 +	    e.preventDefault();
   3.147 +	    ta.focus();
   3.148 +	    helpMarkdownPreview(ta);
   3.149 +	});
   3.150 +	ta.insertAdjacentElement('afterend', btn);
   3.151 +    }
   3.152      function init() {
   3.153  	isOlderJS = !("insertAdjacentElement" in document.body);
   3.154  	initGrpAction();
   3.155 @@ -850,6 +946,7 @@
   3.156  	initFileInput();
   3.157  	initTextarea();
   3.158  	initGrphome();
   3.159 +	initMath();
   3.160      }
   3.161      document.addEventListener('DOMContentLoaded', init, null);
   3.162  })();