@@ -27,9 +27,12 @@ import _linkifyString from 'linkifyjs/string';
27
27
import classNames from 'classnames' ;
28
28
import EMOJIBASE_REGEX from 'emojibase-regex' ;
29
29
import url from 'url' ;
30
+ import katex from 'katex' ;
31
+ import { AllHtmlEntities } from 'html-entities' ;
32
+ import SettingsStore from './settings/SettingsStore' ;
33
+ import cheerio from 'cheerio' ;
30
34
31
35
import { MatrixClientPeg } from './MatrixClientPeg' ;
32
- import SettingsStore from './settings/SettingsStore' ;
33
36
import { tryTransformPermalinkToLocalHref } from "./utils/permalinks/Permalinks" ;
34
37
import { SHORTCODE_TO_EMOJI , getEmojiFromUnicode } from "./emoji" ;
35
38
import ReplyThread from "./components/views/elements/ReplyThread" ;
@@ -240,7 +243,8 @@ const sanitizeHtmlParams: IExtendedSanitizeOptions = {
240
243
allowedAttributes : {
241
244
// custom ones first:
242
245
font : [ 'color' , 'data-mx-bg-color' , 'data-mx-color' , 'style' ] , // custom to matrix
243
- span : [ 'data-mx-bg-color' , 'data-mx-color' , 'data-mx-spoiler' , 'style' ] , // custom to matrix
246
+ span : [ 'data-mx-maths' , 'data-mx-bg-color' , 'data-mx-color' , 'data-mx-spoiler' , 'style' ] , // custom to matrix
247
+ div : [ 'data-mx-maths' ] ,
244
248
a : [ 'href' , 'name' , 'target' , 'rel' ] , // remote target: custom to matrix
245
249
img : [ 'src' , 'width' , 'height' , 'alt' , 'title' ] ,
246
250
ol : [ 'start' ] ,
@@ -414,6 +418,21 @@ export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts
414
418
if ( isHtmlMessage ) {
415
419
isDisplayedWithHtml = true ;
416
420
safeBody = sanitizeHtml ( formattedBody , sanitizeParams ) ;
421
+
422
+ if ( SettingsStore . getValue ( "feature_latex_maths" ) ) {
423
+ const phtml = cheerio . load ( safeBody ,
424
+ { _useHtmlParser2 : true , decodeEntities : false } )
425
+ phtml ( 'div, span[data-mx-maths!=""]' ) . replaceWith ( function ( i , e ) {
426
+ return katex . renderToString (
427
+ AllHtmlEntities . decode ( phtml ( e ) . attr ( 'data-mx-maths' ) ) ,
428
+ {
429
+ throwOnError : false ,
430
+ displayMode : e . name == 'div' ,
431
+ output : "htmlAndMathml" ,
432
+ } ) ;
433
+ } ) ;
434
+ safeBody = phtml . html ( ) ;
435
+ }
417
436
}
418
437
} finally {
419
438
delete sanitizeParams . textFilter ;
@@ -515,7 +534,6 @@ export function checkBlockNode(node: Node) {
515
534
case "H6" :
516
535
case "PRE" :
517
536
case "BLOCKQUOTE" :
518
- case "DIV" :
519
537
case "P" :
520
538
case "UL" :
521
539
case "OL" :
@@ -528,6 +546,9 @@ export function checkBlockNode(node: Node) {
528
546
case "TH" :
529
547
case "TD" :
530
548
return true ;
549
+ case "DIV" :
550
+ // don't treat math nodes as block nodes for deserializing
551
+ return ! ( node as HTMLElement ) . hasAttribute ( "data-mx-maths" ) ;
531
552
default :
532
553
return false ;
533
554
}
0 commit comments