@@ -20,6 +20,9 @@ import LiveMessage from '../Announcer/LiveMessage';
2020/* @conditional -compile-remove(mention) */
2121import { defaultOnMentionRender } from './MentionRenderer' ;
2222import DOMPurify from 'dompurify' ;
23+ import { _AttachmentDownloadCardsStrings } from '../AttachmentDownloadCards' ;
24+ /* @conditional -compile-remove(attachment-download) */
25+ import { AttachmentMetadata } from '../../types' ;
2326
2427type ChatMessageContentProps = {
2528 message : ChatMessage ;
@@ -164,9 +167,12 @@ export const BlockedMessageContent = (props: BlockedMessageContentProps): JSX.El
164167} ;
165168
166169const extractContentForAllyMessage = ( props : ChatMessageContentProps ) : string => {
167- if ( props . message . content ) {
170+ let attachments = undefined ;
171+ /* @conditional -compile-remove(attachment-download) */
172+ attachments = props . message . attachments ;
173+ if ( props . message . content || attachments ) {
168174 // Replace all <img> tags with 'image' for aria.
169- const parsedContent = DOMPurify . sanitize ( props . message . content , {
175+ const parsedContent = DOMPurify . sanitize ( props . message . content ?? '' , {
170176 ALLOWED_TAGS : [ 'img' ] ,
171177 RETURN_DOM_FRAGMENT : true
172178 } ) ;
@@ -180,6 +186,16 @@ const extractContentForAllyMessage = (props: ChatMessageContentProps): string =>
180186 parsedContent . replaceChild ( imageTextNode , child ) ;
181187 } ) ;
182188
189+ // Inject attachment names for aria.
190+ if ( attachments ) {
191+ let attachmentList = '' ;
192+ /* @conditional -compile-remove(attachment-download) */
193+ attachmentList = attachmentCardGroupDescription ( props ) ;
194+ const attachmentTextNode = document . createElement ( 'div' ) ;
195+ attachmentTextNode . innerHTML = ` ${ attachmentList } ` ;
196+ parsedContent . appendChild ( attachmentTextNode ) ;
197+ }
198+
183199 // Strip all html tags from the content for aria.
184200 const message = DOMPurify . sanitize ( parsedContent , { ALLOWED_TAGS : [ ] } ) ;
185201 return message ;
@@ -207,6 +223,29 @@ const messageContentAriaText = (props: ChatMessageContentProps): string | undefi
207223 } ) ;
208224} ;
209225
226+ /* @conditional -compile-remove(attachment-download) */
227+ const attachmentCardGroupDescription = ( props : ChatMessageContentProps ) : string => {
228+ const attachments = props . message . attachments ;
229+ return getAttachmentCountLiveMessage ( attachments ?? [ ] , props . strings . attachmentCardGroupMessage ) ;
230+ } ;
231+
232+ /* @conditional -compile-remove(attachment-download) */
233+ /**
234+ * @private
235+ */
236+ export const getAttachmentCountLiveMessage = (
237+ attachments : AttachmentMetadata [ ] ,
238+ attachmentCardGroupMessage : string
239+ ) : string => {
240+ if ( attachments . length === 0 ) {
241+ return '' ;
242+ }
243+ return _formatString ( attachmentCardGroupMessage , {
244+ attachmentCount : `${ attachments . length } `
245+ } ) ;
246+ return '' ;
247+ } ;
248+
210249const defaultOnRenderInlineImage = ( inlineImage : InlineImage ) : JSX . Element => {
211250 return (
212251 < img
0 commit comments