-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
115 lines (115 loc) · 3.92 KB
/
index.ts
File metadata and controls
115 lines (115 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import type MarkdownIt from "markdown-it";
import type Token from "markdown-it/lib/token";
import type StateInline from "markdown-it/lib/rules_inline/state_inline";
import type StateBlock from "markdown-it/lib/rules_block/state_block";
function render(content:string,display:boolean,displaylines:boolean):string
{
const sign=display?'$$':'$';content=content.replaceAll('&','&').replaceAll('<','<').replaceAll('>','>');
if(displaylines) return `${sign}\\displaylines{${content}}${sign}`;
else return `${sign}${content}${sign}`;
}
function isValidDelim(state:StateInline,pos:number)
{
let max=state.posMax,can_open=true,can_close=true;
const prevChar=pos>0?state.src.charCodeAt(pos-1):-1,nextChar=pos+1<=max?state.src.charCodeAt(pos+1):-1;
if(prevChar===0x20||prevChar===0x09||(nextChar>=0x30&&nextChar<=0x39))can_close=false;
if(nextChar===0x20||nextChar===0x09)can_open=false;
return {can_open:can_open,can_close:can_close,};
}
function math_inline(state:StateInline,silent:boolean)
{
if(state.src[state.pos]!=="$") return false;
let res=isValidDelim(state,state.pos);
if(!res.can_open)
{
if(!silent) state.pending+="$";
state.pos+=1;
return true;
}
const start=state.pos+1;
let match=start;
while((match=state.src.indexOf("$",match))!==-1)
{
let pos=match-1;
while(state.src[pos]==="\\") pos--;
if((match-pos)%2==1) break;
match+=1;
}
if(match===-1)
{
if(!silent) state.pending+="$";
state.pos=start;
return true;
}
if (match-start===0)
{
if(!silent) state.pending+="$$";
state.pos=start+1;
return true;
}
res=isValidDelim(state,match);
if(!res.can_close)
{
if(!silent) state.pending+="$";
state.pos=start;
return true;
}
if (!silent)
{
const token=state.push("math_inline","math",0);
token.markup="$";
token.content=state.src.slice(start,match);
}
state.pos=match+1;
return true;
}
function math_block(state:StateBlock,start:number,end:number,silent:boolean)
{
let next:number,lastPos:number;
let found=false,pos=state.bMarks[start]+state.tShift[start],max=state.eMarks[start],lastLine="";
if(pos+2>max) return false;
if(state.src.slice(pos,pos+2)!=="$$") return false;
pos+=2;
let firstLine=state.src.slice(pos,max);
if(silent) return true;
if(firstLine.trim().slice(-2)==="$$")
{
firstLine=firstLine.trim().slice(0,-2);
found=true;
}
for(next=start;!found;)
{
next++;
if(next>=end) break;
pos=state.bMarks[next]+state.tShift[next];
max=state.eMarks[next];
if(pos<max&&state.tShift[next]<state.blkIndent) break;
if(state.src.slice(pos,max).trim().slice(-2)==="$$")
{
lastPos=state.src.slice(0,max).lastIndexOf("$$");
lastLine=state.src.slice(pos,lastPos);
found=true;
}
}
state.line=next+1;
const token=state.push("math_block","math",0);
token.block=true;
token.content=(firstLine&&firstLine.trim()?firstLine+"\n":"")+state.getLines(start+1,next,state.tShift[start],true)+(lastLine&&lastLine.trim()?lastLine:"");
token.map=[start, state.line];
token.markup="$$";
return true;
}
interface Option{
inline?:boolean,
block?:boolean
}
function math_plugin(md:MarkdownIt,options?:Option)
{
options=options||{};
let inline=options.inline||false,block=options.block||true;
md.inline.ruler.after("escape","math_inline",math_inline);
md.block.ruler.after("blockquote","math_block",math_block,{alt:["paragraph","reference","blockquote","list"],});
md.renderer.rules.math_inline=(tokens:Token[],idx:number)=>{return render(tokens[idx].content,false,inline)};
md.renderer.rules.math_block=(tokens:Token[],idx:number)=>{return render(tokens[idx].content,true,block)};
};
export=math_plugin;