This commit is contained in:
Виталий Лавшонок
2025-11-04 12:54:05 +03:00
parent 1ef655803a
commit 7ef7bdf055

View File

@@ -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<MarkdownEditorProps> = ({
defaultValue,
onChange,
}) => {
const [markdown, setMarkdown] = useState<string>(defaultValue ? defaultValue :
`# 🌙 Добро пожаловать в Markdown-редактор
const MarkdownEditor: FC<MarkdownEditorProps> = ({ defaultValue, onChange }) => {
const [markdown, setMarkdown] = useState<string>(defaultValue || `# 🌙 Добро пожаловать в Markdown-редактор
Добро пожаловать в **Markdown-редактор**!
Здесь ты можешь писать в формате Markdown и видеть результат **в реальном времени** 👇
@@ -202,99 +199,87 @@ print(greet("Мир"))
`);
useEffect(() => {
onChange(markdown);
}, [markdown])
useEffect(() => {
onChange(markdown);
}, [markdown]);
return (
<div className="h-screen grid grid-rows-[60px,1fr]">
<div className="">
// Обработчик вставки
const handlePaste = async (e: React.ClipboardEvent<HTMLTextAreaElement>) => {
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 (
<div className="h-screen grid grid-rows-[60px,1fr]">
<div>
<Header missionId={1} />
</div>
<div className="grid grid-cols-2 h-full min-h-0">
<div className="overflow-y-auto min-h-0 overflow-hidden ">
<div className="p-4 border-r border-gray-700 flex flex-col h-full ">
<h2 className="text-lg font-semibold mb-3 text-gray-100">👀 Предпросмотр</h2>
<div className="flex-1 bg-[#161b22] rounded-lg shadow-lg p-6 h-[calc(100%-40px)]">
<div className="prose prose-invert max-w-none h-full overflow-auto pr-4 medium-scrollbar">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[
rehypeRaw,
rehypeSanitize,
rehypeHighlight
]}
>
{markdown}
</ReactMarkdown>
</div>
</div>
<div className="grid grid-cols-2 h-full min-h-0">
{/* Предпросмотр */}
<div className="overflow-y-auto min-h-0 overflow-hidden">
<div className="p-4 border-r border-gray-700 flex flex-col h-full">
<h2 className="text-lg font-semibold mb-3 text-gray-100">👀 Предпросмотр</h2>
<div className="flex-1 bg-[#161b22] rounded-lg shadow-lg p-6 h-[calc(100%-40px)]">
<div className="prose prose-invert max-w-none h-full overflow-auto pr-4 medium-scrollbar">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw, rehypeSanitize, rehypeHighlight]}
>
{markdown}
</ReactMarkdown>
</div>
</div>
</div>
</div>
<div className="overflow-y-auto min-h-0 overflow-hidden ">
<div className="p-4 border-r border-gray-700 flex flex-col h-full ">
<h2 className="text-lg font-semibold mb-3 text-gray-100">📝 Редактор</h2>
<textarea
value={markdown}
onChange={(e) => setMarkdown(e.target.value)}
className="flex-1 w-full bg-[#0d1117] text-gray-200 border border-gray-700
rounded-lg p-5 font-mono text-sm resize-none focus:outline-none focus:ring-2
medium-scrollbar
"
placeholder="Пиши в формате Markdown..."
/>
</div>
{/* Редактор */}
<div className="overflow-y-auto min-h-0 overflow-hidden">
<div className="p-4 border-r border-gray-700 flex flex-col h-full">
<h2 className="text-lg font-semibold mb-3 text-gray-100">📝 Редактор</h2>
<textarea
value={markdown}
onChange={(e) => setMarkdown(e.target.value)}
onPaste={handlePaste} // <-- вот сюда обработчик вставки
className="flex-1 w-full bg-[#0d1117] text-gray-200 border border-gray-700
rounded-lg p-5 font-mono text-sm resize-none focus:outline-none focus:ring-2
medium-scrollbar"
placeholder="Пиши в формате Markdown..."
/>
</div>
</div>
</div>
</div>
);
};
);
}
/*
<div className="grid grid-cols-2 h-screen bg-[#0d1117] text-gray-200 relative">
<div className="p-4 border-r border-gray-700 bg-[#161b22] flex flex-col h-screen ">
<h2 className="text-lg font-semibold mb-3 text-gray-100">📝 Редактор</h2>
<textarea
value={markdown}
onChange={(e) => setMarkdown(e.target.value)}
className="flex-1 w-full bg-[#0d1117] text-gray-200 border border-gray-700
rounded-lg p-3 font-mono text-sm resize-none focus:outline-none focus:ring-2
medium-scrollbar
"
placeholder="Пиши в формате Markdown..."
/>
</div>
<div className="p-4 bg-[#0d1117] flex flex-col h-full relative">
<h2 className="text-lg font-semibold mb-[12px] text-gray-100 h-[28px]">👀 Предпросмотр</h2>
<div className="flex-1 bg-[#161b22] rounded-lg shadow-lg p-6 h-[calc(100%-40px)]">
<div className="prose prose-invert max-w-none h-full overflow-auto pr-4 medium-scrollbar">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[
rehypeRaw,
rehypeSanitize,
rehypeHighlight
]}
>
{markdown}
</ReactMarkdown>
</div>
</div>
</div>
</div>
*/
export default MarkdownEditor;
export default MarkdownEditor;