feat: Link Preview block (carte aperçu URL) + proxy images
Some checks failed
CI / Lint, Unit Tests & Build (push) Failing after 1m29s
CI / Deploy production (on server) (push) Has been skipped

- Bloc Link Preview : colle une URL → carte avec titre, description, image, favicon
- API /api/link-preview : extraction OpenGraph + meta tags
- API /api/image-proxy : contourne le hotlinking (Referer spoofing)
- Métadonnées persistées en HTML (data-preview JSON) — pas de refetch au reload
- Texte indexable : titre + description + URL inclus pour recherche/embeddings
- Modal propre pour saisir l'URL (plus de prompt())
- Slash menu + smart paste 'Coller comme carte aperçu'
- i18n FR/EN complet
- Fix: bouton calendrier retiré du sélecteur de vue
This commit is contained in:
Antigravity
2026-06-14 17:43:53 +00:00
parent 5246ed41e9
commit ba3ab3422a
10 changed files with 657 additions and 2 deletions

View File

@@ -3,7 +3,7 @@
import { useEffect, useRef } from 'react'
import { createPortal } from 'react-dom'
import { useLanguage } from '@/lib/i18n'
import { Link2, ImageIcon, Video, Code, FileText } from 'lucide-react'
import { Link2, ImageIcon, Video, Code, FileText, Layout } from 'lucide-react'
export type SmartPasteExtendedMenuProps = {
type: 'url' | 'code'
@@ -12,6 +12,7 @@ export type SmartPasteExtendedMenuProps = {
isImage?: boolean
isVideo?: boolean
onLink?: () => void
onLinkPreview?: () => void
onImage?: () => void
onVideo?: () => void
onCodeBlock?: () => void
@@ -26,6 +27,7 @@ export function SmartPasteExtendedMenu({
isImage,
isVideo,
onLink,
onLinkPreview,
onImage,
onVideo,
onCodeBlock,
@@ -90,6 +92,12 @@ export function SmartPasteExtendedMenu({
<Link2 size={15} className="text-blue-500" />
<span>{t('richTextEditor.smartPasteUrlLink') || 'Coller comme lien hypertexte'}</span>
</button>
{onLinkPreview && (
<button type="button" className="block-action-item" onClick={onLinkPreview}>
<Layout size={15} className="text-indigo-500" />
<span>{t('richTextEditor.smartPasteUrlPreview') || 'Coller comme carte aperçu'}</span>
</button>
)}
{isImage && onImage && (
<button type="button" className="block-action-item" onClick={onImage}>
<ImageIcon size={15} className="text-emerald-500" />