Parse markdown text and convert it to a message content format that supports images. Supports standard markdown image syntax: -  - image without alt text -  - image with alt text Example: Input: "**Example:**\n\n
| 57 | result: str = Field(description="The generated code") |
| 58 | |
| 59 | def parse_markdown_with_images(markdown_text: str) -> Union[str, list]: |
| 60 | """ |
| 61 | Parse markdown text and convert it to a message content format that supports images. |
| 62 | |
| 63 | Supports standard markdown image syntax: |
| 64 | -  - image without alt text |
| 65 | -  - image with alt text |
| 66 | |
| 67 | Example: |
| 68 | Input: "**Example:**\n\n\n\nText after" |
| 69 | Output: [ |
| 70 | ContentPartText(text="**Example:**\n\n"), |
| 71 | ContentPartImage(image_url=ImageURL(url="https://example.com/image.jpg", ...)), |
| 72 | ContentPartText(text="\n\nText after") |
| 73 | ] |
| 74 | |
| 75 | Args: |
| 76 | markdown_text: The markdown text that may contain image references like  |
| 77 | |
| 78 | Returns: |
| 79 | If no images found: returns the original string |
| 80 | If images found: returns a list of ContentPartText and ContentPartImage objects |
| 81 | """ |
| 82 | # Pattern to match markdown image syntax:  or  |
| 83 | # Matches:  |
| 84 | image_pattern = r'!\[([^\]]*)\]\(([^)]+)\)' |
| 85 | |
| 86 | # Find all image matches with their positions |
| 87 | matches = list(re.finditer(image_pattern, markdown_text)) |
| 88 | |
| 89 | if not matches: |
| 90 | # No images found, return as plain string |
| 91 | return markdown_text |
| 92 | |
| 93 | # Build content list with text and image parts |
| 94 | content_parts = [] |
| 95 | last_end = 0 |
| 96 | |
| 97 | for match in matches: |
| 98 | # Add text before the image (including whitespace) |
| 99 | text_before = markdown_text[last_end:match.start()] |
| 100 | # Only add non-empty text parts (preserve whitespace if it's meaningful) |
| 101 | if text_before: |
| 102 | content_parts.append(ContentPartText(text=text_before)) |
| 103 | |
| 104 | # Extract image URL (group 2 is the URL in parentheses) |
| 105 | image_url = match.group(2) |
| 106 | |
| 107 | # Determine media type from URL extension (handle URLs with query parameters) |
| 108 | media_type = 'image/png' # default fallback |
| 109 | # Extract path before query parameters (e.g., "image.jpg?v=1" -> "image.jpg") |
| 110 | url_path = image_url.split('?')[0].lower() |
| 111 | if url_path.endswith('.jpg') or url_path.endswith('.jpeg'): |
| 112 | media_type = 'image/jpeg' |
| 113 | elif url_path.endswith('.png'): |
| 114 | media_type = 'image/png' |
| 115 | elif url_path.endswith('.gif'): |
| 116 | media_type = 'image/gif' |
no test coverage detected