mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-27 02:20:28 +00:00
a1d9464011
* Add optional KaTeX support to the tiddlywiki/markdown plugin. Uses the remarkable-katex plugin 1.1.8 by Brad Howes to enable KaTeX support if the tiddlywiki/katex plugin is installed. Fixes #2984. TESTED: Created a test wiki with: ``` $ node tiddlywiki.js test --init markdowndemo $ node tiddlywiki.js test --listen ``` * Verified markdown support works without the tiddlywiki/katex plugin enabled. * Verified markdown support works with the tiddlywiki/katex plugin enabled. * Verified KaTeX (both inline and blocks) work as expected when the tiddlywiki/katex plugin is enabled. * Mention remarkable-katex plugin usage in the readme Tiddler. * Include the remarkable-katex license as a tiddler. * Include the Remarkable license. * Include unminified original source of remarkable-katex 1.1.8.
20 lines
2.7 KiB
JavaScript
20 lines
2.7 KiB
JavaScript
"use strict";const rkatex=(md,options)=>{const backslash='\\';const dollar='$';const opts=options||{};const delimiter=opts.delimiter||dollar;if(delimiter.length!==1){throw new Error('invalid delimiter');}
|
|
const katex=require("katex");const renderKatex=(source,displayMode)=>katex.renderToString(source,{displayMode:displayMode,throwOnError:false});const parseBlockKatex=(state,startLine,endLine)=>{let haveEndMarker=false;let pos=state.bMarks[startLine]+state.tShift[startLine];let max=state.eMarks[startLine];if(pos+1>max){return false;}
|
|
const marker=state.src.charAt(pos);if(marker!==delimiter){return false;}
|
|
let mem=pos;pos=state.skipChars(pos,marker);let len=pos-mem;if(len!==2){return false;}
|
|
let nextLine=startLine;for(;;){++nextLine;if(nextLine>=endLine){break;}
|
|
pos=mem=state.bMarks[nextLine]+state.tShift[nextLine];max=state.eMarks[nextLine];if(pos<max&&state.tShift[nextLine]<state.blkIndent){break;}
|
|
if(state.src.charAt(pos)!==delimiter){continue;}
|
|
if(state.tShift[nextLine]-state.blkIndent>=4){continue;}
|
|
pos=state.skipChars(pos,marker);if(pos-mem<len){continue;}
|
|
pos=state.skipSpaces(pos);if(pos<max){continue;}
|
|
haveEndMarker=true;break;}
|
|
len=state.tShift[startLine];state.line=nextLine+(haveEndMarker?1:0);const content=state.getLines(startLine+1,nextLine,len,true).replace(/[ \n]+/g,' ').trim();state.tokens.push({type:'katex',params:null,content:content,lines:[startLine,state.line],level:state.level,block:true});return true;};const parseInlineKatex=(state,silent)=>{const start=state.pos;const max=state.posMax;let pos=start;if(state.src.charAt(pos)!==delimiter){return false;}
|
|
++pos;while(pos<max&&state.src.charAt(pos)===delimiter){++pos;}
|
|
const marker=state.src.slice(start,pos);if(marker.length>2){return false;}
|
|
const spanStart=pos;let escapedDepth=0;while(pos<max){const char=state.src.charAt(pos);if(char==='{'&&(pos==0||state.src.charAt(pos-1)!=backslash)){escapedDepth+=1;}else if(char==='}'&&(pos==0||state.src.charAt(pos-1)!=backslash)){escapedDepth-=1;if(escapedDepth<0){return false;}}else if(char===delimiter&&escapedDepth===0){const matchStart=pos;let matchEnd=pos+1;while(matchEnd<max&&state.src.charAt(matchEnd)===delimiter){++matchEnd;}
|
|
if(matchEnd-matchStart===marker.length){if(!silent){const content=state.src.slice(spanStart,matchStart).replace(/[ \n]+/g,' ').trim();state.push({type:'katex',content:content,block:marker.length>1,level:state.level});}
|
|
state.pos=matchEnd;return true;}}
|
|
pos+=1;}
|
|
if(!silent){state.pending+=marker;}
|
|
state.pos+=marker.length;return true;};md.inline.ruler.push('katex',parseInlineKatex,options);md.block.ruler.push('katex',parseBlockKatex,options);md.renderer.rules.katex=(tokens,idx)=>renderKatex(tokens[idx].content,tokens[idx].block);md.renderer.rules.katex.delimiter=delimiter;};module.exports=rkatex; |