Spaces:
Sleeping
Sleeping
Load environment variables and use HF_TOKEN for Hugging Face API authentication in generate_svg.py
6b83232
| import os | |
| from graphviz import Digraph | |
| # from cairosvg import svg2pdf | |
| import re | |
| import os | |
| import dotenv | |
| import random | |
| dotenv.load_dotenv() | |
| hf_token = os.getenv("HF_TOKEN") | |
| def parse_markdown_to_dict(md_text): | |
| lines = md_text.strip().splitlines() | |
| mindmap = {} | |
| stack = [] | |
| for line in lines: | |
| heading_match = re.match(r'^(#{1,6})\s+(.*)', line) | |
| bullet_match = re.match(r'^\s*-\s+(.*)', line) | |
| if heading_match: | |
| level = len(heading_match.group(1)) | |
| title = heading_match.group(2).strip() | |
| node = {'title': title, 'children': []} | |
| while len(stack) >= level: | |
| stack.pop() | |
| if stack: | |
| stack[-1]['children'].append(node) | |
| else: | |
| mindmap = node | |
| stack.append(node) | |
| elif bullet_match and stack: | |
| stack[-1]['children'].append({'title': bullet_match.group(1), 'children': []}) | |
| return mindmap | |
| generated_colors = set() | |
| def generate_random_color(): | |
| """Generate a random color that hasn't been generated before.""" | |
| while True: | |
| # Generate a random color in hex format | |
| color = "#{:02x}{:02x}{:02x}".format(random.randint(128, 255), random.randint(128, 255), random.randint(128, 255)) | |
| # If the color is not in the set, it's unique | |
| if color not in generated_colors: | |
| generated_colors.add(color) # Add the color to the set of generated colors | |
| return color # Return the unique color | |
| else: | |
| continue # Try again | |
| def brighten_color(color, factor=0.15): | |
| """Brighten the color by a certain factor (default 10%)""" | |
| # Remove the '#' symbol | |
| color = color.lstrip('#') | |
| # Convert hex to RGB | |
| r, g, b = [int(color[i:i+2], 16) for i in (0, 2, 4)] | |
| # Increase each component by the factor, but clamp to 255 | |
| r = min(255, int(r * (1 + factor))) | |
| g = min(255, int(g * (1 + factor))) | |
| b = min(255, int(b * (1 + factor))) | |
| # Convert back to hex | |
| return "#{:02x}{:02x}{:02x}".format(r, g, b) | |
| def add_nodes_to_graph(graph, node, parent_id=None, font_size=9, parent_color=None): | |
| node_id = str(id(node)) | |
| title = node['title'] | |
| if parent_color is None: | |
| node_color = "#ADD8E6" # Light Blue for the main heading | |
| border_color = "#000000" # Dark Blue border for the main heading | |
| parent_color = "#ADD8E6" | |
| elif parent_color == "#ADD8E6": | |
| node_color = generate_random_color() | |
| border_color = "#808080" | |
| parent_color = node_color | |
| else: | |
| # Child node and its descendants with the same random color | |
| node_color = brighten_color(parent_color, factor=0.15) | |
| border_color = "#808080" | |
| # Check for markdown links | |
| url_match = re.search(r'\[(.*?)\]\((.*?)\)', title) | |
| if url_match: | |
| prefix_text = title[:url_match.start()].strip() | |
| display_text = url_match.group(1) | |
| url = url_match.group(2) | |
| label = f'{prefix_text} {display_text}' | |
| graph.node(node_id, label=label, shape="box", style="rounded,filled", color=border_color, fontcolor="black", fillcolor=node_color, href=url, tooltip=title, fontsize=str(font_size)) | |
| else: | |
| graph.node(node_id, title, shape="box", style="rounded,filled", color=border_color, fontcolor="black", fillcolor=node_color, tooltip=title, fontsize=str(font_size)) | |
| if parent_id: | |
| graph.edge(parent_id, node_id) | |
| # Recurse to children, passing down color for the child and its descendants | |
| for child in node.get('children', []): | |
| # Assign a random color to each child node (no inheritance from parent) | |
| add_nodes_to_graph(graph, child, node_id, font_size=max(8, font_size - 1), parent_color=parent_color) | |
| # def generate_mindmap_pdf(svg_file): | |
| # pdf_file = svg_file.replace(".svg", ".pdf") | |
| # svg2pdf(file_obj=open(svg_file, "rb"), write_to=pdf_file) | |
| # return pdf_file | |
| def generate_mindmap_svg(md_text): | |
| mindmap_dict = parse_markdown_to_dict(md_text) | |
| root_title = mindmap_dict.get('title', 'Mindmap') | |
| sanitized_title = re.sub(r'[^a-zA-Z0-9_\-]', '', root_title.replace(" ", "")) | |
| output_filename = f"{sanitized_title}_mindmap.svg" | |
| graph = Digraph(format='svg') | |
| graph.attr(rankdir='LR', size='10,10!', pad="0.5", margin="0.2", ratio="auto") | |
| graph.attr('node', fontname="Arial", fontsize="9") | |
| add_nodes_to_graph(graph, mindmap_dict) | |
| svg_content = graph.pipe(format='svg').decode('utf-8') | |
| svg_content = svg_content.replace("%3", root_title) | |
| # Save the modified SVG content to a file | |
| with open(output_filename, 'w') as f: | |
| f.write(svg_content) | |
| return output_filename | |
| def generate_mindmap(md_text): | |
| mindmap_svg = generate_mindmap_svg(md_text) | |
| # mindmap_pdf = generate_mindmap_pdf(mindmap_svg) | |
| return mindmap_svg | |
| def upload_svg(mindmap_svg): | |
| from huggingface_hub import HfApi | |
| api = HfApi(token=hf_token) | |
| api.upload_file( | |
| path_or_fileobj=mindmap_svg, | |
| path_in_repo=f"SVG/{mindmap_svg}", | |
| repo_id="raannakasturi/ReXploreData", | |
| repo_type="dataset", | |
| ) | |
| if os.path.exists(mindmap_svg): | |
| os.remove(mindmap_svg) | |
| return f"https://huggingface.co/datasets/raannakasturi/ReXploreData/raw/main/SVG/{mindmap_svg}" | |
| def main(markdown_text): | |
| mindmap_svg = generate_mindmap_svg(markdown_text.replace("**", "")) | |
| url = upload_svg(mindmap_svg) | |
| print(f"Uploaded SVG to {url}") | |
| return url | |