@@ -13,6 +13,7 @@ import LoadingIcon from "../icons/three-dots.svg";
1313import React from "react" ;
1414import { useDebouncedCallback } from "use-debounce" ;
1515import { showImageModal } from "./ui-lib" ;
16+ import { nanoid } from "nanoid" ;
1617
1718export function Mermaid ( props : { code : string } ) {
1819 const ref = useRef < HTMLDivElement > ( null ) ;
@@ -62,6 +63,31 @@ export function Mermaid(props: { code: string }) {
6263
6364export function HTMLPreview ( props : { code : string } ) {
6465 const ref = useRef < HTMLDivElement > ( null ) ;
66+ const frameId = useRef < string > ( nanoid ( ) ) ;
67+ const [ height , setHeight ] = useState ( 600 ) ;
68+ /*
69+ * https://stackoverflow.com/questions/19739001/what-is-the-difference-between-srcdoc-and-src-datatext-html-in-an
70+ * 1. using srcdoc
71+ * 2. using src with dataurl:
72+ * easy to share
73+ * length limit (Data URIs cannot be larger than 32,768 characters.)
74+ */
75+
76+ useEffect ( ( ) => {
77+ window . addEventListener ( "message" , ( e ) => {
78+ const { id, height } = e . data ;
79+ if ( id == frameId . current ) {
80+ console . log ( "setHeight" , height ) ;
81+ if ( height < 600 ) {
82+ setHeight ( height + 40 ) ;
83+ }
84+ }
85+ } ) ;
86+ } , [ ] ) ;
87+
88+ const script = encodeURIComponent (
89+ `<script>new ResizeObserver((entries) => parent.postMessage({id: '${ frameId . current } ', height: entries[0].target.clientHeight}, '*')).observe(document.body)</script>` ,
90+ ) ;
6591
6692 return (
6793 < div
@@ -70,14 +96,16 @@ export function HTMLPreview(props: { code: string }) {
7096 cursor : "pointer" ,
7197 overflow : "auto" ,
7298 } }
73- ref = { ref }
74- onClick = { ( ) => console . log ( "click" ) }
99+ onClick = { ( e ) => e . stopPropapation ( ) }
75100 >
76101 < iframe
102+ id = { frameId }
103+ ref = { ref }
77104 frameBorder = { 0 }
78- sandbox = "allow-scripts"
79- style = { { width : "100%" , height : 400 } }
80- srcDoc = { props . code }
105+ sandbox = "allow-forms allow-modals allow-scripts"
106+ style = { { width : "100%" , height } }
107+ src = { `data:text/html,${ encodeURIComponent ( props . code ) } ${ script } ` }
108+ // srcDoc={props.code + script}
81109 > </ iframe >
82110 </ div >
83111 ) ;
@@ -108,10 +136,6 @@ export function PreCode(props: { children: any }) {
108136
109137 return (
110138 < >
111- { mermaidCode . length > 0 && (
112- < Mermaid code = { mermaidCode } key = { mermaidCode } />
113- ) }
114- { htmlCode . length > 0 && < HTMLPreview code = { htmlCode } key = { htmlCode } /> }
115139 < pre ref = { ref } >
116140 < span
117141 className = "copy-code-button"
@@ -124,6 +148,10 @@ export function PreCode(props: { children: any }) {
124148 > </ span >
125149 { props . children }
126150 </ pre >
151+ { mermaidCode . length > 0 && (
152+ < Mermaid code = { mermaidCode } key = { mermaidCode } />
153+ ) }
154+ { htmlCode . length > 0 && < HTMLPreview code = { htmlCode } key = { htmlCode } /> }
127155 </ >
128156 ) ;
129157}
0 commit comments