"use client"; import { useState } from "react"; import { useEditor, EditorContent, NodeViewWrapper, NodeViewContent, ReactNodeViewRenderer } from "@tiptap/react"; import { Node, mergeAttributes } from "@tiptap/core"; import StarterKit from "@tiptap/starter-kit"; import CodeBlock from "@tiptap/extension-code-block"; import Image from "@tiptap/extension-image"; import Link from "@tiptap/extension-link"; import Underline from "@tiptap/extension-underline"; import { Copy, Check } from "lucide-react"; import { KinescopePlayer } from "@/components/player/kinescope-player"; function CodeBlockStudentView({ node }: { node: { textContent: string } }) { const [copied, setCopied] = useState(false); const handleCopy = async () => { // WYSIWYG: копируем содержимое блока ровно как показано. Для Obsidian-сниппетов // (dataview/query) забор ```...``` хранится прямо в содержимом → копируется целиком. try { await navigator.clipboard.writeText(node.textContent); setCopied(true); setTimeout(() => setCopied(false), 1500); } catch { // clipboard недоступен (нет https / нет прав) — тихо игнорируем } }; return (
         as="code" />
      
); } const CodeBlockWithCopy = CodeBlock.extend({ addNodeView() { // eslint-disable-next-line @typescript-eslint/no-explicit-any return ReactNodeViewRenderer(CodeBlockStudentView as any); }, }); function KinescopeVideoStudentView({ node, extension, }: { node: { attrs: Record }; extension: { options: { poster?: string } }; }) { const videoId = node.attrs.videoId as string; if (!videoId) return null; return (
); } const KinescopeVideoExtension = Node.create<{ poster?: string }>({ name: "kinescopeVideo", group: "block", atom: true, addOptions() { return { poster: undefined }; }, addAttributes() { return { videoId: { default: "" } }; }, parseHTML() { return [{ tag: "div[data-kinescope-video]" }]; }, renderHTML({ HTMLAttributes }) { return ["div", mergeAttributes({ "data-kinescope-video": "" }, HTMLAttributes)]; }, addNodeView() { // eslint-disable-next-line @typescript-eslint/no-explicit-any return ReactNodeViewRenderer(KinescopeVideoStudentView as any); }, }); export function LessonContent({ content, coverImage }: { content: object; coverImage?: string | null }) { const editor = useEditor({ extensions: [ StarterKit.configure({ codeBlock: false }), CodeBlockWithCopy, Underline, Image.configure({ inline: false }), Link.configure({ openOnClick: true }), KinescopeVideoExtension.configure({ poster: coverImage ?? undefined }), ], content, editable: false, editorProps: { attributes: { class: "prose prose-slate max-w-none focus:outline-none", }, }, }); return ; }