raannakasturi commited on
Commit
8b1dfdc
·
verified ·
1 Parent(s): 2b16092

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +47 -0
  2. generate_svg.py +137 -0
  3. requirements.txt +2 -0
app.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from generate_svg import main
3
+
4
+ theme = gr.themes.Soft(
5
+ primary_hue="purple",
6
+ secondary_hue="cyan",
7
+ neutral_hue="slate",
8
+ font=[
9
+ gr.themes.GoogleFont("Syne"),
10
+ gr.themes.GoogleFont("Poppins"),
11
+ gr.themes.GoogleFont("Poppins"),
12
+ gr.themes.GoogleFont("Poppins")
13
+ ],
14
+ )
15
+
16
+ with gr.Blocks(theme=theme, title="MarkDown SVG Generator", fill_height=True) as app:
17
+ gr.HTML(
18
+ value ="""
19
+ <h1 style="text-align: center;">MarkDown SVG Generator<p style="text-align: center;">Designed and Developed by <a href="https://raannakasturi.eu.org" target="_blank" rel="nofollow noreferrer external">Nayan Kasturi</a></p> </h1>
20
+ <p style="text-align: center;">MarkDown SVG Generator for ReXplore</p>
21
+ """)
22
+ with gr.Row():
23
+ with gr.Column():
24
+ markdown = gr.Textbox(label="Markdown Text", placeholder="Enter the markdown text", lines=7)
25
+ get_file = gr.Button(value="SVG File", variant="primary")
26
+ svg_viewer = gr.Textbox(label="SVG Viewer", placeholder="SVG Viewer", lines=7, interactive=False, show_copy_button=True)
27
+ get_file.click(
28
+ main,
29
+ inputs=[markdown],
30
+ outputs=[svg_viewer],
31
+ concurrency_limit=25,
32
+ scroll_to_output=True,
33
+ show_api=True,
34
+ api_name="markdown_svg_generator",
35
+ show_progress="full",
36
+ )
37
+
38
+ import subprocess
39
+ try:
40
+ subprocess.run(["apt", "update"], check=True)
41
+ subprocess.run(["apt" "install" "graphviz"], check=True)
42
+ app.queue(default_concurrency_limit=25).launch(show_api=True, show_error=True, debug=True)
43
+ except subprocess.CalledProcessError:
44
+ print("Graphviz is not installed. Please install it using `apt install graphviz` and try again.")
45
+ except Exception as e:
46
+ print(f"An error occurred: {e}")
47
+ raise e
generate_svg.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from graphviz import Digraph
3
+ # from cairosvg import svg2pdf
4
+ import re
5
+ import random
6
+
7
+ def parse_markdown_to_dict(md_text):
8
+ lines = md_text.strip().splitlines()
9
+ mindmap = {}
10
+ stack = []
11
+ for line in lines:
12
+ heading_match = re.match(r'^(#{1,6})\s+(.*)', line)
13
+ bullet_match = re.match(r'^\s*-\s+(.*)', line)
14
+ if heading_match:
15
+ level = len(heading_match.group(1))
16
+ title = heading_match.group(2).strip()
17
+ node = {'title': title, 'children': []}
18
+ while len(stack) >= level:
19
+ stack.pop()
20
+ if stack:
21
+ stack[-1]['children'].append(node)
22
+ else:
23
+ mindmap = node
24
+ stack.append(node)
25
+ elif bullet_match and stack:
26
+ stack[-1]['children'].append({'title': bullet_match.group(1), 'children': []})
27
+ return mindmap
28
+
29
+ generated_colors = set()
30
+
31
+ def generate_random_color():
32
+ """Generate a random color that hasn't been generated before."""
33
+ while True:
34
+ # Generate a random color in hex format
35
+ color = "#{:02x}{:02x}{:02x}".format(random.randint(128, 255), random.randint(128, 255), random.randint(128, 255))
36
+ # If the color is not in the set, it's unique
37
+ if color not in generated_colors:
38
+ generated_colors.add(color) # Add the color to the set of generated colors
39
+ return color # Return the unique color
40
+ else:
41
+ continue # Try again
42
+
43
+ def brighten_color(color, factor=0.15):
44
+ """Brighten the color by a certain factor (default 10%)"""
45
+ # Remove the '#' symbol
46
+ color = color.lstrip('#')
47
+
48
+ # Convert hex to RGB
49
+ r, g, b = [int(color[i:i+2], 16) for i in (0, 2, 4)]
50
+
51
+ # Increase each component by the factor, but clamp to 255
52
+ r = min(255, int(r * (1 + factor)))
53
+ g = min(255, int(g * (1 + factor)))
54
+ b = min(255, int(b * (1 + factor)))
55
+
56
+ # Convert back to hex
57
+ return "#{:02x}{:02x}{:02x}".format(r, g, b)
58
+
59
+ def add_nodes_to_graph(graph, node, parent_id=None, font_size=9, parent_color=None):
60
+ node_id = str(id(node))
61
+ title = node['title']
62
+ if parent_color is None:
63
+ node_color = "#ADD8E6" # Light Blue for the main heading
64
+ border_color = "#000000" # Dark Blue border for the main heading
65
+ parent_color = "#ADD8E6"
66
+ elif parent_color == "#ADD8E6":
67
+ node_color = generate_random_color()
68
+ border_color = "#808080"
69
+ parent_color = node_color
70
+ else:
71
+ # Child node and its descendants with the same random color
72
+ node_color = brighten_color(parent_color, factor=0.15)
73
+ border_color = "#808080"
74
+ # Check for markdown links
75
+ url_match = re.search(r'\[(.*?)\]\((.*?)\)', title)
76
+ if url_match:
77
+ prefix_text = title[:url_match.start()].strip()
78
+ display_text = url_match.group(1)
79
+ url = url_match.group(2)
80
+
81
+ label = f'{prefix_text} {display_text}'
82
+ 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))
83
+ else:
84
+ graph.node(node_id, title, shape="box", style="rounded,filled", color=border_color, fontcolor="black", fillcolor=node_color, tooltip=title, fontsize=str(font_size))
85
+
86
+ if parent_id:
87
+ graph.edge(parent_id, node_id)
88
+
89
+ # Recurse to children, passing down color for the child and its descendants
90
+ for child in node.get('children', []):
91
+ # Assign a random color to each child node (no inheritance from parent)
92
+ add_nodes_to_graph(graph, child, node_id, font_size=max(8, font_size - 1), parent_color=parent_color)
93
+
94
+ # def generate_mindmap_pdf(svg_file):
95
+ # pdf_file = svg_file.replace(".svg", ".pdf")
96
+ # svg2pdf(file_obj=open(svg_file, "rb"), write_to=pdf_file)
97
+ # return pdf_file
98
+
99
+ def generate_mindmap_svg(md_text):
100
+ mindmap_dict = parse_markdown_to_dict(md_text)
101
+ root_title = mindmap_dict.get('title', 'Mindmap')
102
+ sanitized_title = re.sub(r'[^a-zA-Z0-9_\-]', '', root_title.replace(" ", ""))
103
+ output_filename = f"{sanitized_title}_mindmap.svg"
104
+ graph = Digraph(format='svg')
105
+ graph.attr(rankdir='LR', size='10,10!', pad="0.5", margin="0.2", ratio="auto")
106
+ graph.attr('node', fontname="Arial", fontsize="9")
107
+ add_nodes_to_graph(graph, mindmap_dict)
108
+ svg_content = graph.pipe(format='svg').decode('utf-8')
109
+ svg_content = svg_content.replace("%3", root_title)
110
+ # Save the modified SVG content to a file
111
+ with open(output_filename, 'w') as f:
112
+ f.write(svg_content)
113
+ return output_filename
114
+
115
+ def generate_mindmap(md_text):
116
+ mindmap_svg = generate_mindmap_svg(md_text)
117
+ # mindmap_pdf = generate_mindmap_pdf(mindmap_svg)
118
+ return mindmap_svg
119
+
120
+ def upload_svg(mindmap_svg):
121
+ from huggingface_hub import HfApi
122
+ api = HfApi()
123
+ api.upload_file(
124
+ path_or_fileobj=mindmap_svg,
125
+ path_in_repo=f"SVG/{mindmap_svg}",
126
+ repo_id="raannakasturi/ReXploreData",
127
+ repo_type="dataset",
128
+ )
129
+ if os.path.exists(mindmap_svg):
130
+ os.remove(mindmap_svg)
131
+ return f"https://huggingface.co/datasets/raannakasturi/ReXploreData/raw/main/SVG/{mindmap_svg}"
132
+
133
+ def main(markdown_text):
134
+ mindmap_svg = generate_mindmap_svg(markdown_text.replace("**", ""))
135
+ url = upload_svg(mindmap_svg)
136
+ print(f"Uploaded SVG to {url}")
137
+ return url
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ graphviz
2
+ cairosvg