@@ -41,23 +41,101 @@ if(window.jekyllEnv !== 'spec-pdf') {
41
41
) ;
42
42
}
43
43
44
- // no language auto-detect so that EBNF isn't detected as scala
45
- hljs . configure ( {
46
- languages : [ ]
44
+ // See https://github.com/highlightjs/highlight.js/issues/2889 for additional context.
45
+ function renderMath ( { el, result, text} ) {
46
+
47
+ const re = RegExp ( '´' , 'g' ) ;
48
+
49
+ const spans = [ ] ;
50
+
51
+ // get the spans of all math elements
52
+ while ( match = re . exec ( text ) ) {
53
+ const start = match . index ;
54
+ match = re . exec ( text ) ;
55
+ if ( match == null ) {
56
+ break ;
57
+ } else {
58
+ const end = match . index + 1 ;
59
+ spans . push ( { start, end} ) ;
60
+ }
61
+ }
62
+
63
+ // render spans using katex
64
+ for ( const span of spans ) {
65
+ const { start, end} = span ;
66
+ const str = text . substring ( start + 1 , end - 1 ) ;
67
+ const parent = new DocumentFragment ( ) ;
68
+ katex . render ( str , parent , { throwOnError : false } ) ;
69
+ const children = parent . children ;
70
+ // TODO: Double check mutiple elements aren't possible
71
+ if ( children . length == 1 ) {
72
+ span . span = children [ 0 ] ;
73
+ }
74
+ }
75
+
76
+ // Here we start the merging between the katex output and highlight output.
77
+ if ( spans . length != 0 ) {
78
+
79
+ // This is essentially our iterator
80
+ var offset = 0 ;
81
+ var span = spans . shift ( ) ;
82
+ var child = el . firstChild ;
83
+
84
+ // highlight only supports one level of nesting.
85
+ while ( child ) {
86
+ if ( child instanceof Text ) {
87
+ const str = child . wholeText ;
88
+ const start = offset ;
89
+ const end = start + str . length ;
90
+
91
+ if ( span . start >= start && span . end <= end ) {
92
+ const beforeText = str . substring ( 0 , span . start - start ) ;
93
+ if ( beforeText ) {
94
+ el . insertBefore ( new Text ( beforeText ) , child ) ;
95
+ }
96
+
97
+ const afterText = str . substring ( span . end - start ) ;
98
+ child = el . replaceChild ( span . span , child ) ;
99
+
100
+ if ( afterText ) {
101
+ const afterChild = new Text ( afterText ) ;
102
+ if ( child . nextSibling ) {
103
+ el . insertBefore ( afterChild , child . nextSibling ) ;
104
+ } else {
105
+ el . appendChild ( afterChild ) ;
106
+ }
107
+ }
108
+
109
+ offset = span . end ;
110
+
111
+ } else {
112
+ offset = end ;
113
+ }
114
+ } else if ( child . tagName ) {
115
+ const str = child . innerHTML ;
116
+ offset += str . length ;
117
+ }
118
+
119
+ child = child . nextSibling ;
120
+ }
121
+ }
122
+ }
123
+
124
+ hljs . addPlugin ( {
125
+ 'after:highlightElement' : renderMath
47
126
} ) ;
48
127
49
128
// KaTeX configuration
50
129
document . addEventListener ( "DOMContentLoaded" , function ( ) {
51
130
renderMathInElement ( document . body , {
52
- delimiters : [
53
- { left : "´" , right : "´" , display : false } , // "display: false" -> inline
54
- { left : "$$" , right : "$$" , display : true }
55
- ] ,
56
- ignoredTags : [ 'script' , 'noscript' , 'style' , 'textarea' ] ,
131
+ delimiters : [
132
+ { left : "´" , right : "´" , display : false } , // "display: false" -> inline
133
+ { left : "$$" , right : "$$" , display : true }
134
+ ] ,
135
+ // We ignore 'code' here, because highlight will deal with it.
136
+ ignoredTags : [ 'script' , 'noscript' , 'style' , 'code' ] ,
57
137
} ) ;
58
- // syntax highlighting after KaTeX is loaded,
59
- // so that math can be used in code blocks
60
- hljs . initHighlighting ( ) ;
138
+ hljs . highlightAll ( ) ;
61
139
$ ( "pre nobr" ) . addClass ( "fixws" ) ;
62
140
// point when all necessary js is done, so PDF to be rendered
63
141
window . status = "loaded" ;
0 commit comments