def _extract_pptx(self, file_contents: bytes) -> ExtractionResult:
        """Process PowerPoint file contents and convert to Markdown.

        This method handles the core logic of extracting content from a PowerPoint file.
        It processes:
        - Slide titles and content
        - Images (with alt text if available)
        - Tables (converted to HTML format)
        - Text frames
        - Slide notes

        Args:
            file_contents: Raw bytes of the PowerPoint file to process.

        Returns:
            ExtractionResult: Contains the extracted content in Markdown format,
                the MIME type, and any additional metadata.

        Notes:
            The extraction preserves the following elements:
            - Slide numbers (as HTML comments)
            - Images (converted to Markdown image syntax with alt text)
            - Tables (converted to HTML table syntax)
            - Text content (with titles properly formatted)
            - Slide notes (under a dedicated section for each slide)
        """
        md_content = ""
        presentation = pptx.Presentation(BytesIO(file_contents))

        for index, slide in enumerate(presentation.slides):
            md_content += f"\n\n<!-- Slide number: {index + 1} -->\n"

            title = None
            if hasattr(slide.shapes, "title"):
                title = slide.shapes.title

            for shape in slide.shapes:
                if not hasattr(shape, "shape_type"):
                    continue

                if shape.shape_type == MSO_SHAPE_TYPE.PICTURE or (
                    shape.shape_type == MSO_SHAPE_TYPE.PLACEHOLDER and hasattr(shape, "image")
                ):
                    alt_text = ""
                    with suppress(AttributeError):
                        alt_text = shape._element._nvXxPr.cNvPr.attrib.get("descr", "")  # noqa: SLF001

                    filename = re.sub(r"\W", "", shape.name) + ".jpg"
                    md_content += f"\n![{alt_text if alt_text else shape.name}]({filename})\n"

                elif shape.shape_type == MSO_SHAPE_TYPE.TABLE:
                    html_table = "<table>"
                    first_row = True

                    for row in shape.table.rows:
                        html_table += "<tr>"

                        for cell in row.cells:
                            tag = "th" if first_row else "td"
                            html_table += f"<{tag}>{escape(cell.text)}</{tag}>"

                        html_table += "</tr>"
                        first_row = False

                    html_table += "</table>"
                    md_content += "\n" + html_table + "\n"

                elif shape.has_text_frame:
                    md_content += "# " + shape.text.lstrip() + "\n" if shape == title else shape.text + "\n"

            md_content = md_content.strip()
            if slide.has_notes_slide:
                md_content += "\n\n### Notes:\n"
                notes_frame = slide.notes_slide.notes_text_frame

                if notes_frame is not None:  # pragma: no branch
                    md_content += notes_frame.text

                md_content = md_content.strip()

        return ExtractionResult(
            content=normalize_spaces(md_content),
            mime_type=MARKDOWN_MIME_TYPE,
            metadata=self._extract_presentation_metadata(presentation),
            chunks=[],
        )
Process PowerPoint file contents and convert to Markdown.

        This method handles the core logic of extracting content from a PowerPoint file.
        It processes:
        - Slide titles and content
        - Images (with alt text if available)
        - Tables (converted to HTML format)
        - Text frames
        - Slide notes

        Args:
            file_contents: Raw bytes of the PowerPoint file to process.

        Returns:
            ExtractionResult: Contains the extracted content in Markdown format,
                the MIME type, and any additional metadata.

        Notes:
            The extraction preserves the following elements:
            - Slide numbers (as HTML comments)
            - Images (converted to Markdown image syntax with alt text)
            - Tables (converted to HTML table syntax)
            - Text content (with titles properly formatted)
            - Slide notes (under a dedicated section for each slide)
        
kreuzberg/_extractors/_presentation.py