diff --git a/src/components/editor/Editor.tsx b/src/components/editor/Editor.tsx
index 2bbe474..7a62e62 100644
--- a/src/components/editor/Editor.tsx
+++ b/src/components/editor/Editor.tsx
@@ -97,7 +97,7 @@ const Editor = ({ content }: { content: JSONContent[] | null }) => {
Underline,
Highlight.configure({ multicolor: true }),
TextAlign.configure({
- types: ['paragraph', 'image', 'blockquote', 'horizontal_rule'],
+ types: ['paragraph', 'image', 'blockquote', 'horizontal_rule', 'file'],
}),
Blockquote.configure({
HTMLAttributes: {
diff --git a/src/components/editor/common/File.ts b/src/components/editor/common/File.ts
new file mode 100644
index 0000000..8b002f0
--- /dev/null
+++ b/src/components/editor/common/File.ts
@@ -0,0 +1,52 @@
+export interface FileAttributes {
+ src: string;
+ title: string;
+}
+
+export const createFileNodeHTML = (attrs: FileAttributes): HTMLElement => {
+ const fileWrapper = document.createElement('div');
+ fileWrapper.className =
+ 'flex items-center justify-between p-3 border border-gray-300 rounded-lg shadow-sm bg-white max-w-md';
+
+ // 왼쪽 아이콘과 파일 제목
+ const leftDiv = document.createElement('div');
+ leftDiv.className = 'flex items-center space-x-2';
+
+ const iconSvg = `
+
+ `;
+ leftDiv.innerHTML = iconSvg;
+
+ const fileTitle = document.createElement('span');
+ fileTitle.className = 'text-sm font-medium text-gray-800 truncate';
+ fileTitle.textContent = attrs.title || 'No title';
+
+ leftDiv.appendChild(fileTitle);
+
+ // 오른쪽 다운로드 아이콘
+ const rightSpan = document.createElement('span');
+ rightSpan.className =
+ 'flex items-center justify-center w-8 h-8 text-blue-600 rounded-full transition';
+
+ const downloadLink = document.createElement('a');
+ downloadLink.href = `http://43.200.90.72/file/download/${attrs.src}`;
+ downloadLink.target = '_blank';
+ downloadLink.rel = 'noopener noreferrer';
+
+ const downloadSvg = `
+
+ `;
+ downloadLink.innerHTML = downloadSvg;
+
+ rightSpan.appendChild(downloadLink);
+
+ // 전체 구조 결합
+ fileWrapper.appendChild(leftDiv);
+ fileWrapper.appendChild(rightSpan);
+
+ return fileWrapper;
+};
diff --git a/src/components/editor/common/extractPaywallData.ts b/src/components/editor/common/extractPaywallData.ts
index d6b400d..775faf1 100644
--- a/src/components/editor/common/extractPaywallData.ts
+++ b/src/components/editor/common/extractPaywallData.ts
@@ -1,6 +1,7 @@
import { Editor } from '@tiptap/react';
import { JSONContent } from '@tiptap/core';
import { DOMSerializer } from '@tiptap/pm/model';
+import { createFileNodeHTML, FileAttributes } from './File';
interface PaywallData {
isPremium: boolean;
@@ -25,9 +26,18 @@ const extractPaywallData = (editor: Editor): PaywallData => {
const tempDiv = document.createElement('div');
nodes.forEach((node) => {
try {
- const pmNode = schema.nodeFromJSON(node);
- const serializedNode = domSerializer.serializeNode(pmNode);
- tempDiv.appendChild(serializedNode);
+ if (node.type === 'file' && node.attrs?.src) {
+ const fileWrapper = createFileNodeHTML({
+ src: node.attrs.src,
+ title: node.attrs.title,
+ } as FileAttributes);
+
+ tempDiv.appendChild(fileWrapper);
+ } else {
+ const pmNode = schema.nodeFromJSON(node);
+ const serializedNode = domSerializer.serializeNode(pmNode);
+ tempDiv.appendChild(serializedNode);
+ }
} catch (error) {
console.error('Error converting node to HTML:', error, node);
}
diff --git a/src/components/editor/customComponent/CustomFile.ts b/src/components/editor/customComponent/CustomFile.ts
index 97face7..22438bb 100644
--- a/src/components/editor/customComponent/CustomFile.ts
+++ b/src/components/editor/customComponent/CustomFile.ts
@@ -7,7 +7,7 @@ const CustomFile = Node.create({
group: 'block',
atom: true,
-
+
addAttributes() {
return {
src: {
@@ -18,7 +18,7 @@ const CustomFile = Node.create({
},
};
},
-
+
parseHTML() {
return [
{
@@ -26,11 +26,23 @@ const CustomFile = Node.create({
},
];
},
-
+
renderHTML({ HTMLAttributes }) {
- return ['div', mergeAttributes(HTMLAttributes, { 'data-type': 'file' }), ''];
+ return [
+ 'div',
+ mergeAttributes(HTMLAttributes, { 'data-type': 'file' }),
+ [
+ 'a',
+ {
+ href: HTMLAttributes.src,
+ target: '_blank',
+ rel: 'noopener noreferrer',
+ },
+ 'Download File',
+ ],
+ ];
},
-
+
addNodeView() {
return ReactNodeViewRenderer(FileComponent); // React 컴포넌트와 연결
},