From 66b920a4abf80cef37e3c5498510ced426ef9e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Tue, 6 Aug 2024 13:00:30 +0530 Subject: [PATCH 01/15] Create pyparser.py --- pyparser.py | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 pyparser.py diff --git a/pyparser.py b/pyparser.py new file mode 100644 index 0000000..003e42e --- /dev/null +++ b/pyparser.py @@ -0,0 +1,83 @@ +import os +import json +import re + +class MarkdownParsingError(Exception): + pass + +def parse_markdown_to_json(markdown_text): + task = { + "name": "", + "description": "", + "modality": "", + "diagram": None, + "citations": None, + "examples": [], + "tags": [] + } + + # Helper function to extract content between headers + def extract_section(start_pattern, end_pattern=None): + if end_pattern: + match = re.search(f"{start_pattern}(.*?){end_pattern}", markdown_text, re.DOTALL) + else: + match = re.search(f"{start_pattern}(.*?)$", markdown_text, re.DOTALL) + if match: + return match.group(1).strip() + return None + + # Extract name (required) + name_match = re.search(r'^#\s+(.+)$', markdown_text, re.MULTILINE) + if not name_match: + raise MarkdownParsingError("Task name not found. Expected '# Task Name' at the start.") + task["name"] = name_match.group(1).strip() + + # Extract description (required) + description = extract_section(r'## Description:', r'##') + if not description: + raise MarkdownParsingError("Description section not found or empty.") + task["description"] = description + + # Extract modality (required) + modality = extract_section(r'## Modality:', r'##') + if not modality: + raise MarkdownParsingError("Modality section not found or empty.") + task["modality"] = modality + + # Extract diagram (optional) + diagram = extract_section(r'## Diagram \(Optional\):', r'##') + task["diagram"] = diagram + + # Extract citations (optional) + citations = extract_section(r'## Citations \(Optional\):', r'##') + if citations: + task["citations"] = [citation.strip()[2:] for citation in citations.split('\n') if citation.strip().startswith('-')] + + # Extract examples (required) + examples_text = extract_section(r'## Examples:', r'## Tags:') + if not examples_text: + raise MarkdownParsingError("Examples section not found or empty.") + + examples = re.split(r'###\s+Example\s+\d+:', examples_text) + if len(examples) < 2: # First split is empty, so we need at least 2 elements + raise MarkdownParsingError("No examples found. Expected at least one '### Example X:' section.") + + for example in examples[1:]: # Skip the first split as it's empty + input_match = re.search(r'Input:\s*```(.+?)```', example, re.DOTALL) + output_match = re.search(r'Output:\s*```(.+?)```', example, re.DOTALL) + if not input_match or not output_match: + raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") + task["examples"].append([{ + "input": input_match.group(1).strip(), + "output": output_match.group(1).strip() + }]) + + # Extract tags (required) + tags_text = extract_section(r'## Tags:') + if not tags_text: + raise MarkdownParsingError("Tags section not found or empty.") + task["tags"] = [tag.strip()[2:] for tag in tags_text.split('\n') if tag.strip().startswith('-')] + if not task["tags"]: + raise MarkdownParsingError("No tags found. Expected at least one tag starting with '-'.") + + return task From 0542d5f61895e5e2169ff012e19136aa1c9aed52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Tue, 6 Aug 2024 13:04:19 +0530 Subject: [PATCH 02/15] Create validate.py --- validate.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 validate.py diff --git a/validate.py b/validate.py new file mode 100644 index 0000000..0ebf062 --- /dev/null +++ b/validate.py @@ -0,0 +1,53 @@ +# This file check all the .md files from task folder and convert them into json (with proper error check and formatting) and put them in task-json folder. +import os +import json +import re +from parser import parse_markdown_to_json # Importing the parsing function from a separate file + +def process_tasks(tasks_folder, json_folder): + # Create the JSON folder if it doesn't exist + os.makedirs(json_folder, exist_ok=True) + + # Get a list of all markdown files in the tasks folder + md_files = [f for f in os.listdir(tasks_folder) if f.endswith('.md')] + + for md_file in md_files: + # Construct full paths for markdown and json files + md_path = os.path.join(tasks_folder, md_file) + json_file = md_file.replace('.md', '.json') + json_path = os.path.join(json_folder, json_file) + + # Check if JSON file needs to be created or updated + if not os.path.exists(json_path) or os.path.getmtime(md_path) > os.path.getmtime(json_path): + print(f"Processing {md_file}...") + + try: + # Read the markdown file + with open(md_path, 'r', encoding='utf-8') as md_file: + markdown_content = md_file.read() + + # Parse markdown to JSON + json_content = parse_markdown_to_json(markdown_content) + + # Write the JSON content to file + with open(json_path, 'w', encoding='utf-8') as json_file: + json.dump(json_content, json_file, indent=2, ensure_ascii=False) + + print(f"Successfully converted and saved {json_file}") + except MarkdownParsingError as e: + # Handle specific markdown parsing errors + print(f"Error processing {md_file}: {str(e)}") + except Exception as e: + # Handle any other unexpected errors + print(f"Unexpected error processing {md_file}: {str(e)}") + else: + # Skip processing if JSON file is up to date + print(f"Skipping {md_file} - JSON file already up to date") + +if __name__ == "__main__": + # Define folder paths + tasks_folder = "tasks" + json_folder = "tasks-json" + + # Run the main processing function + process_tasks(tasks_folder, json_folder) From bd2e56ca42b59881c65b4153ad007c6aef847ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Wed, 7 Aug 2024 08:18:25 +0530 Subject: [PATCH 03/15] Update pyparser.py --- pyparser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyparser.py b/pyparser.py index 003e42e..37320f5 100644 --- a/pyparser.py +++ b/pyparser.py @@ -69,7 +69,7 @@ def extract_section(start_pattern, end_pattern=None): raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") task["examples"].append([{ "input": input_match.group(1).strip(), - "output": output_match.group(1).strip() + "output": "output": output_match.group(1).strip().replace('\n', '\r\n') }]) # Extract tags (required) From 54beead67cd27d73fe7486dcd2f7b72f4da13022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Wed, 7 Aug 2024 08:21:05 +0530 Subject: [PATCH 04/15] Update and rename validate.py to markdown_to_json.py --- validate.py => markdown_to_json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename validate.py => markdown_to_json.py (95%) diff --git a/validate.py b/markdown_to_json.py similarity index 95% rename from validate.py rename to markdown_to_json.py index 0ebf062..eb92443 100644 --- a/validate.py +++ b/markdown_to_json.py @@ -2,7 +2,7 @@ import os import json import re -from parser import parse_markdown_to_json # Importing the parsing function from a separate file +from parser import * def process_tasks(tasks_folder, json_folder): # Create the JSON folder if it doesn't exist From 532c4f174ad7feb37f03f3ab74104f0aae69f383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Wed, 7 Aug 2024 08:44:39 +0530 Subject: [PATCH 05/15] Update markdown_to_json.py --- markdown_to_json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdown_to_json.py b/markdown_to_json.py index eb92443..3ec642f 100644 --- a/markdown_to_json.py +++ b/markdown_to_json.py @@ -2,7 +2,7 @@ import os import json import re -from parser import * +from pyparser import * def process_tasks(tasks_folder, json_folder): # Create the JSON folder if it doesn't exist From 53507ed4d84063ad5f07b277a54de2722e362318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Wed, 7 Aug 2024 08:45:44 +0530 Subject: [PATCH 06/15] Update pyparser.py --- pyparser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyparser.py b/pyparser.py index 37320f5..9b92342 100644 --- a/pyparser.py +++ b/pyparser.py @@ -69,7 +69,7 @@ def extract_section(start_pattern, end_pattern=None): raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") task["examples"].append([{ "input": input_match.group(1).strip(), - "output": "output": output_match.group(1).strip().replace('\n', '\r\n') + "output": output_match.group(1).strip().replace('\n', '\r\n') }]) # Extract tags (required) From e812faf11c18efab2a2a37c3a31cce292b411a3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Wed, 7 Aug 2024 08:52:51 +0530 Subject: [PATCH 07/15] Update pyparser.py --- pyparser.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/pyparser.py b/pyparser.py index 9b92342..8f3350a 100644 --- a/pyparser.py +++ b/pyparser.py @@ -6,6 +6,9 @@ class MarkdownParsingError(Exception): pass def parse_markdown_to_json(markdown_text): + + line_ending = '\r\n' if '\r\n' in markdown_text else '\n' + task = { "name": "", "description": "", @@ -18,6 +21,7 @@ def parse_markdown_to_json(markdown_text): # Helper function to extract content between headers def extract_section(start_pattern, end_pattern=None): + if end_pattern: match = re.search(f"{start_pattern}(.*?){end_pattern}", markdown_text, re.DOTALL) else: @@ -63,14 +67,15 @@ def extract_section(start_pattern, end_pattern=None): raise MarkdownParsingError("No examples found. Expected at least one '### Example X:' section.") for example in examples[1:]: # Skip the first split as it's empty - input_match = re.search(r'Input:\s*```(.+?)```', example, re.DOTALL) - output_match = re.search(r'Output:\s*```(.+?)```', example, re.DOTALL) - if not input_match or not output_match: - raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") - task["examples"].append([{ - "input": input_match.group(1).strip(), - "output": output_match.group(1).strip().replace('\n', '\r\n') - }]) + input_match = re.search(r'Input:\s*```(.+?)```', example, re.DOTALL) + output_match = re.search(r'Output:\s*```(.+?)```', example, re.DOTALL) + if not input_match or not output_match: + raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") + task["examples"].append({ + "input": input_match.group(1).strip(), + "output": output_match.group(1).strip().replace('\n', line_ending) + }) + # Extract tags (required) tags_text = extract_section(r'## Tags:') From 38ea6420e3b4d8015cda484af51eb854c197f37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Wed, 7 Aug 2024 09:14:20 +0530 Subject: [PATCH 08/15] Update pyparser.py --- pyparser.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyparser.py b/pyparser.py index 8f3350a..c9ef1f6 100644 --- a/pyparser.py +++ b/pyparser.py @@ -67,14 +67,14 @@ def extract_section(start_pattern, end_pattern=None): raise MarkdownParsingError("No examples found. Expected at least one '### Example X:' section.") for example in examples[1:]: # Skip the first split as it's empty - input_match = re.search(r'Input:\s*```(.+?)```', example, re.DOTALL) - output_match = re.search(r'Output:\s*```(.+?)```', example, re.DOTALL) - if not input_match or not output_match: - raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") - task["examples"].append({ - "input": input_match.group(1).strip(), - "output": output_match.group(1).strip().replace('\n', line_ending) - }) + input_match = re.search(r'Input:\s*```(.+?)```', example, re.DOTALL) + output_match = re.search(r'Output:\s*```(.+?)```', example, re.DOTALL) + if not input_match or not output_match: + raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") + task["examples"].append([{ + "input": input_match.group(1).strip(), + "output": output_match.group(1).strip().replace('\n', line_ending) + }]) # Extract tags (required) From 6c3ad602a92f47ec16b24e9faa83e986477fe6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Wed, 7 Aug 2024 09:16:45 +0530 Subject: [PATCH 09/15] Update pyparser.py --- pyparser.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyparser.py b/pyparser.py index c9ef1f6..18559e2 100644 --- a/pyparser.py +++ b/pyparser.py @@ -72,11 +72,13 @@ def extract_section(start_pattern, end_pattern=None): if not input_match or not output_match: raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") task["examples"].append([{ - "input": input_match.group(1).strip(), - "output": output_match.group(1).strip().replace('\n', line_ending) + "input": input_match.group(1).strip(), + "output": output_match.group(1).strip() # Remove the .replace('\n', line_ending) }]) + + # Extract tags (required) tags_text = extract_section(r'## Tags:') if not tags_text: From 7ccc27363dc19aa979c14688c4ca3f4a0519eb6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Wed, 7 Aug 2024 09:17:36 +0530 Subject: [PATCH 10/15] Update markdown_to_json.py --- markdown_to_json.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/markdown_to_json.py b/markdown_to_json.py index 3ec642f..92f1e88 100644 --- a/markdown_to_json.py +++ b/markdown_to_json.py @@ -31,7 +31,10 @@ def process_tasks(tasks_folder, json_folder): # Write the JSON content to file with open(json_path, 'w', encoding='utf-8') as json_file: - json.dump(json_content, json_file, indent=2, ensure_ascii=False) + json.dump(json_content, json_file, indent=2, ensure_ascii=False, separators=(',', ': '), sort_keys=True) + json_file.write('\n') # Add a final newline + + print(f"Successfully converted and saved {json_file}") except MarkdownParsingError as e: From b7799c9a05629c2cd1a2380f6c8271c7749fc281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Wed, 7 Aug 2024 09:19:41 +0530 Subject: [PATCH 11/15] Update markdown_to_json.py --- markdown_to_json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdown_to_json.py b/markdown_to_json.py index 92f1e88..f660956 100644 --- a/markdown_to_json.py +++ b/markdown_to_json.py @@ -31,7 +31,7 @@ def process_tasks(tasks_folder, json_folder): # Write the JSON content to file with open(json_path, 'w', encoding='utf-8') as json_file: - json.dump(json_content, json_file, indent=2, ensure_ascii=False, separators=(',', ': '), sort_keys=True) + json.dump(json_content, json_file, indent=2, ensure_ascii=False, separators=(',', ': ')) json_file.write('\n') # Add a final newline From 54581db00943ce4275e46b5bd6041e0f45309524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Sat, 10 Aug 2024 12:05:47 +0530 Subject: [PATCH 12/15] Update pyparser.py --- pyparser.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/pyparser.py b/pyparser.py index 18559e2..5a3827c 100644 --- a/pyparser.py +++ b/pyparser.py @@ -67,18 +67,16 @@ def extract_section(start_pattern, end_pattern=None): raise MarkdownParsingError("No examples found. Expected at least one '### Example X:' section.") for example in examples[1:]: # Skip the first split as it's empty - input_match = re.search(r'Input:\s*```(.+?)```', example, re.DOTALL) - output_match = re.search(r'Output:\s*```(.+?)```', example, re.DOTALL) + input_match = re.search(r'Input:\s*(.+?)Output:', example, re.DOTALL) + output_match = re.search(r'Output:\s*(.+?)$', example, re.DOTALL) if not input_match or not output_match: raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") - task["examples"].append([{ - "input": input_match.group(1).strip(), - "output": output_match.group(1).strip() # Remove the .replace('\n', line_ending) - }]) + task["examples"].append({ + "input": input_match.group(1).replace('\`\`\`', '').strip(), + "output": output_match.group(1).replace('\`\`\`', '').strip() # Remove the .replace('\n', line_ending) + }) - - # Extract tags (required) tags_text = extract_section(r'## Tags:') if not tags_text: From 45b097eba833c4f3c6023758bdf2648602ec84ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Sat, 10 Aug 2024 12:07:20 +0530 Subject: [PATCH 13/15] Update pyparser.py --- pyparser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyparser.py b/pyparser.py index 5a3827c..e907433 100644 --- a/pyparser.py +++ b/pyparser.py @@ -71,10 +71,10 @@ def extract_section(start_pattern, end_pattern=None): output_match = re.search(r'Output:\s*(.+?)$', example, re.DOTALL) if not input_match or not output_match: raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") - task["examples"].append({ + task["examples"].append([{ "input": input_match.group(1).replace('\`\`\`', '').strip(), "output": output_match.group(1).replace('\`\`\`', '').strip() # Remove the .replace('\n', line_ending) - }) + }]) # Extract tags (required) From 9b87592cd599861c59109a42acd5da445b682ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Sun, 11 Aug 2024 15:15:00 +0530 Subject: [PATCH 14/15] Update markdown_to_json.py --- markdown_to_json.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/markdown_to_json.py b/markdown_to_json.py index f660956..859bff0 100644 --- a/markdown_to_json.py +++ b/markdown_to_json.py @@ -7,35 +7,33 @@ def process_tasks(tasks_folder, json_folder): # Create the JSON folder if it doesn't exist os.makedirs(json_folder, exist_ok=True) - + # Get a list of all markdown files in the tasks folder md_files = [f for f in os.listdir(tasks_folder) if f.endswith('.md')] - + for md_file in md_files: # Construct full paths for markdown and json files md_path = os.path.join(tasks_folder, md_file) json_file = md_file.replace('.md', '.json') json_path = os.path.join(json_folder, json_file) - + # Check if JSON file needs to be created or updated if not os.path.exists(json_path) or os.path.getmtime(md_path) > os.path.getmtime(json_path): print(f"Processing {md_file}...") - + try: # Read the markdown file with open(md_path, 'r', encoding='utf-8') as md_file: markdown_content = md_file.read() - + # Parse markdown to JSON json_content = parse_markdown_to_json(markdown_content) - + # Write the JSON content to file - with open(json_path, 'w', encoding='utf-8') as json_file: - json.dump(json_content, json_file, indent=2, ensure_ascii=False, separators=(',', ': ')) + with open(json_path, 'w', encoding='utf-8', newline='\n') as json_file: + json.dump(json_content, json_file, indent=2, ensure_ascii=False) json_file.write('\n') # Add a final newline - - print(f"Successfully converted and saved {json_file}") except MarkdownParsingError as e: # Handle specific markdown parsing errors @@ -51,6 +49,6 @@ def process_tasks(tasks_folder, json_folder): # Define folder paths tasks_folder = "tasks" json_folder = "tasks-json" - + # Run the main processing function process_tasks(tasks_folder, json_folder) From 682491fac6d917d25c994e85d04d71b5abfff30e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aaditya=20Ura=20=28looking=20for=20PhD=20Fall=E2=80=9924?= =?UTF-8?q?=29?= Date: Sun, 11 Aug 2024 15:15:26 +0530 Subject: [PATCH 15/15] Update pyparser.py --- pyparser.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/pyparser.py b/pyparser.py index e907433..770c6f7 100644 --- a/pyparser.py +++ b/pyparser.py @@ -6,9 +6,6 @@ class MarkdownParsingError(Exception): pass def parse_markdown_to_json(markdown_text): - - line_ending = '\r\n' if '\r\n' in markdown_text else '\n' - task = { "name": "", "description": "", @@ -21,7 +18,6 @@ def parse_markdown_to_json(markdown_text): # Helper function to extract content between headers def extract_section(start_pattern, end_pattern=None): - if end_pattern: match = re.search(f"{start_pattern}(.*?){end_pattern}", markdown_text, re.DOTALL) else: @@ -61,22 +57,21 @@ def extract_section(start_pattern, end_pattern=None): examples_text = extract_section(r'## Examples:', r'## Tags:') if not examples_text: raise MarkdownParsingError("Examples section not found or empty.") - + examples = re.split(r'###\s+Example\s+\d+:', examples_text) if len(examples) < 2: # First split is empty, so we need at least 2 elements raise MarkdownParsingError("No examples found. Expected at least one '### Example X:' section.") - + for example in examples[1:]: # Skip the first split as it's empty - input_match = re.search(r'Input:\s*(.+?)Output:', example, re.DOTALL) - output_match = re.search(r'Output:\s*(.+?)$', example, re.DOTALL) + input_match = re.search(r'Input:\s*```(.+?)```\s*Output:', example, re.DOTALL) + output_match = re.search(r'Output:\s*```(.+?)```\s*$', example, re.DOTALL) if not input_match or not output_match: raise MarkdownParsingError(f"Invalid example format. Expected 'Input:' and 'Output:' sections with code blocks.") task["examples"].append([{ - "input": input_match.group(1).replace('\`\`\`', '').strip(), - "output": output_match.group(1).replace('\`\`\`', '').strip() # Remove the .replace('\n', line_ending) + "input": input_match.group(1).strip(), + "output": output_match.group(1).strip() }]) - # Extract tags (required) tags_text = extract_section(r'## Tags:') if not tags_text: