1
1
import { isDarkTheme } from '../utils.js' ;
2
2
import { makeCodeCopyButton } from './codecopy.js' ;
3
+ import { displayError } from './common.js' ;
3
4
4
5
const { mermaidMaxSourceCharacters} = window . config ;
5
6
6
- const iframeCss = `
7
- :root {color-scheme: normal}
8
- body {margin: 0; padding: 0; overflow: hidden}
9
- #mermaid {display: block; margin: 0 auto}
10
- ` ;
11
-
12
- function displayError ( el , err ) {
13
- el . closest ( 'pre' ) . classList . remove ( 'is-loading' ) ;
14
- const errorNode = document . createElement ( 'div' ) ;
15
- errorNode . setAttribute ( 'class' , 'ui message error markup-block-error gt-mono' ) ;
16
- errorNode . textContent = err . str || err . message || String ( err ) ;
17
- el . closest ( 'pre' ) . before ( errorNode ) ;
18
- }
7
+ const iframeCss = `:root {color-scheme: normal}
8
+ body {margin: 0; padding: 0; overflow: hidden}
9
+ #mermaid {display: block; margin: 0 auto}` ;
19
10
20
11
export async function renderMermaid ( ) {
21
12
const els = document . querySelectorAll ( '.markup code.language-mermaid' ) ;
@@ -30,45 +21,52 @@ export async function renderMermaid() {
30
21
} ) ;
31
22
32
23
for ( const el of els ) {
33
- const source = el . textContent ;
24
+ const pre = el . closest ( 'pre' ) ;
25
+ if ( pre . hasAttribute ( 'data-render-done' ) ) continue ;
34
26
27
+ const source = el . textContent ;
35
28
if ( mermaidMaxSourceCharacters >= 0 && source . length > mermaidMaxSourceCharacters ) {
36
- displayError ( el , new Error ( `Mermaid source of ${ source . length } characters exceeds the maximum allowed length of ${ mermaidMaxSourceCharacters } .` ) ) ;
29
+ displayError ( pre , new Error ( `Mermaid source of ${ source . length } characters exceeds the maximum allowed length of ${ mermaidMaxSourceCharacters } .` ) ) ;
37
30
continue ;
38
31
}
39
32
40
33
try {
41
34
await mermaid . parse ( source ) ;
42
35
} catch ( err ) {
43
- displayError ( el , err ) ;
44
- el . closest ( 'pre' ) . classList . remove ( 'is-loading' ) ;
36
+ displayError ( pre , err ) ;
45
37
continue ;
46
38
}
47
39
48
40
try {
49
41
// can't use bindFunctions here because we can't cross the iframe boundary. This
50
42
// means js-based interactions won't work but they aren't intended to work either
51
43
const { svg} = await mermaid . render ( 'mermaid' , source ) ;
52
- const heightStr = ( svg . match ( / v i e w B o x = " ( .+ ?) " / ) || [ '' , '' ] ) [ 1 ] . split ( / \s + / ) [ 3 ] ;
53
- if ( ! heightStr ) return displayError ( el , new Error ( 'Could not determine chart height' ) ) ;
54
44
55
45
const iframe = document . createElement ( 'iframe' ) ;
56
- iframe . classList . add ( 'markup-render' ) ;
57
- iframe . sandbox = 'allow-scripts' ;
58
- iframe . style . height = `${ Math . ceil ( parseFloat ( heightStr ) ) } px` ;
46
+ iframe . classList . add ( 'markup-render' , 'gt-invisible' ) ;
59
47
iframe . srcdoc = `<html><head><style>${ iframeCss } </style></head><body>${ svg } </body></html>` ;
60
48
61
49
const mermaidBlock = document . createElement ( 'div' ) ;
62
- mermaidBlock . classList . add ( 'mermaid-block' ) ;
50
+ mermaidBlock . classList . add ( 'mermaid-block' , 'is-loading' , 'gt-hidden' ) ;
63
51
mermaidBlock . append ( iframe ) ;
64
52
65
53
const btn = makeCodeCopyButton ( ) ;
66
54
btn . setAttribute ( 'data-clipboard-text' , source ) ;
67
-
68
55
mermaidBlock . append ( btn ) ;
69
- el . closest ( 'pre' ) . replaceWith ( mermaidBlock ) ;
56
+
57
+ iframe . addEventListener ( 'load' , ( ) => {
58
+ pre . replaceWith ( mermaidBlock ) ;
59
+ mermaidBlock . classList . remove ( 'gt-hidden' ) ;
60
+ iframe . style . height = `${ iframe . contentWindow . document . body . clientHeight } px` ;
61
+ setTimeout ( ( ) => { // avoid flash of iframe background
62
+ mermaidBlock . classList . remove ( 'is-loading' ) ;
63
+ iframe . classList . remove ( 'gt-invisible' ) ;
64
+ } , 0 ) ;
65
+ } ) ;
66
+
67
+ document . body . append ( mermaidBlock ) ;
70
68
} catch ( err ) {
71
- displayError ( el , err ) ;
69
+ displayError ( pre , err ) ;
72
70
}
73
71
}
74
72
}
0 commit comments