From 7ef7bdf055d5c874addd0b8a3793dd47f9d556a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D1=82=D0=B0=D0=BB=D0=B8=D0=B9=20=D0=9B=D0=B0?= =?UTF-8?q?=D0=B2=D1=88=D0=BE=D0=BD=D0=BE=D0=BA?= <114582703+valavshonok@users.noreply.github.com> Date: Tue, 4 Nov 2025 12:54:05 +0300 Subject: [PATCH] add img --- src/views/articleeditor/Editor.tsx | 171 +++++++++++++---------------- 1 file changed, 78 insertions(+), 93 deletions(-) diff --git a/src/views/articleeditor/Editor.tsx b/src/views/articleeditor/Editor.tsx index 6a4327b..5f011ae 100644 --- a/src/views/articleeditor/Editor.tsx +++ b/src/views/articleeditor/Editor.tsx @@ -4,20 +4,17 @@ import remarkGfm from "remark-gfm"; import rehypeHighlight from "rehype-highlight"; import rehypeRaw from "rehype-raw"; import rehypeSanitize from "rehype-sanitize"; +import axios from "../../axios"; import "highlight.js/styles/github-dark.css"; import Header from "../mission/statement/Header"; interface MarkdownEditorProps { - defaultValue?: string; - onChange: (value: string) => void; + defaultValue?: string; + onChange: (value: string) => void; } - const MarkdownEditor: FC = ({ - defaultValue, - onChange, -}) => { - const [markdown, setMarkdown] = useState(defaultValue ? defaultValue : - `# 🌙 Добро пожаловать в Markdown-редактор +const MarkdownEditor: FC = ({ defaultValue, onChange }) => { + const [markdown, setMarkdown] = useState(defaultValue || `# 🌙 Добро пожаловать в Markdown-редактор Добро пожаловать в **Markdown-редактор**! Здесь ты можешь писать в формате Markdown и видеть результат **в реальном времени** 👇 @@ -202,99 +199,87 @@ print(greet("Мир")) `); - useEffect(() => { - onChange(markdown); - }, [markdown]) + useEffect(() => { + onChange(markdown); + }, [markdown]); - return ( -
-
+ // Обработчик вставки + const handlePaste = async (e: React.ClipboardEvent) => { + const items = e.clipboardData.items; + + for (const item of items) { + if (item.type.startsWith("image/")) { + e.preventDefault(); // предотвращаем вставку картинки как текста + + const file = item.getAsFile(); + if (!file) return; + + const formData = new FormData(); + formData.append("file", file); + + try { + const response = await axios.post("/media/upload", formData, { + headers: { "Content-Type": "multipart/form-data" }, + }); + + const imageUrl = response.data.url; + // Вставляем ссылку на картинку в текст + const cursorPos = (e.target as HTMLTextAreaElement).selectionStart; + const newText = + markdown.slice(0, cursorPos) + + `![image](${imageUrl})` + + markdown.slice(cursorPos); + + setMarkdown(newText); + } catch (err) { + console.error("Ошибка загрузки изображения:", err); + } + } + } + }; + + return ( +
+
- -
-
-
-

👀 Предпросмотр

-
-
- - {markdown} - -
-
+
+ {/* Предпросмотр */} +
+
+

👀 Предпросмотр

+
+
+ + {markdown} + +
+
- -
-
-

📝 Редактор

-