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
@@ -9,14 +10,6 @@ const iframeCss = `
9
10
#mermaid {display: block; margin: 0 auto}
10
11
` ;
11
12
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
- }
19
-
20
13
export async function renderMermaid ( ) {
21
14
const els = document . querySelectorAll ( '.markup code.language-mermaid' ) ;
22
15
if ( ! els . length ) return ;
@@ -30,33 +23,35 @@ export async function renderMermaid() {
30
23
} ) ;
31
24
32
25
for ( const el of els ) {
33
- const source = el . textContent ;
26
+ const pre = el . closest ( 'pre' ) ;
27
+ if ( pre . hasAttribute ( 'data-done' ) ) continue ;
34
28
29
+ const source = el . textContent ;
35
30
if ( mermaidMaxSourceCharacters >= 0 && source . length > mermaidMaxSourceCharacters ) {
36
- displayError ( el , new Error ( `Mermaid source of ${ source . length } characters exceeds the maximum allowed length of ${ mermaidMaxSourceCharacters } .` ) ) ;
31
+ displayError ( pre , new Error ( `Mermaid source of ${ source . length } characters exceeds the maximum allowed length of ${ mermaidMaxSourceCharacters } .` ) ) ;
37
32
continue ;
38
33
}
39
34
40
35
try {
41
36
await mermaid . parse ( source ) ;
42
37
} catch ( err ) {
43
- displayError ( el , err ) ;
44
- el . closest ( 'pre' ) . classList . remove ( 'is-loading' ) ;
38
+ displayError ( pre , err ) ;
45
39
continue ;
46
40
}
47
41
48
42
try {
49
43
// can't use bindFunctions here because we can't cross the iframe boundary. This
50
44
// means js-based interactions won't work but they aren't intended to work either
51
45
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
46
55
47
const iframe = document . createElement ( 'iframe' ) ;
56
48
iframe . classList . add ( 'markup-render' ) ;
57
- iframe . sandbox = 'allow-scripts' ;
58
- iframe . style . height = `${ Math . ceil ( parseFloat ( heightStr ) ) } px` ;
49
+ iframe . sandbox = 'allow-scripts allow-same-origin' ;
59
50
iframe . srcdoc = `<html><head><style>${ iframeCss } </style></head><body>${ svg } </body></html>` ;
51
+ iframe . addEventListener ( 'load' , ( e ) => {
52
+ const height = e . target . contentWindow . document . body . clientHeight ;
53
+ iframe . style . height = `${ height } px` ;
54
+ } ) ;
60
55
61
56
const mermaidBlock = document . createElement ( 'div' ) ;
62
57
mermaidBlock . classList . add ( 'mermaid-block' ) ;
@@ -66,9 +61,9 @@ export async function renderMermaid() {
66
61
btn . setAttribute ( 'data-clipboard-text' , source ) ;
67
62
68
63
mermaidBlock . append ( btn ) ;
69
- el . closest ( ' pre' ) . replaceWith ( mermaidBlock ) ;
64
+ pre . replaceWith ( mermaidBlock ) ;
70
65
} catch ( err ) {
71
- displayError ( el , err ) ;
66
+ displayError ( pre , err ) ;
72
67
}
73
68
}
74
69
}
0 commit comments