DEV Community

Muhammad Jazman
Muhammad Jazman

Posted on

markdown (.md) to mm

import xml.etree.ElementTree as ET
import re

def markdown_to_mm(md_file_path, output_mm_path):
    # Root <map> element required by FreeMind/Freeplane
    map_elem = ET.Element('map', version='1.0.1')

    # Root node
    root_node = ET.SubElement(map_elem, 'node', TEXT='Root Mindmap')

    # Track hierarchy using a stack: (level, xml_node_element)
    stack = [(0, root_node)]

    with open(md_file_path, 'r', encoding='utf-8') as f:
        lines = f.readlines()

    for line in lines:
        line_str = line.strip()
        if not line_str:
            continue

        level = None
        text = ""

        # Match Markdown headers (# Header 1, ## Header 2)
        heading_match = re.match(r'^(#+)\s+(.*)', line_str)
        if heading_match:
            level = len(heading_match.group(1))
            text = heading_match.group(2)
        else:
            # Match bullet lists (- or *) with indentation
            bullet_match = re.match(r'^(\s*)([-*])\s+(.*)', line)
            if bullet_match:
                indent_spaces = len(bullet_match.group(1))
                # Treat every 2 or 4 spaces as 1 indent level
                level = (indent_spaces // 2) + 1
                text = bullet_match.group(3)

        if level is not None:
            # Pop stack until we find the parent level
            while stack and stack[-1][0] >= level:
                stack.pop()

            parent_node = stack[-1][1] if stack else root_node
            new_node = ET.SubElement(parent_node, 'node', TEXT=text)
            stack.append((level, new_node))

    # Write out to .mm XML format
    tree = ET.ElementTree(map_elem)
    ET.indent(tree, space="  ")  # Pretty print XML formatting
    tree.write(output_mm_path, encoding='utf-8', xml_declaration=True)
    print(f"Successfully converted '{md_file_path}' to '{output_mm_path}'")

# Usage:
# markdown_to_mm('input.md', 'output.mm')
markdown_to_mm('The Charisma Myth Mastering.coggle.md', 'The Charisma Myth Mastering.coggle.mm')

Enter fullscreen mode Exit fullscreen mode

Top comments (0)