import { Node as e, mergeAttributes as t } from "@tiptap/core"
import { ReactNodeViewRenderer as i } from "@tiptap/react"
import { getUrls as n, debounce as r } from "./helpers/index.js"
const s = "link-preview",
a = 5
export const handleUpdate = r((e, t) => {
const i = e.getJSON(),
r = t.storage,
s = n(i, (t) => {
const i = e.chain().focus().extendMarkRange("link")
t ? i.setLink({ href: t }).run() : i.unsetLink().run()
})
for (const t of [...s].slice(0, 5))
r.active.has(t) || r.failed.has(t) || (e.commands.setLinkPreview({ url: t }), r.active.add(t))
for (const t of r.active)
(!r.failed.has(t) && s.has(t)) || (e.commands.removeLinkPreview({ url: t }), r.active.delete(t))
}, 600)
export const LinkPreview = e.create({
name: s,
group: "block",
atom: !0,
addStorage: () => ({ active: new Set(), failed: new Set() }),
addAttributes: () => ({
url: { default: null },
title: { default: null },
description: { default: null },
image: { default: null },
}),
parseHTML: () => [{ tag: s }],
renderHTML: ({ HTMLAttributes: e }) => [s, t(e)],
addCommands() {
return {
saveFile: (e, t) => () => (t && this.options.store.set(e, t), !0),
removeFile: (e) => () => (this.options.store.del(e), !0),
setLinkPreview:
({ url: e }) =>
({ state: t, dispatch: i }) => {
const { tr: n, schema: r, doc: a } = t,
o = r.nodes[s].create({ url: e }),
d = n.insert(a.content.size, o)
return (i && d.docChanged && i(d), !0)
},
removeLinkPreview:
({ url: e }) =>
({ state: t, dispatch: i }) => {
const { tr: n, doc: r } = t
let a = n,
o = !1
return (
r.descendants((t, i) => {
t.type.name === s &&
t.attrs.url === e &&
((a = a.delete(i, i + t.nodeSize)), (o = !0))
}),
i && o && i(a),
!0
)
},
}
},
addNodeView() {
return i(this.options.Component, { className: "inline-block" })
},
onUpdate({ editor: e }) {
this.options?.isFileSharingDisabled?.() ||
this.options?.isLinkSharingDisabled?.() ||
handleUpdate(e, this)
},
})