We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
bug: MarkdownConverter not removing code blocks
The `MarkdownConverter` does not remove code blocks in the scenario I have at hand. The first thing that seems to happen is that the markdown gets converter to html and then the code looks for `<pre>` or `<code>` blocks. However, the html produced from our tutorials for example has code blocks as `<p>` ``` ... ``` `</p>`

I am able to fix this by adding the following line [here](https://github.com/deepset-ai/haystack/blob/d962bc0bc95ad1870e37b59f5aef4b6842b2df58/haystack/nodes/file_converter/markdown.py#L90):
`html = re.sub(r"<p>```(.*?)```</p>", " ", html, flags=re.DOTALL)
` 

If this is an ok fix, I'm happy to provide a PR

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `haystack/nodes/file_converter/markdown.py`
Content:
```
1 import logging
2 import re
3 from pathlib import Path
4 from typing import Dict, List, Optional, Tuple, Any
5 
6 try:
7     import frontmatter
8     from bs4 import BeautifulSoup, NavigableString
9     from markdown import markdown
10 except (ImportError, ModuleNotFoundError) as ie:
11     from haystack.utils.import_utils import _optional_component_not_installed
12 
13     _optional_component_not_installed(__name__, "preprocessing", ie)
14 
15 from haystack.nodes.file_converter.base import BaseConverter
16 from haystack.schema import Document
17 
18 
19 logger = logging.getLogger(__name__)
20 
21 
22 class MarkdownConverter(BaseConverter):
23     def __init__(
24         self,
25         remove_numeric_tables: bool = False,
26         valid_languages: Optional[List[str]] = None,
27         id_hash_keys: Optional[List[str]] = None,
28         progress_bar: bool = True,
29         remove_code_snippets: bool = True,
30         extract_headlines: bool = False,
31         add_frontmatter_to_meta: bool = False,
32     ):
33         """
34         :param remove_numeric_tables: Not applicable.
35         :param valid_languages: Not applicable.
36         :param id_hash_keys: Generate the document ID from a custom list of strings that refer to the document's
37             attributes. To make sure you don't have duplicate documents in your DocumentStore if texts are
38             not unique, you can modify the metadata and pass for example, `"meta"` to this field ([`"content"`, `"meta"`]).
39             In this case, the ID is generated by using the content and the defined metadata.
40         :param progress_bar: Show a progress bar for the conversion.
41         :param remove_code_snippets: Whether to remove snippets from the markdown file.
42         :param extract_headlines: Whether to extract headings from the markdown file.
43         :param add_frontmatter_to_meta: Whether to add the contents of the frontmatter to `meta`.
44         """
45         super().__init__(
46             remove_numeric_tables=remove_numeric_tables,
47             valid_languages=valid_languages,
48             id_hash_keys=id_hash_keys,
49             progress_bar=progress_bar,
50         )
51 
52         self.remove_code_snippets = remove_code_snippets
53         self.extract_headlines = extract_headlines
54         self.add_frontmatter_to_meta = add_frontmatter_to_meta
55 
56     def convert(
57         self,
58         file_path: Path,
59         meta: Optional[Dict[str, Any]] = None,
60         remove_numeric_tables: Optional[bool] = None,
61         valid_languages: Optional[List[str]] = None,
62         encoding: Optional[str] = "utf-8",
63         id_hash_keys: Optional[List[str]] = None,
64         remove_code_snippets: Optional[bool] = None,
65         extract_headlines: Optional[bool] = None,
66         add_frontmatter_to_meta: Optional[bool] = None,
67     ) -> List[Document]:
68         """
69         Reads text from a markdown file and executes optional preprocessing steps.
70 
71         :param file_path: path of the file to convert
72         :param meta: dictionary of meta data key-value pairs to append in the returned document.
73         :param encoding: Select the file encoding (default is `utf-8`)
74         :param remove_numeric_tables: Not applicable
75         :param valid_languages: Not applicable
76         :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's
77             attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are
78             not unique, you can modify the metadata and pass e.g. `"meta"` to this field (e.g. [`"content"`, `"meta"`]).
79             In this case the id will be generated by using the content and the defined metadata.
80         :param remove_code_snippets: Whether to remove snippets from the markdown file.
81         :param extract_headlines: Whether to extract headings from the markdown file.
82         :param add_frontmatter_to_meta: Whether to add the contents of the frontmatter to `meta`.
83         """
84 
85         id_hash_keys = id_hash_keys if id_hash_keys is not None else self.id_hash_keys
86         remove_code_snippets = remove_code_snippets if remove_code_snippets is not None else self.remove_code_snippets
87         extract_headlines = extract_headlines if extract_headlines is not None else self.extract_headlines
88         add_frontmatter_to_meta = (
89             add_frontmatter_to_meta if add_frontmatter_to_meta is not None else self.add_frontmatter_to_meta
90         )
91 
92         with open(file_path, encoding=encoding, errors="ignore") as f:
93             metadata, markdown_text = frontmatter.parse(f.read())
94 
95         # md -> html -> text since BeautifulSoup can extract text cleanly
96         html = markdown(markdown_text)
97 
98         # remove code snippets
99         if remove_code_snippets:
100             html = re.sub(r"<pre>(.*?)</pre>", " ", html, flags=re.DOTALL)
101             html = re.sub(r"<code>(.*?)</code>", " ", html, flags=re.DOTALL)
102         soup = BeautifulSoup(html, "html.parser")
103 
104         if add_frontmatter_to_meta:
105             if meta is None:
106                 meta = metadata
107             else:
108                 meta.update(metadata)
109 
110         if extract_headlines:
111             text, headlines = self._extract_text_and_headlines(soup)
112             if meta is None:
113                 meta = {}
114             meta["headlines"] = headlines
115         else:
116             text = soup.get_text()
117 
118         document = Document(content=text, meta=meta, id_hash_keys=id_hash_keys)
119         return [document]
120 
121     @staticmethod
122     def _extract_text_and_headlines(soup: BeautifulSoup) -> Tuple[str, List[Dict]]:
123         """
124         Extracts text and headings from a soup object.
125         """
126         headline_tags = {"h1", "h2", "h3", "h4", "h5", "h6"}
127         headlines = []
128         text = ""
129         for desc in soup.descendants:
130             if desc.name in headline_tags:
131                 current_headline = desc.get_text()
132                 current_start_idx = len(text)
133                 current_level = int(desc.name[-1]) - 1
134                 headlines.append({"headline": current_headline, "start_idx": current_start_idx, "level": current_level})
135 
136             if isinstance(desc, NavigableString):
137                 text += desc.get_text()
138 
139         return text, headlines
140
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/haystack/nodes/file_converter/markdown.py b/haystack/nodes/file_converter/markdown.py
--- a/haystack/nodes/file_converter/markdown.py
+++ b/haystack/nodes/file_converter/markdown.py
@@ -93,7 +93,7 @@
             metadata, markdown_text = frontmatter.parse(f.read())
 
         # md -> html -> text since BeautifulSoup can extract text cleanly
-        html = markdown(markdown_text)
+        html = markdown(markdown_text, extensions=["fenced_code"])
 
         # remove code snippets
         if remove_code_snippets:

{"golden_diff": "diff --git a/haystack/nodes/file_converter/markdown.py b/haystack/nodes/file_converter/markdown.py\n--- a/haystack/nodes/file_converter/markdown.py\n+++ b/haystack/nodes/file_converter/markdown.py\n@@ -93,7 +93,7 @@\n             metadata, markdown_text = frontmatter.parse(f.read())\n \n         # md -> html -> text since BeautifulSoup can extract text cleanly\n-        html = markdown(markdown_text)\n+        html = markdown(markdown_text, extensions=[\"fenced_code\"])\n \n         # remove code snippets\n         if remove_code_snippets:\n", "issue": "bug: MarkdownConverter not removing code blocks\nThe `MarkdownConverter` does not remove code blocks in the scenario I have at hand. The first thing that seems to happen is that the markdown gets converter to html and then the code looks for `<pre>` or `<code>` blocks. However, the html produced from our tutorials for example has code blocks as `<p>` ``` ... ``` `</p>`\r\n\r\nI am able to fix this by adding the following line [here](https://github.com/deepset-ai/haystack/blob/d962bc0bc95ad1870e37b59f5aef4b6842b2df58/haystack/nodes/file_converter/markdown.py#L90):\r\n`html = re.sub(r\"<p>```(.*?)```</p>\", \" \", html, flags=re.DOTALL)\r\n` \r\n\r\nIf this is an ok fix, I'm happy to provide a PR\n", "before_files": [{"content": "import logging\nimport re\nfrom pathlib import Path\nfrom typing import Dict, List, Optional, Tuple, Any\n\ntry:\n    import frontmatter\n    from bs4 import BeautifulSoup, NavigableString\n    from markdown import markdown\nexcept (ImportError, ModuleNotFoundError) as ie:\n    from haystack.utils.import_utils import _optional_component_not_installed\n\n    _optional_component_not_installed(__name__, \"preprocessing\", ie)\n\nfrom haystack.nodes.file_converter.base import BaseConverter\nfrom haystack.schema import Document\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass MarkdownConverter(BaseConverter):\n    def __init__(\n        self,\n        remove_numeric_tables: bool = False,\n        valid_languages: Optional[List[str]] = None,\n        id_hash_keys: Optional[List[str]] = None,\n        progress_bar: bool = True,\n        remove_code_snippets: bool = True,\n        extract_headlines: bool = False,\n        add_frontmatter_to_meta: bool = False,\n    ):\n        \"\"\"\n        :param remove_numeric_tables: Not applicable.\n        :param valid_languages: Not applicable.\n        :param id_hash_keys: Generate the document ID from a custom list of strings that refer to the document's\n            attributes. To make sure you don't have duplicate documents in your DocumentStore if texts are\n            not unique, you can modify the metadata and pass for example, `\"meta\"` to this field ([`\"content\"`, `\"meta\"`]).\n            In this case, the ID is generated by using the content and the defined metadata.\n        :param progress_bar: Show a progress bar for the conversion.\n        :param remove_code_snippets: Whether to remove snippets from the markdown file.\n        :param extract_headlines: Whether to extract headings from the markdown file.\n        :param add_frontmatter_to_meta: Whether to add the contents of the frontmatter to `meta`.\n        \"\"\"\n        super().__init__(\n            remove_numeric_tables=remove_numeric_tables,\n            valid_languages=valid_languages,\n            id_hash_keys=id_hash_keys,\n            progress_bar=progress_bar,\n        )\n\n        self.remove_code_snippets = remove_code_snippets\n        self.extract_headlines = extract_headlines\n        self.add_frontmatter_to_meta = add_frontmatter_to_meta\n\n    def convert(\n        self,\n        file_path: Path,\n        meta: Optional[Dict[str, Any]] = None,\n        remove_numeric_tables: Optional[bool] = None,\n        valid_languages: Optional[List[str]] = None,\n        encoding: Optional[str] = \"utf-8\",\n        id_hash_keys: Optional[List[str]] = None,\n        remove_code_snippets: Optional[bool] = None,\n        extract_headlines: Optional[bool] = None,\n        add_frontmatter_to_meta: Optional[bool] = None,\n    ) -> List[Document]:\n        \"\"\"\n        Reads text from a markdown file and executes optional preprocessing steps.\n\n        :param file_path: path of the file to convert\n        :param meta: dictionary of meta data key-value pairs to append in the returned document.\n        :param encoding: Select the file encoding (default is `utf-8`)\n        :param remove_numeric_tables: Not applicable\n        :param valid_languages: Not applicable\n        :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's\n            attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are\n            not unique, you can modify the metadata and pass e.g. `\"meta\"` to this field (e.g. [`\"content\"`, `\"meta\"`]).\n            In this case the id will be generated by using the content and the defined metadata.\n        :param remove_code_snippets: Whether to remove snippets from the markdown file.\n        :param extract_headlines: Whether to extract headings from the markdown file.\n        :param add_frontmatter_to_meta: Whether to add the contents of the frontmatter to `meta`.\n        \"\"\"\n\n        id_hash_keys = id_hash_keys if id_hash_keys is not None else self.id_hash_keys\n        remove_code_snippets = remove_code_snippets if remove_code_snippets is not None else self.remove_code_snippets\n        extract_headlines = extract_headlines if extract_headlines is not None else self.extract_headlines\n        add_frontmatter_to_meta = (\n            add_frontmatter_to_meta if add_frontmatter_to_meta is not None else self.add_frontmatter_to_meta\n        )\n\n        with open(file_path, encoding=encoding, errors=\"ignore\") as f:\n            metadata, markdown_text = frontmatter.parse(f.read())\n\n        # md -> html -> text since BeautifulSoup can extract text cleanly\n        html = markdown(markdown_text)\n\n        # remove code snippets\n        if remove_code_snippets:\n            html = re.sub(r\"<pre>(.*?)</pre>\", \" \", html, flags=re.DOTALL)\n            html = re.sub(r\"<code>(.*?)</code>\", \" \", html, flags=re.DOTALL)\n        soup = BeautifulSoup(html, \"html.parser\")\n\n        if add_frontmatter_to_meta:\n            if meta is None:\n                meta = metadata\n            else:\n                meta.update(metadata)\n\n        if extract_headlines:\n            text, headlines = self._extract_text_and_headlines(soup)\n            if meta is None:\n                meta = {}\n            meta[\"headlines\"] = headlines\n        else:\n            text = soup.get_text()\n\n        document = Document(content=text, meta=meta, id_hash_keys=id_hash_keys)\n        return [document]\n\n    @staticmethod\n    def _extract_text_and_headlines(soup: BeautifulSoup) -> Tuple[str, List[Dict]]:\n        \"\"\"\n        Extracts text and headings from a soup object.\n        \"\"\"\n        headline_tags = {\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"}\n        headlines = []\n        text = \"\"\n        for desc in soup.descendants:\n            if desc.name in headline_tags:\n                current_headline = desc.get_text()\n                current_start_idx = len(text)\n                current_level = int(desc.name[-1]) - 1\n                headlines.append({\"headline\": current_headline, \"start_idx\": current_start_idx, \"level\": current_level})\n\n            if isinstance(desc, NavigableString):\n                text += desc.get_text()\n\n        return text, headlines\n", "path": "haystack/nodes/file_converter/markdown.py"}], "after_files": [{"content": "import logging\nimport re\nfrom pathlib import Path\nfrom typing import Dict, List, Optional, Tuple, Any\n\ntry:\n    import frontmatter\n    from bs4 import BeautifulSoup, NavigableString\n    from markdown import markdown\nexcept (ImportError, ModuleNotFoundError) as ie:\n    from haystack.utils.import_utils import _optional_component_not_installed\n\n    _optional_component_not_installed(__name__, \"preprocessing\", ie)\n\nfrom haystack.nodes.file_converter.base import BaseConverter\nfrom haystack.schema import Document\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass MarkdownConverter(BaseConverter):\n    def __init__(\n        self,\n        remove_numeric_tables: bool = False,\n        valid_languages: Optional[List[str]] = None,\n        id_hash_keys: Optional[List[str]] = None,\n        progress_bar: bool = True,\n        remove_code_snippets: bool = True,\n        extract_headlines: bool = False,\n        add_frontmatter_to_meta: bool = False,\n    ):\n        \"\"\"\n        :param remove_numeric_tables: Not applicable.\n        :param valid_languages: Not applicable.\n        :param id_hash_keys: Generate the document ID from a custom list of strings that refer to the document's\n            attributes. To make sure you don't have duplicate documents in your DocumentStore if texts are\n            not unique, you can modify the metadata and pass for example, `\"meta\"` to this field ([`\"content\"`, `\"meta\"`]).\n            In this case, the ID is generated by using the content and the defined metadata.\n        :param progress_bar: Show a progress bar for the conversion.\n        :param remove_code_snippets: Whether to remove snippets from the markdown file.\n        :param extract_headlines: Whether to extract headings from the markdown file.\n        :param add_frontmatter_to_meta: Whether to add the contents of the frontmatter to `meta`.\n        \"\"\"\n        super().__init__(\n            remove_numeric_tables=remove_numeric_tables,\n            valid_languages=valid_languages,\n            id_hash_keys=id_hash_keys,\n            progress_bar=progress_bar,\n        )\n\n        self.remove_code_snippets = remove_code_snippets\n        self.extract_headlines = extract_headlines\n        self.add_frontmatter_to_meta = add_frontmatter_to_meta\n\n    def convert(\n        self,\n        file_path: Path,\n        meta: Optional[Dict[str, Any]] = None,\n        remove_numeric_tables: Optional[bool] = None,\n        valid_languages: Optional[List[str]] = None,\n        encoding: Optional[str] = \"utf-8\",\n        id_hash_keys: Optional[List[str]] = None,\n        remove_code_snippets: Optional[bool] = None,\n        extract_headlines: Optional[bool] = None,\n        add_frontmatter_to_meta: Optional[bool] = None,\n    ) -> List[Document]:\n        \"\"\"\n        Reads text from a markdown file and executes optional preprocessing steps.\n\n        :param file_path: path of the file to convert\n        :param meta: dictionary of meta data key-value pairs to append in the returned document.\n        :param encoding: Select the file encoding (default is `utf-8`)\n        :param remove_numeric_tables: Not applicable\n        :param valid_languages: Not applicable\n        :param id_hash_keys: Generate the document id from a custom list of strings that refer to the document's\n            attributes. If you want to ensure you don't have duplicate documents in your DocumentStore but texts are\n            not unique, you can modify the metadata and pass e.g. `\"meta\"` to this field (e.g. [`\"content\"`, `\"meta\"`]).\n            In this case the id will be generated by using the content and the defined metadata.\n        :param remove_code_snippets: Whether to remove snippets from the markdown file.\n        :param extract_headlines: Whether to extract headings from the markdown file.\n        :param add_frontmatter_to_meta: Whether to add the contents of the frontmatter to `meta`.\n        \"\"\"\n\n        id_hash_keys = id_hash_keys if id_hash_keys is not None else self.id_hash_keys\n        remove_code_snippets = remove_code_snippets if remove_code_snippets is not None else self.remove_code_snippets\n        extract_headlines = extract_headlines if extract_headlines is not None else self.extract_headlines\n        add_frontmatter_to_meta = (\n            add_frontmatter_to_meta if add_frontmatter_to_meta is not None else self.add_frontmatter_to_meta\n        )\n\n        with open(file_path, encoding=encoding, errors=\"ignore\") as f:\n            metadata, markdown_text = frontmatter.parse(f.read())\n\n        # md -> html -> text since BeautifulSoup can extract text cleanly\n        html = markdown(markdown_text, extensions=[\"fenced_code\"])\n\n        # remove code snippets\n        if remove_code_snippets:\n            html = re.sub(r\"<pre>(.*?)</pre>\", \" \", html, flags=re.DOTALL)\n            html = re.sub(r\"<code>(.*?)</code>\", \" \", html, flags=re.DOTALL)\n        soup = BeautifulSoup(html, \"html.parser\")\n\n        if add_frontmatter_to_meta:\n            if meta is None:\n                meta = metadata\n            else:\n                meta.update(metadata)\n\n        if extract_headlines:\n            text, headlines = self._extract_text_and_headlines(soup)\n            if meta is None:\n                meta = {}\n            meta[\"headlines\"] = headlines\n        else:\n            text = soup.get_text()\n\n        document = Document(content=text, meta=meta, id_hash_keys=id_hash_keys)\n        return [document]\n\n    @staticmethod\n    def _extract_text_and_headlines(soup: BeautifulSoup) -> Tuple[str, List[Dict]]:\n        \"\"\"\n        Extracts text and headings from a soup object.\n        \"\"\"\n        headline_tags = {\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"}\n        headlines = []\n        text = \"\"\n        for desc in soup.descendants:\n            if desc.name in headline_tags:\n                current_headline = desc.get_text()\n                current_start_idx = len(text)\n                current_level = int(desc.name[-1]) - 1\n                headlines.append({\"headline\": current_headline, \"start_idx\": current_start_idx, \"level\": current_level})\n\n            if isinstance(desc, NavigableString):\n                text += desc.get_text()\n\n        return text, headlines\n", "path": "haystack/nodes/file_converter/markdown.py"}]}