diff --git a/web-next/components/ForumEditor.tsx b/web-next/components/ForumEditor.tsx index c276afb..f96d6ae 100644 --- a/web-next/components/ForumEditor.tsx +++ b/web-next/components/ForumEditor.tsx @@ -1,6 +1,8 @@ 'use client' import { Editor } from '@tinymce/tinymce-react' +import { useLocale } from 'next-intl' +import { wowheadUrl, wowheadData, type WowheadType } from '@/lib/wowhead' /** * Editor TinyMCE del foro (community, self-hosted desde /tinymce — ver @@ -12,7 +14,25 @@ import { Editor } from '@tinymce/tinymce-react' * `licenseKey: 'gpl'` deja claro que es la edición community (GPL), no la de nube. * El HTML que produce se sanea SIEMPRE en el servidor con nh3 (lib/forum-sanitize), * nunca se confía en el cliente. + * + * Botón «Wowhead»: abre un diálogo (tipo + ID + texto) e inserta un enlace de + * wowhead con su data-wowhead en el idioma de la web, para que salga el tooltip, + * el color por calidad y el icono (lo pinta el script global tooltips.js). */ + +const WOWHEAD_TYPES: { value: WowheadType; es: string; en: string }[] = [ + { value: 'item', es: 'Ítem', en: 'Item' }, + { value: 'spell', es: 'Hechizo', en: 'Spell' }, + { value: 'quest', es: 'Misión', en: 'Quest' }, + { value: 'npc', es: 'PNJ', en: 'NPC' }, + { value: 'achievement', es: 'Logro', en: 'Achievement' }, + { value: 'object', es: 'Objeto', en: 'Object' }, +] + +function esc(s: string): string { + return s.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"') +} + export function ForumEditor({ value, onChange, @@ -22,6 +42,18 @@ export function ForumEditor({ onChange: (html: string) => void height?: number }) { + const locale = useLocale() + const es = locale !== 'en' + const L = { + title: 'Wowhead', + tooltip: es ? 'Insertar enlace de Wowhead' : 'Insert a Wowhead link', + type: es ? 'Tipo' : 'Type', + id: 'ID', + text: es ? 'Texto (opcional)' : 'Text (optional)', + insert: es ? 'Insertar' : 'Insert', + cancel: es ? 'Cancelar' : 'Cancel', + } + return ( { + editor.ui.registry.addButton('wowhead', { + text: 'Wowhead', + tooltip: L.tooltip, + onAction: () => { + editor.windowManager.open({ + title: L.title, + body: { + type: 'panel', + items: [ + { + type: 'listbox', + name: 'wtype', + label: L.type, + items: WOWHEAD_TYPES.map((t) => ({ value: t.value, text: es ? t.es : t.en })), + }, + { type: 'input', name: 'wid', label: L.id }, + { type: 'input', name: 'wtext', label: L.text }, + ], + }, + initialData: { wtype: 'item', wid: '', wtext: '' }, + buttons: [ + { type: 'cancel', text: L.cancel }, + { type: 'submit', text: L.insert, primary: true }, + ], + onSubmit: (api) => { + const data = api.getData() as { wtype: WowheadType; wid: string; wtext: string } + const id = String(data.wid).trim().replace(/\D/g, '') + if (!id) { + api.close() + return + } + const type = (data.wtype || 'item') as WowheadType + const label = data.wtext.trim() || `${type}=${id}` + const href = wowheadUrl(type, id, locale) + const wh = wowheadData(type, id, locale) + editor.insertContent( + `${esc(label)} `, + ) + api.close() + }, + }) + }, + }) + }, }} /> )