This is an automated email from the ASF dual-hosted git repository.
robin0716 pushed a commit to branch feat/embed
in repository https://gitbox.apache.org/repos/asf/incubator-answer-plugins.git
The following commit(s) were added to refs/heads/feat/embed by this push:
new 698f8fa refactor(embed-basic): Implement the embed plugin with JSX
and add loading status
698f8fa is described below
commit 698f8facf5d4103f767f43fe7bfbe5e41b16b3c8
Author: robin <[email protected]>
AuthorDate: Fri Jun 7 15:25:19 2024 +0800
refactor(embed-basic): Implement the embed plugin with JSX and add loading
status
---
embed-basic/components/CodePenEmbed/index.tsx | 37 ++++++++++++
embed-basic/components/DropboxEmbed/index.tsx | 36 ++++++++++++
embed-basic/components/EmbedContainer/index.tsx | 58 +++++++++++++++++++
embed-basic/components/ExcalidrawEmbed/index.tsx | 36 ++++++++++++
embed-basic/components/FigmaEmbed/index.tsx | 35 ++++++++++++
embed-basic/components/GithubGistEmbed/index.tsx | 33 +++++++++++
embed-basic/components/JSFiddleEmbed/index.tsx | 35 ++++++++++++
embed-basic/components/LoomEmbed/index.tsx | 36 ++++++++++++
embed-basic/components/TwitterEmbed/index.tsx | 71 ++++++++++++++++++++++++
embed-basic/components/YouTubeEmbed/index.tsx | 37 ++++++++++++
embed-basic/components/index.ts | 40 +++++++++++++
embed-basic/{hooks.ts => hooks.tsx} | 70 ++++++++++++-----------
12 files changed, 493 insertions(+), 31 deletions(-)
diff --git a/embed-basic/components/CodePenEmbed/index.tsx
b/embed-basic/components/CodePenEmbed/index.tsx
new file mode 100644
index 0000000..2632d5d
--- /dev/null
+++ b/embed-basic/components/CodePenEmbed/index.tsx
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import EmbedContainer from '../EmbedContainer';
+
+const CodePenEmbed = ({ penId }) => {
+ return (
+ <EmbedContainer>
+ <iframe
+ width="100%"
+ height="100%"
+
src={`https://codepen.io/${penId}/embed/preview/${penId}?height=265&theme-id=0&default-tab=result`}
+ title="CodePen Embed"
+ allowTransparency
+ allowFullScreen
+ />
+ </EmbedContainer>
+ );
+};
+
+export default CodePenEmbed;
diff --git a/embed-basic/components/DropboxEmbed/index.tsx
b/embed-basic/components/DropboxEmbed/index.tsx
new file mode 100644
index 0000000..9c678e3
--- /dev/null
+++ b/embed-basic/components/DropboxEmbed/index.tsx
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import EmbedContainer from '../EmbedContainer';
+
+const DropboxEmbed = ({ dropboxId }) => {
+ return (
+ <EmbedContainer height={380}>
+ <iframe
+ title="Dropbox"
+ width="100%"
+ height="100%"
+ src={`https://www.dropbox.com/s/${dropboxId}?raw=1`}
+ frameBorder="0"
+ />
+ </EmbedContainer>
+ );
+};
+
+export default DropboxEmbed;
diff --git a/embed-basic/components/EmbedContainer/index.tsx
b/embed-basic/components/EmbedContainer/index.tsx
new file mode 100644
index 0000000..224584f
--- /dev/null
+++ b/embed-basic/components/EmbedContainer/index.tsx
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { FC, cloneElement, useRef } from 'react';
+import Spinner from 'react-bootstrap/Spinner';
+
+interface EmbedContainerProps {
+ children: React.ReactElement;
+ height?: number | string;
+}
+const EmbedContainer: FC<EmbedContainerProps> = ({
+ children,
+ height = 350,
+}) => {
+ const loadingRef = useRef<HTMLSpanElement>(null);
+
+ const handleLoad = () => {
+ if (loadingRef.current) {
+ const parentElement = loadingRef.current.parentElement;
+ if (parentElement) {
+ parentElement.style.height = height + 'px';
+ }
+ loadingRef.current.remove();
+ }
+ };
+ let Component = children;
+ if (children.type === 'iframe') {
+ Component = cloneElement(children, { onLoad: handleLoad });
+ }
+ return (
+ <>
+ {Component}
+ <span
+ ref={loadingRef}
+ className="loading position-absolute top-0 left-0 w-100 h-100 z-1
bg-white d-flex justify-content-center align-items-center">
+ <Spinner animation="border" variant="secondary" />
+ </span>
+ </>
+ );
+};
+
+export default EmbedContainer;
diff --git a/embed-basic/components/ExcalidrawEmbed/index.tsx
b/embed-basic/components/ExcalidrawEmbed/index.tsx
new file mode 100644
index 0000000..1a659bf
--- /dev/null
+++ b/embed-basic/components/ExcalidrawEmbed/index.tsx
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import EmbedContainer from '../EmbedContainer';
+
+const ExcalidrawEmbed = ({ excalidrawId }) => {
+ return (
+ <EmbedContainer height={380}>
+ <iframe
+ title="Excalidraw"
+ width="100%"
+ height="100%"
+ src={`https://excalidraw.com/${excalidrawId}/embed`}
+ frameBorder="0"
+ />
+ </EmbedContainer>
+ );
+};
+
+export default ExcalidrawEmbed;
diff --git a/embed-basic/components/FigmaEmbed/index.tsx
b/embed-basic/components/FigmaEmbed/index.tsx
new file mode 100644
index 0000000..14cb644
--- /dev/null
+++ b/embed-basic/components/FigmaEmbed/index.tsx
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import EmbedContainer from '../EmbedContainer';
+
+const FigmaEmbed = ({ url }) => {
+ return (
+ <EmbedContainer height={450}>
+ <iframe
+ style={{ border: 'none' }}
+ width="100%"
+ height="100%"
+ src={`https://www.figma.com/embed?embed_host=share&url=${url}`}
+ allowFullScreen></iframe>
+ </EmbedContainer>
+ );
+};
+
+export default FigmaEmbed;
diff --git a/embed-basic/components/GithubGistEmbed/index.tsx
b/embed-basic/components/GithubGistEmbed/index.tsx
new file mode 100644
index 0000000..cadb158
--- /dev/null
+++ b/embed-basic/components/GithubGistEmbed/index.tsx
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import EmbedContainer from '../EmbedContainer';
+
+const GithubGistEmbed = ({ scriptUrl }) => {
+ return (
+ <EmbedContainer>
+ <iframe
+ className="w-100 h-100"
+ src={`data:text/html;charset=utf-8,<head><base target='_blank'
/></head><body style='margin:0;'><script src='${scriptUrl}'></script></body>`}
+ />
+ </EmbedContainer>
+ );
+};
+
+export default GithubGistEmbed;
diff --git a/embed-basic/components/JSFiddleEmbed/index.tsx
b/embed-basic/components/JSFiddleEmbed/index.tsx
new file mode 100644
index 0000000..3265776
--- /dev/null
+++ b/embed-basic/components/JSFiddleEmbed/index.tsx
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import EmbedContainer from '../EmbedContainer';
+
+const JSFiddleEmbed = ({ fiddleId }) => {
+ return (
+ <EmbedContainer>
+ <iframe
+ width="100%"
+ height="100%"
+ src={`https://jsfiddle.net/${fiddleId}/embedded/`}
+ allowFullScreen
+ allowTransparency></iframe>
+ </EmbedContainer>
+ );
+};
+
+export default JSFiddleEmbed;
diff --git a/embed-basic/components/LoomEmbed/index.tsx
b/embed-basic/components/LoomEmbed/index.tsx
new file mode 100644
index 0000000..00b48df
--- /dev/null
+++ b/embed-basic/components/LoomEmbed/index.tsx
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import EmbedContainer from '../EmbedContainer';
+
+const LoomEmbed = ({ loomId }) => {
+ return (
+ <EmbedContainer height={380}>
+ <iframe
+ title="Loom"
+ width="100%"
+ height="100%"
+ src={`https://www.loom.com/embed/${loomId}`}
+ frameBorder="0"
+ />
+ </EmbedContainer>
+ );
+};
+
+export default LoomEmbed;
diff --git a/embed-basic/components/TwitterEmbed/index.tsx
b/embed-basic/components/TwitterEmbed/index.tsx
new file mode 100644
index 0000000..99f865e
--- /dev/null
+++ b/embed-basic/components/TwitterEmbed/index.tsx
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { useRef, useEffect } from 'react';
+import Spinner from 'react-bootstrap/Spinner';
+
+declare global {
+ interface Window {
+ twttr: any;
+ }
+}
+const TwitterEmbed = ({ url, title = '' }) => {
+ const loadingRef = useRef<HTMLDivElement>(null);
+ useEffect(() => {
+ if (!loadingRef.current) {
+ return;
+ }
+ const script = document.createElement('script');
+ script.src = 'https://platform.twitter.com/widgets.js';
+ script.async = true;
+ loadingRef.current.before(script);
+
+ script.onload = () => {
+ if (!window?.twttr) {
+ return;
+ }
+ window.twttr.events.bind('rendered', () => {
+ if (loadingRef.current) {
+ const parentElement = loadingRef.current.parentElement;
+ if (parentElement) {
+ parentElement.style.height = 'auto';
+ parentElement.classList.add('d-flex', 'justify-content-center');
+ }
+ loadingRef.current.remove();
+ }
+ });
+ };
+ }, []);
+ return (
+ <>
+ <blockquote className="twitter-tweet ">
+ <a href={url} target="_blank">
+ {title}
+ </a>
+ </blockquote>
+ <span
+ ref={loadingRef}
+ className="loading position-absolute top-0 left-0 w-100 h-100 z-1
bg-white d-flex justify-content-center align-items-center">
+ <Spinner animation="border" variant="secondary" />
+ </span>
+ </>
+ );
+};
+
+export default TwitterEmbed;
diff --git a/embed-basic/components/YouTubeEmbed/index.tsx
b/embed-basic/components/YouTubeEmbed/index.tsx
new file mode 100644
index 0000000..9a5879b
--- /dev/null
+++ b/embed-basic/components/YouTubeEmbed/index.tsx
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import EmbedContainer from '../EmbedContainer';
+
+const YouTubeEmbed = ({ videoId }) => {
+ return (
+ <EmbedContainer height={380}>
+ <iframe
+ width="100%"
+ height="100%"
+ src={`https://www.youtube.com/embed/${videoId}`}
+ title="YouTube video player"
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media;
gyroscope; picture-in-picture"
+ allowFullScreen
+ />
+ </EmbedContainer>
+ );
+};
+
+export default YouTubeEmbed;
diff --git a/embed-basic/components/index.ts b/embed-basic/components/index.ts
new file mode 100644
index 0000000..c4ad04d
--- /dev/null
+++ b/embed-basic/components/index.ts
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import GithubGistEmbed from './GithubGistEmbed';
+import CodePenEmbed from './CodePenEmbed';
+import YouTubeEmbed from './YouTubeEmbed';
+import JSFiddleEmbed from './JSFiddleEmbed';
+import FigmaEmbed from './FigmaEmbed';
+import ExcalidrawEmbed from './ExcalidrawEmbed';
+import LoomEmbed from './LoomEmbed';
+import DropboxEmbed from './DropboxEmbed';
+import TwitterEmbed from './TwitterEmbed';
+
+export {
+ GithubGistEmbed,
+ CodePenEmbed,
+ YouTubeEmbed,
+ JSFiddleEmbed,
+ FigmaEmbed,
+ ExcalidrawEmbed,
+ LoomEmbed,
+ DropboxEmbed,
+ TwitterEmbed,
+};
diff --git a/embed-basic/hooks.ts b/embed-basic/hooks.tsx
similarity index 74%
rename from embed-basic/hooks.ts
rename to embed-basic/hooks.tsx
index 9380f88..d1a59a3 100644
--- a/embed-basic/hooks.ts
+++ b/embed-basic/hooks.tsx
@@ -17,12 +17,31 @@
* under the License.
*/
-import { useEffect, useState, RefObject } from 'react';
+import {
+ useEffect,
+ useState,
+ RefObject,
+ ReactElement,
+ isValidElement,
+} from 'react';
+import { createRoot } from 'react-dom/client';
+import {
+ GithubGistEmbed,
+ CodePenEmbed,
+ YouTubeEmbed,
+ JSFiddleEmbed,
+ FigmaEmbed,
+ ExcalidrawEmbed,
+ LoomEmbed,
+ DropboxEmbed,
+ TwitterEmbed,
+} from './components';
interface Config {
platform: string;
enable: boolean;
}
+
const useRenderEmbed = (
element: HTMLElement | RefObject<HTMLElement> | null,
) => {
@@ -37,7 +56,7 @@ const useRenderEmbed = (
/https:\/\/www\.youtube\.com\/embed\/([a-zA-Z0-9_-]{11})/,
],
embed: (videoId: string) => {
- return `<iframe width="100%" height="380"
src="https://www.youtube.com/embed/${videoId}" title="YouTube video player"
frameborder="0" allow="accelerometer; autoplay; clipboard-write;
encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`;
+ return <YouTubeEmbed videoId={videoId} />;
},
},
{
@@ -67,7 +86,12 @@ const useRenderEmbed = (
}
`;
- return [styleElement, blockquoteElement, scriptElement];
+ return (
+ <TwitterEmbed
+ url={url.replace('x.com', 'twitter.com')}
+ title={title}
+ />
+ );
},
},
{
@@ -77,7 +101,7 @@ const useRenderEmbed = (
/https:\/\/codepen\.io\/[a-zA-Z0-9_]+\/full\/([a-zA-Z0-9_]+)/,
],
embed: (penId) => {
- return `<iframe width="100%" height="380" scrolling="no"
title="CodePen Embed"
src="https://codepen.io/${penId}/embed/preview/${penId}?height=265&theme-id=0&default-tab=result"
frameborder="no" allowtransparency="true" allowfullscreen="true"></iframe>`;
+ return <CodePenEmbed penId={penId} />;
},
},
{
@@ -87,7 +111,7 @@ const useRenderEmbed = (
/https:\/\/jsfiddle\.net\/[a-zA-Z0-9_]+\/([a-zA-Z0-9_]+)\/embed/,
],
embed: (fiddleId: string) => {
- return `<iframe width="100%" height="380"
src="https://jsfiddle.net/${fiddleId}/embedded/"
allowfullscreen="allowfullscreen" allowpaymentrequest
frameborder="0"></iframe>`;
+ return <JSFiddleEmbed fiddleId={fiddleId} />;
},
},
{
@@ -98,14 +122,7 @@ const useRenderEmbed = (
],
embed: (_, url) => {
const scriptUrl = url.indexOf('.js') > -1 ? url : `${url}.js`;
- console.log(scriptUrl);
- return `<iframe
- width="100%"
- height="350"
- src="data:text/html;charset=utf-8,
- <head><base target='_blank' /></head>
- <body style='margin:0;'><script src='${scriptUrl}'></script>
- </body>">`;
+ return <GithubGistEmbed scriptUrl={scriptUrl} />;
},
},
{
@@ -115,8 +132,7 @@ const useRenderEmbed = (
/https:\/\/www\.figma\.com\/file\/[a-zA-Z0-9_]+\/([a-zA-Z0-9_]+)/,
],
embed: (_, url) => {
- return `<iframe style="border: none;" width="100%" height="450
-" src="https://www.figma.com/embed?embed_host=share&url=${url}"
allowfullscreen></iframe>`;
+ return <FigmaEmbed url={url} />;
},
},
{
@@ -126,7 +142,7 @@ const useRenderEmbed = (
/https:\/\/excalidraw\.com\/([a-zA-Z0-9_,-]+)/,
],
embed: (excalidrawId: string) => {
- return `<iframe width="100%" height="380"
src="https://excalidraw.com/${excalidrawId}/embed" frameborder="0"></iframe>`;
+ return <ExcalidrawEmbed excalidrawId={excalidrawId} />;
},
},
{
@@ -136,7 +152,7 @@ const useRenderEmbed = (
/https:\/\/www\.loom\.com\/share\/([a-zA-Z0-9_]+)/,
],
embed: (loomId: string) => {
- return `<iframe width="100%" height="380"
src="https://www.loom.com/embed/${loomId}" frameborder="0"></iframe>`;
+ return <LoomEmbed loomId={loomId} />;
},
},
{
@@ -145,7 +161,7 @@ const useRenderEmbed = (
/https:\/\/www\.dropbox\.com\/s\/([a-zA-Z0-9_]+)\/[a-zA-Z0-9_]+/,
],
embed: (dropboxId: string) => {
- return `<iframe width="100%" height="380"
src="https://www.dropbox.com/s/${dropboxId}?raw=1" frameborder="0"></iframe>`;
+ return <DropboxEmbed dropboxId={dropboxId} />;
},
},
];
@@ -161,7 +177,7 @@ const useRenderEmbed = (
url: string,
title: string,
): string | HTMLElement | HTMLElement[] => {
- let html: string | HTMLElement | HTMLElement[] = '';
+ let html: string | HTMLElement | HTMLElement[] | ReactElement = '';
filteredEmbeds.forEach((embed) => {
if (html) return;
@@ -193,19 +209,11 @@ const useRenderEmbed = (
return;
}
const embed = renderEmbed(url, link?.textContent || '');
- if (embed) {
+ if (isValidElement(embed)) {
const parentElement = link.parentElement as HTMLElement;
- if (typeof embed === 'string') {
- parentElement.innerHTML = embed;
- } else if (Array.isArray(embed)) {
- link.remove();
- embed.forEach((item) => {
- parentElement.appendChild(item);
- });
- } else {
- link.innerHTML = '';
- parentElement.appendChild(embed);
- }
+ parentElement.classList.add('position-relative');
+ parentElement.style.height = '128px';
+ createRoot(parentElement).render(embed);
} else {
link.innerHTML = `
<div class="border rounded p-3">