import { wowheadUrl, wowheadData, type WowheadType } from './wowhead' import { fetchWowheadInfo } from './wowhead-resolve' // Localiza los enlaces de wowhead de un post al idioma de QUIEN LO LEE (no de quien // lo posteó). Los enlaces se guardan con el locale del autor (subdominio, domain y // nombre); aquí, al renderizar el tema, se reescriben al locale del lector: se ajusta // el subdominio y el domain del tooltip, y se vuelve a resolver el nombre en su idioma. // No toca lo guardado: es solo de presentación. const ANCHOR_RE = /]*)>([\s\S]*?)<\/a>/gi const ENTITY_RE = /(item|spell|quest|npc|achievement|object)=(\d+)/i function attr(attrs: string, name: string): string | undefined { return new RegExp(`${name}="([^"]*)"`, 'i').exec(attrs)?.[1] } function escAttr(s: string): string { return s.replace(/&/g, '&').replace(/"/g, '"') } function escHtml(s: string): string { return s.replace(/&/g, '&').replace(//g, '>') } /** Extrae type=id de un enlace de wowhead (de data-wowhead o del href). */ function entityOf(attrs: string): { type: WowheadType; id: string } | null { if (!/wowhead\.com/i.test(attrs) && !/data-wowhead=/i.test(attrs)) return null const src = attr(attrs, 'data-wowhead') || attr(attrs, 'href') || '' const m = ENTITY_RE.exec(src) return m ? { type: m[1].toLowerCase() as WowheadType, id: m[2] } : null } export async function localizeWowheadLinks(html: string, locale: string): Promise { if (!html || (!/wowhead\.com/i.test(html) && !/data-wowhead/i.test(html))) return html // 1) recopila las entidades únicas y resuelve su nombre en el locale del lector const entities = new Map() for (const m of html.matchAll(ANCHOR_RE)) { const e = entityOf(m[1]) if (e) entities.set(`${e.type}=${e.id}`, e) } if (entities.size === 0) return html const names = new Map() await Promise.all( [...entities.values()].map(async (e) => { const info = await fetchWowheadInfo(e.type, e.id, locale) if (info?.name) names.set(`${e.type}=${e.id}`, info.name) }), ) // 2) reescribe cada enlace de wowhead al locale del lector return html.replace(ANCHOR_RE, (full, attrs: string, inner: string) => { const e = entityOf(attrs) if (!e) return full const key = `${e.type}=${e.id}` const href = wowheadUrl(e.type, e.id, locale) const wh = wowheadData(e.type, e.id, locale) const name = names.get(key) || inner // si no resuelve, se conserva el texto guardado return `${escHtml(name)}` }) }