(value: string)
| 21 | }; |
| 22 | |
| 23 | const inlineMarkdownToHtml = (value: string): string => { |
| 24 | let result = escapeHtml(value); |
| 25 | |
| 26 | result = result.replace( |
| 27 | /!\[([^\]]*)\]\(([^)]+)\)/g, |
| 28 | (_, alt: string, url: string) => { |
| 29 | const src = escapeAttribute(url); |
| 30 | if (isVideoUrl(url)) { |
| 31 | const type = getVideoMimeType(url); |
| 32 | const source = `<source src="${src}"${ |
| 33 | type ? ` type="${type}"` : '' |
| 34 | } />`; |
| 35 | return `<video src="${src}" controls preload="metadata" aria-label="${alt}">${source}</video>`; |
| 36 | } |
| 37 | return `<img src="${src}" alt="${alt}" />`; |
| 38 | }, |
| 39 | ); |
| 40 | |
| 41 | result = result.replace( |
| 42 | /\[([^\]]+)\]\(([^)]+)\)/g, |
| 43 | (_, label: string, url: string) => |
| 44 | `<a href="${escapeAttribute(url)}">${label}</a>`, |
| 45 | ); |
| 46 | |
| 47 | return result |
| 48 | .split(/(<[^>]+>)/g) |
| 49 | .map((part) => |
| 50 | part.startsWith('<') ? part : applyInlineTextFormatting(part), |
| 51 | ) |
| 52 | .join(''); |
| 53 | }; |
| 54 | |
| 55 | /** |
| 56 | * Converts markdown to HTML using basic markdown syntax. |
no test coverage detected