2024-08-08 22:01:38 +00:00
import katex from 'katex' ;
2024-08-13 10:12:35 +00:00
const inlineRule =
/^(\${1,2})(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n\$]))\1(?=[\s?!\.,:?!。,:]|$)/ ;
2024-08-08 22:01:38 +00:00
const inlineRuleNonStandard = /^(\${1,2})(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n\$]))\1/ ; // Non-standard, even if there are no spaces before and after $ or $$, try to parse
const blockRule = /^(\${1,2})\n((?:\\[^]|[^\\])+?)\n\1(?:\n|$)/ ;
2024-08-13 10:12:35 +00:00
export default function ( options = { } ) {
return {
extensions : [
inlineKatex ( options , createRenderer ( options , false ) ) ,
blockKatex ( options , createRenderer ( options , true ) )
]
} ;
2024-08-08 22:01:38 +00:00
}
function createRenderer ( options , newlineAfter ) {
2024-08-13 10:12:35 +00:00
return ( token ) = >
katex . renderToString ( token . text , { . . . options , displayMode : token.displayMode } ) +
( newlineAfter ? '\n' : '' ) ;
2024-08-08 22:01:38 +00:00
}
function inlineKatex ( options , renderer ) {
2024-08-13 10:12:35 +00:00
const nonStandard = options && options . nonStandard ;
const ruleReg = nonStandard ? inlineRuleNonStandard : inlineRule ;
return {
name : 'inlineKatex' ,
level : 'inline' ,
start ( src ) {
let index ;
let indexSrc = src ;
2024-08-08 22:01:38 +00:00
2024-08-13 10:12:35 +00:00
while ( indexSrc ) {
index = indexSrc . indexOf ( '$' ) ;
if ( index === - 1 ) {
return ;
}
const f = nonStandard ? index > - 1 : index === 0 || indexSrc . charAt ( index - 1 ) === ' ' ;
if ( f ) {
const possibleKatex = indexSrc . substring ( index ) ;
2024-08-08 22:01:38 +00:00
2024-08-13 10:12:35 +00:00
if ( possibleKatex . match ( ruleReg ) ) {
return index ;
}
}
2024-08-08 22:01:38 +00:00
2024-08-13 10:12:35 +00:00
indexSrc = indexSrc . substring ( index + 1 ) . replace ( /^\$+/ , '' ) ;
}
} ,
tokenizer ( src , tokens ) {
const match = src . match ( ruleReg ) ;
if ( match ) {
return {
type : 'inlineKatex' ,
raw : match [ 0 ] ,
text : match [ 2 ] . trim ( ) ,
displayMode : match [ 1 ] . length === 2
} ;
}
} ,
renderer
} ;
2024-08-08 22:01:38 +00:00
}
function blockKatex ( options , renderer ) {
2024-08-13 10:12:35 +00:00
return {
name : 'blockKatex' ,
level : 'block' ,
tokenizer ( src , tokens ) {
const match = src . match ( blockRule ) ;
if ( match ) {
return {
type : 'blockKatex' ,
raw : match [ 0 ] ,
text : match [ 2 ] . trim ( ) ,
displayMode : match [ 1 ] . length === 2
} ;
}
} ,
renderer
} ;
}