matthoffner commited on
Commit
1fa631b
1 Parent(s): 3482873

Update components/Markdown/CodeBlock.tsx

Browse files
Files changed (1) hide show
  1. components/Markdown/CodeBlock.tsx +34 -10
components/Markdown/CodeBlock.tsx CHANGED
@@ -1,5 +1,5 @@
1
  import { IconCheck, IconClipboard, IconDownload, IconCaretRight } from '@tabler/icons-react';
2
- import { FC, memo, useState } from 'react';
3
  import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
4
  import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
5
 
@@ -15,15 +15,35 @@ interface Props {
15
  value: string;
16
  }
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  export const CodeBlock: FC<Props> = memo(({ language, value }) => {
19
  const { t } = useTranslation('markdown');
20
  const [isCopied, setIsCopied] = useState<Boolean>(false);
21
  const [isRunning, setIsRunning] = useState<Boolean>(false);
 
22
 
23
  const toggleRunCode = () => {
24
  setIsRunning(!isRunning);
25
  };
26
 
 
 
 
 
 
 
27
  const copyToClipboard = () => {
28
  if (!navigator.clipboard || !navigator.clipboard.writeText) {
29
  return;
@@ -77,13 +97,15 @@ export const CodeBlock: FC<Props> = memo(({ language, value }) => {
77
  {isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
78
  {isCopied ? t('Copied!') : t('Copy code')}
79
  </button>
80
- <button
81
- className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-white"
82
- onClick={toggleRunCode}
83
- >
84
- <IconCaretRight size={18} />
85
- {isRunning ? t('Stop') : t('Run code')}
86
- </button>
 
 
87
  <button
88
  className="flex items-center rounded bg-none p-1 text-xs text-white"
89
  onClick={downloadAsFile}
@@ -102,10 +124,12 @@ export const CodeBlock: FC<Props> = memo(({ language, value }) => {
102
  </SyntaxHighlighter>
103
  {isRunning && (
104
  <iframe
105
- srcDoc={value}
106
  title="live code preview"
107
  className="w-full h-64 mt-4 border-2 border-gray-300"
108
- />
 
 
109
  )}
110
  </div>
111
  );
 
1
  import { IconCheck, IconClipboard, IconDownload, IconCaretRight } from '@tabler/icons-react';
2
+ import { FC, memo, useRef, useState } from 'react';
3
  import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
4
  import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
5
 
 
15
  value: string;
16
  }
17
 
18
+ const IframeContent: FC = () => {
19
+ useEffect(() => {
20
+ window.addEventListener("message", ({ data: { code, language } }) => {
21
+ if (language === 'html') {
22
+ document.body.innerHTML = code;
23
+ } else if (language === 'javascript') {
24
+ eval(code);
25
+ }
26
+ });
27
+ }, []);
28
+ return null;
29
+ };
30
+
31
  export const CodeBlock: FC<Props> = memo(({ language, value }) => {
32
  const { t } = useTranslation('markdown');
33
  const [isCopied, setIsCopied] = useState<Boolean>(false);
34
  const [isRunning, setIsRunning] = useState<Boolean>(false);
35
+ const iframeRef = useRef<any>(null);
36
 
37
  const toggleRunCode = () => {
38
  setIsRunning(!isRunning);
39
  };
40
 
41
+ useEffect(() => {
42
+ if (isRunning && iframeRef.current) {
43
+ iframeRef.current.contentWindow?.postMessage({ code: value, language }, "*");
44
+ }
45
+ }, [isRunning, value, language]);
46
+
47
  const copyToClipboard = () => {
48
  if (!navigator.clipboard || !navigator.clipboard.writeText) {
49
  return;
 
97
  {isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
98
  {isCopied ? t('Copied!') : t('Copy code')}
99
  </button>
100
+ {(language === 'html' || language === 'javascript') && (
101
+ <button
102
+ className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-white"
103
+ onClick={toggleRunCode}
104
+ >
105
+ <IconCaretRight size={18} />
106
+ {isRunning ? t('Stop') : t('Run code')}
107
+ </button>
108
+ )}
109
  <button
110
  className="flex items-center rounded bg-none p-1 text-xs text-white"
111
  onClick={downloadAsFile}
 
124
  </SyntaxHighlighter>
125
  {isRunning && (
126
  <iframe
127
+ ref={iframeRef}
128
  title="live code preview"
129
  className="w-full h-64 mt-4 border-2 border-gray-300"
130
+ >
131
+ <IframeContent />
132
+ </iframe>
133
  )}
134
  </div>
135
  );