From 6eb0ba3eddf21f8c02592a1012ac596238d704e0 Mon Sep 17 00:00:00 2001 From: kch12 Date: Tue, 18 Feb 2025 21:49:16 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20youtube=20=EC=82=BD=EC=9E=85=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20HTML=20?= =?UTF-8?q?=EB=B3=80=ED=99=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/article.ts | 35 +++++----- .../editor/common/extractPaywallData.ts | 35 +++++++--- src/components/editor/handler/AddYoutube.tsx | 65 ++++++++++++++----- 3 files changed, 95 insertions(+), 40 deletions(-) diff --git a/src/api/article.ts b/src/api/article.ts index 02f9f01..18985d1 100644 --- a/src/api/article.ts +++ b/src/api/article.ts @@ -2,22 +2,27 @@ import { AddArticleData } from '../types/article'; import { apiClient } from './axiosInstance'; export const saveArticle = async (articleData: AddArticleData) => { - try { - const token = localStorage.getItem('token'); + console.log('articleData:', articleData); + console.log('imageLink:', articleData.imageLink); + console.log('paywallUp:', articleData.paywallUp); + console.log('paywallDown:', articleData.paywallDown); - if (!token) { - throw new Error('로그인이 필요합니다.'); - } - const { data } = await apiClient.post('/articles', articleData, { - headers: { - Authorization: `${token}`, - }, - }); - return data; - } catch (error) { - console.error(error); - throw new Error('api Error'); - } + // try { + // const token = localStorage.getItem('token'); + + // if (!token) { + // throw new Error('로그인이 필요합니다.'); + // } + // const { data } = await apiClient.post('/articles', articleData, { + // headers: { + // Authorization: `${token}`, + // }, + // }); + // return data; + // } catch (error) { + // console.error(error); + // throw new Error('api Error'); + // } }; export const uploadImage = async (imageUrl: string) => { diff --git a/src/components/editor/common/extractPaywallData.ts b/src/components/editor/common/extractPaywallData.ts index 6392dd6..b61620c 100644 --- a/src/components/editor/common/extractPaywallData.ts +++ b/src/components/editor/common/extractPaywallData.ts @@ -52,6 +52,28 @@ const extractPaywallData = (editor: Editor): PaywallData => { whiteSpace: node.attrs.whiteSpace, } as LinkAttributes); tempDiv.appendChild(linkElement); + } else if (node.type === 'oembed' && node.attrs?.src) { + const oembedWrapper = document.createElement('div'); + oembedWrapper.className = `relative mt-5 ${node.attrs.alignment}`; + + const moduleElement = document.createElement('div'); + moduleElement.className = 'relative'; + moduleElement.style.paddingTop = '75%'; + + const iframeElement = document.createElement('iframe'); + iframeElement.width = node.attrs.width; + iframeElement.height = node.attrs.height; + iframeElement.src = node.attrs.src; + iframeElement.setAttribute('frameborder', node.attrs.frameborder); + iframeElement.allow = node.attrs.allow; + iframeElement.referrerPolicy = node.attrs.referrerpolicy; + iframeElement.allowFullscreen = node.attrs.allowfullscreen; + iframeElement.title = node.attrs.title; + iframeElement.className = 'absolute top-0 left-0 w-full h-full'; + + moduleElement.appendChild(iframeElement); + oembedWrapper.appendChild(moduleElement); + tempDiv.appendChild(oembedWrapper); } else if (node.type === 'table') { const tableWrapper = document.createElement('div'); tableWrapper.className = 'mt-5 relative mx-auto w-full'; @@ -110,15 +132,10 @@ const extractPaywallData = (editor: Editor): PaywallData => { if (!imageLink) { if (node.type === 'photo' && node.attrs?.src) { imageLink = node.attrs.src; - } else if ( - (node.type === 'photoGroup' || node.type === 'photoStrip') && - node.content - ) { - const firstImgNode = node.content.find( - (childNode) => childNode.type === 'image', - ); - if (firstImgNode && firstImgNode.attrs?.src) { - imageLink = firstImgNode.attrs.src; + } else if (node.type === 'photoGroup' || node.type === 'photoStrip') { + const firstImage = node.attrs?.images?.[0]; + if (firstImage && firstImage.src) { + imageLink = firstImage.src; } } } diff --git a/src/components/editor/handler/AddYoutube.tsx b/src/components/editor/handler/AddYoutube.tsx index f9c6e3c..409e352 100644 --- a/src/components/editor/handler/AddYoutube.tsx +++ b/src/components/editor/handler/AddYoutube.tsx @@ -37,22 +37,55 @@ const AddYoutube: React.FC<{ editor: Editor }> = ({ editor }) => { throw new Error('YouTube oEmbed에서 iframe src를 찾을 수 없습니다.'); } - editor - .chain() - .focus() - .insertContent({ - type: 'oembed', - attrs: { - src: iframeSrc, - width: data.thumbnail_width || '400', - height: data.thumbnail_height || '300', - frameborder: frameborder, - allow: allow, - allowfullscreen: allowfullscreen, - title: data.title || 'Untitled', - }, - }) - .run(); + const { state } = editor.view; + const { selection } = state; + + const isInsideCustomBlock = + selection.$from.node(1)?.type.name === 'customBlock'; + + if (isInsideCustomBlock) { + const customBlockPos = + selection.$from.start(1) + selection.$from.node(1).nodeSize; + + editor + .chain() + .focus() + .command(({ tr }) => { + tr.insertText('\n', state.selection.from); + return true; + }) + .exitCode() + .insertContentAt(customBlockPos, { + type: 'oembed', + attrs: { + src: iframeSrc, + width: data.thumbnail_width || '400', + height: data.thumbnail_height || '300', + frameborder: frameborder, + allow: allow, + allowfullscreen: allowfullscreen, + title: data.title || 'Untitled', + }, + }) + .run(); + } else { + editor + .chain() + .focus() + .insertContent({ + type: 'oembed', + attrs: { + src: iframeSrc, + width: data.thumbnail_width || '400', + height: data.thumbnail_height || '300', + frameborder: frameborder, + allow: allow, + allowfullscreen: allowfullscreen, + title: data.title || 'Untitled', + }, + }) + .run(); + } } catch (error) { console.error('Failed to fetch YouTube oEmbed API:', error); } From 86df8341a8f29dce396877bb7329b00c41c6285a Mon Sep 17 00:00:00 2001 From: kch12 Date: Tue, 18 Feb 2025 21:50:10 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EC=95=84=ED=8B=B0=ED=81=B4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/article.ts | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/api/article.ts b/src/api/article.ts index 18985d1..02f9f01 100644 --- a/src/api/article.ts +++ b/src/api/article.ts @@ -2,27 +2,22 @@ import { AddArticleData } from '../types/article'; import { apiClient } from './axiosInstance'; export const saveArticle = async (articleData: AddArticleData) => { - console.log('articleData:', articleData); - console.log('imageLink:', articleData.imageLink); - console.log('paywallUp:', articleData.paywallUp); - console.log('paywallDown:', articleData.paywallDown); - - // try { - // const token = localStorage.getItem('token'); + try { + const token = localStorage.getItem('token'); - // if (!token) { - // throw new Error('로그인이 필요합니다.'); - // } - // const { data } = await apiClient.post('/articles', articleData, { - // headers: { - // Authorization: `${token}`, - // }, - // }); - // return data; - // } catch (error) { - // console.error(error); - // throw new Error('api Error'); - // } + if (!token) { + throw new Error('로그인이 필요합니다.'); + } + const { data } = await apiClient.post('/articles', articleData, { + headers: { + Authorization: `${token}`, + }, + }); + return data; + } catch (error) { + console.error(error); + throw new Error('api Error'); + } }; export const uploadImage = async (imageUrl: string) => {