import { Node, mergeAttributes } from '@tiptap/core'; export interface ButtonOptions { HTMLAttributes: Record; } declare module '@tiptap/core' { interface Commands { button: { setButton: (options: { text: string; href: string; style?: 'solid' | 'outline' | 'link' }) => ReturnType; }; } } export const ButtonExtension = Node.create({ name: 'button', group: 'inline', inline: true, atom: true, addAttributes() { return { text: { default: 'Click Here', }, href: { default: '#', }, style: { default: 'solid', }, }; }, parseHTML() { return [ { tag: 'a[data-button]', priority: 100, // Higher priority than Link extension (default 50) getAttrs: (node: HTMLElement) => ({ text: node.getAttribute('data-text') || node.textContent || 'Click Here', href: node.getAttribute('data-href') || node.getAttribute('href') || '#', style: node.getAttribute('data-style') || 'solid', }), }, { tag: 'a.button', priority: 100, getAttrs: (node: HTMLElement) => ({ text: node.textContent || 'Click Here', href: node.getAttribute('href') || '#', style: 'solid', }), }, { tag: 'a.button-outline', priority: 100, getAttrs: (node: HTMLElement) => ({ text: node.textContent || 'Click Here', href: node.getAttribute('href') || '#', style: 'outline', }), }, ]; }, renderHTML({ HTMLAttributes }) { const { text, href, style } = HTMLAttributes; // Different styling based on button style let inlineStyle: string; if (style === 'link') { // Plain link - just underlined text, no button-like appearance inlineStyle = 'color: #7f54b3; text-decoration: underline; cursor: pointer;'; } else { // Solid/Outline buttons - show as styled link with background hint inlineStyle = 'color: #7f54b3; text-decoration: underline; cursor: pointer; font-weight: 600; background: rgba(127,84,179,0.1); padding: 2px 6px; border-radius: 3px;'; } return [ 'a', mergeAttributes(this.options.HTMLAttributes, { href, class: style === 'link' ? 'link-node' : 'button-node', style: inlineStyle, 'data-button': '', 'data-text': text, 'data-href': href, 'data-style': style, title: style === 'link' ? `Link: ${text}` : `Button: ${text} → ${href}`, }), text, ]; }, addCommands() { return { setButton: (options) => ({ commands }) => { return commands.insertContent({ type: this.name, attrs: options, }); }, }; }, });