import argparse import re import xml.etree.ElementTree as ET def extract_code_snippets(file_path: str) -> dict: """ Extracts code snippets delimited by "BEGIN CODE SNIPPET XYZ" and "END CODE SNIPPET" from the given file, with XYZ being some user-defined name. All snippets are extracted and returned as a dictionary with the snippet name as the key, and the snippet contents as the value. :param file_path: File path in which the tag should be found. """ snippets = dict() with open(file_path) as f_in: lines = f_in.readlines() snippet_name = None snippet_start_line = None for i, line in enumerate(lines): if "BEGIN CODE SNIPPET" in line: snippet_name = line.split("BEGIN CODE SNIPPET")[1].strip() snippet_start_line = i + 1 if "END CODE SNIPPET" in line: snippets[snippet_name] = "".join(lines[snippet_start_line:i]) return snippets def decode_xml_snippet_tag(line): """ Extracts and decodes the XML snippet tag under the following form : ``` ``` :param line: Line containing the XML tag. """ # Extract the XML tag from the line the_match = re.match("()", line) if the_match: xml_string = the_match.group(1) else: return None # Parse the XML string root = ET.fromstring(f'{xml_string}') # Wrap in a root tag if needed # Iterate over all include_snippet tags for elem in root.findall('include_snippet'): name = elem.get('name') file = elem.get('file') return {"name": name, "file": file} def extract_snippet_infos(lines) -> dict: """ Extracts the names of the snippets required from the source markdown file. Returns a dictionary of lists : - file_name_1 - snippet_name_1 - snippet_name_2 - ... - file_name_2 - snippet_name_1 - snippet_name_2 - ... - ... """ snippet_infos = dict() snippet_infos_list = [] for line in lines: if "` tags under the following form: ``` ``` Beware that the `` tag is case-sensitive ! It must be all lowercase to be correctly detected. :param args: Parsed program arguments. """ with open(args.source) as f_in: with open(args.destination, "w+") as f_out: # Read source markdown file source_lines = f_in.readlines() # Extract required code snippets from markdown file snippet_infos = extract_snippet_infos(source_lines) print_snippet_information(snippet_infos) # Extract actual snippets snippets = dict() for file_path in snippet_infos.keys(): snippets[file_path] = extract_code_snippets(file_path) print_snippet_summary(snippets) # Replace the snippet calls by the actual content output_lines = insert_snippets_in_markdown(source_lines, snippets) # Write the processed file f_out.writelines(output_lines) def parse_args(): """ Parses the arguments of the program. """ # Create the argument parser parser = argparse.ArgumentParser(description='Markdown code snippet injector.') # Add the positional arguments parser.add_argument('source', type=str, help='Source path (mandatory)') parser.add_argument('destination', type=str, help='Destination path (mandatory)') return parser.parse_args() if __name__ == "__main__": args = parse_args() process_markdown_file(args)