import Image from '@tiptap/extension-image'
import { mergeAttributes } from '@tiptap/core'
import { ReactNodeViewRenderer } from '@tiptap/react'
import { ImageNodeView } from './ImageNodeView'
/**
* تصویر مقاله با کپشن.
* خروجی HTML در سایت:
کپشن
* و در ویرایشگر با NodeView سفارشی (ورودی کپشن + دکمه حذف) نمایش داده میشود.
*/
export const ArticleImage = Image.extend({
addAttributes() {
return {
// ویژگیهای استاندارد تصویر (src/alt/title/width/height) از افزونه پایه
...this.parent?.(),
caption: {
default: '',
parseHTML: (element) =>
element.closest('figure')?.querySelector('figcaption')?.textContent?.trim() ?? '',
},
// پیوند کپشن — کل متن figcaption به این نشانی لینک میشود
caption_href: {
default: '',
parseHTML: (element) =>
element.closest('figure')?.querySelector('figcaption a')?.getAttribute('href') ?? '',
},
}
},
parseHTML() {
return [
{
tag: 'figure',
priority: 60,
getAttrs: (element) => {
if (!(element instanceof HTMLElement)) return false
const img = element.querySelector('img')
if (!img) return false
return {
src: img.getAttribute('src'),
alt: img.getAttribute('alt'),
title: img.getAttribute('title'),
caption: element.querySelector('figcaption')?.textContent?.trim() ?? '',
caption_href: element.querySelector('figcaption a')?.getAttribute('href') ?? '',
}
},
},
// تصاویر بدون figure (محتوای قدیمی یا چسباندهشده)
{ tag: 'img[src]:not([src^="data:"])' },
]
},
renderHTML({ HTMLAttributes }) {
const { caption, ...imageAttributes } = HTMLAttributes
const image: [string, Record] = [
'img',
mergeAttributes(this.options.HTMLAttributes, imageAttributes),
]
// کپشن خالی → عنصر figcaption اصلاً رندر نمیشود (فقط تصویر میماند)
const captionHref = (HTMLAttributes.caption_href as string | undefined)?.trim() ?? ''
// توجه: آرایهٔ درونی بهصورت تو در تو پاس میشود — اسپرد آن اسپک را تخت میکند
// و رندرر استاتیک با «Unsupported DomOutputSpec» میمیرد.
const captionSpec = captionHref
? ['a', { href: captionHref, target: '_blank', rel: 'noopener noreferrer nofollow' }, caption]
: caption
return caption
? [
'figure',
{ class: 'article-figure' },
image,
['figcaption', { class: 'article-figure__caption' }, captionSpec],
]
: ['figure', { class: 'article-figure' }, image]
},
addNodeView() {
return ReactNodeViewRenderer(ImageNodeView)
},
})