import { Node, mergeAttributes } from '@tiptap/core'; import { ReactNodeViewRenderer, NodeViewWrapper, NodeViewContent, type NodeViewProps, } from '@tiptap/react'; import { LockKeyhole } from 'lucide-react'; /** 编辑态「登录可见」区块视图 */ function MembersOnlyView({ selected }: NodeViewProps) { return (
登录可见
); } declare module '@tiptap/core' { interface Commands { membersOnly: { insertMembersOnly: () => ReturnType; wrapMembersOnly: () => ReturnType; }; } } /** TipTap 自定义节点:登录可见内容区块 */ export const MembersOnly = Node.create({ name: 'membersOnly', group: 'block', content: 'block+', defining: true, isolating: true, parseHTML() { return [{ tag: 'members-only' }]; }, renderHTML({ HTMLAttributes }) { return ['members-only', mergeAttributes(HTMLAttributes), 0]; }, addNodeView() { return ReactNodeViewRenderer(MembersOnlyView); }, addCommands() { return { insertMembersOnly: () => ({ chain }) => chain() .insertContent({ type: this.name, content: [{ type: 'paragraph', content: [{ type: 'text', text: '在此输入仅登录用户可见的内容…' }], }], }) .run(), wrapMembersOnly: () => ({ tr, state, dispatch }) => { const { from, to, empty } = state.selection; if (empty) return false; const slice = state.doc.slice(from, to); if (!slice.content.size) return false; const node = state.schema.nodes.membersOnly.create(null, slice.content); if (dispatch) { tr.replaceRangeWith(from, to, node); } return true; }, }; }, });