const INLINE_MEDIA_PATTERN = /!\[([^\]]*)\]\(swt-attachment:\/\/(\d+)\)/g; export const shangwutongInlineMediaIndexes = contentAttributes => { const indexes = contentAttributes?.swt?.inline_media; if (!Array.isArray(indexes)) return new Set(); return new Set( indexes.map(Number).filter(index => Number.isInteger(index) && index >= 0) ); }; const attachmentURL = attachment => attachment?.dataUrl ?? attachment?.data_url; const resolveAttachmentURL = dataUrl => { if (!dataUrl) return ''; try { return new URL( dataUrl, typeof window === 'undefined' ? 'http://localhost' : window.location.origin ).href; } catch { return dataUrl; } }; export const formatShangwutongInlineContent = ( content, attachments, contentAttributes ) => { const indexes = shangwutongInlineMediaIndexes(contentAttributes); if (!indexes.size) return content || ''; const renderedIndexes = new Set(); const formattedContent = (content || '').replace( INLINE_MEDIA_PATTERN, (match, alt, rawIndex) => { const index = Number(rawIndex); if (!indexes.has(index)) return match; renderedIndexes.add(index); const dataUrl = resolveAttachmentURL(attachmentURL(attachments?.[index])); if (!dataUrl) return alt || '商务通表情'; return `![${alt || '商务通表情'}](<${dataUrl}>)`; } ); const missingImages = [...indexes] .filter(index => !renderedIndexes.has(index)) .map(index => { const dataUrl = resolveAttachmentURL(attachmentURL(attachments?.[index])); return dataUrl ? `![商务通表情](<${dataUrl}>)` : '商务通表情'; }); if (!missingImages.length) return formattedContent; return [formattedContent, missingImages.join('')].filter(Boolean).join('\n'); };