Compare commits

...

2 Commits

Author SHA1 Message Date
Gregory Leeman 86286d6a66 Merge branch 'main' of https://git.gregoryleeman.com/gregory/wf 5 months ago
Gregory Leeman de859c21ac lazygit 5 months ago
  1. 219
      wf/script.py

219
wf/script.py

@ -291,7 +291,7 @@ def simplify_project(project_data, full_data, follow_mirrors=False): # {{{
"name": project_data.get("nm", ""),
"id": project_data.get("id", ""),
"children": [],
"description": project_data.get("no", ""),
"description": project_data.get("no", "").rstrip().replace("\n$", ""),
"format": project_data.get("metadata", {}).get("layoutMode", None)
}
children = project_data.get("ch", [])
@ -398,8 +398,6 @@ def filter_project_all(project_data, filters, include_headers=False): # {{{
def replace(project_data, regex, replacement): # {{{
project_data["name"] = re.sub(regex, replacement, project_data["name"])
children = project_data.get("children", [])
@ -480,7 +478,7 @@ colors2 = {
}
def recolor(project_data, colors):
def recolor(project_data, colors): # {{{
for key, value in colors.items():
if key in project_data["name"]:
if key.startswith("x"):
@ -488,6 +486,10 @@ def recolor(project_data, colors):
else:
project_data["name"] = f"[{value}]{project_data['name'].strip()}[/]"
break
# if project_data["format"] == "h1":
# project_data["name"] = f"[base3][underline]{project_data['name']}[/]"
# if project_data["format"] == "h2":
# project_data["name"] = f"[base1][underline]{project_data['name']}[/]"
children = project_data.get("children", [])
for child in children:
recolor(child, colors)
@ -497,28 +499,210 @@ def recolor(project_data, colors):
def print_pretty(data, indent=0, color="grey", show_description=True, show_id=False): # {{{
try:
# href = f"https://workflowy.com/#/{data['id'].split('-')[4]}"
for item in data["children"]:
if item["format"] == "h1":
console.print("")
console.print(" " * indent + f"[base3]•[/] [base3][underline]{item['name']}[/][/][base01]{' ' + item['id'].split('-')[4] if show_id else ''}[/]")
elif item["format"] == "h2":
console.print(" " * indent + f"[base3]•[/] [base1][underline]{item['name']}[/][/][base01]{' ' + item['id'].split('-')[4] if show_id else ''}[/]")
else:
console.print(" " * indent + f"[base3]•[/] [{color}]{item['name']}[/][base01]{' ' + item['id'].split('-')[4] if show_id else ''}[/]")
console.print(" " * indent + f"[base3]•[/] [{color}]{item['name']}[/][base01]{' ' + item['id'].split('-')[4] if show_id else ''}[/]")
if item["description"] and show_description:
console.print(" " * (indent + 1) + f"[base01]{item['description'].replace('\n', '\n' + ' ' * (indent + 1))}[/]")
if item["children"]:
print_pretty(item, indent + 1, color, show_description=show_description, show_id=show_id)
except Exception as e:
console.log(f"Error: {e}")
# }}}
def generate_d3_mindmap_html(data, show_description=True, show_id=False): # {{{
import json
import re
# Map of Rich tag colors to hex values or CSS color names
color_map = {
"base3": "#073642",
"base2": "#002b36",
"base1": "#586e75",
"base0": "#657b83",
"base00": "#839496",
"base01": "#93a1a1",
"base02": "#eee8d5",
"base03": "#fdf6e3",
"yellow": "#b58900",
"orange": "#cb4b16",
"red": "#dc322f",
"magenta": "#d33682",
"violet": "#6c71c4",
"blue": "#268bd2",
"cyan": "#2aa198",
"green": "#859900",
}
def parse_rich_tags(text):
text = re.sub(r"\[(underline)? ?([a-zA-Z0-9]+)?\](.*?)\[/\]",
lambda m: f'<tspan style="{"text-decoration: underline;" if m.group(1) else ""}'
f'{"fill: " + color_map[m.group(2)] + ";" if m.group(2) else ""}">{m.group(3)}</tspan>',
text)
return text
def remove_rich_tags(text):
text = re.sub(r"\[(underline)? ?([a-zA-Z0-9]+)?\](.*?)\[/\]", r"\3", text)
return text
# Recursively transform data to add the parsed Rich-style text
def transform_data(item):
node = {
"name": remove_rich_tags(parse_rich_tags(item["name"])), # Parse Rich tags in name
"id": item["id"].split("-")[4] if show_id else "",
"description": parse_rich_tags(item["description"]) if show_description else ""
}
if item["children"]:
node["children"] = [transform_data(child) for child in item["children"]]
return node
transformed_data = transform_data(data)
# Create the HTML content with D3.js code
html_content = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mind Map</title>
<script src="https://d3js.org/d3.v6.min.js"></script>
<style>
body {{
font-family: Arial, sans-serif;
background-color: #073642;
color: #fdf6e3;
}}
.node {{
cursor: pointer;
}}
.node circle {{
fill: #586e75;
stroke: #586e75;
stroke-width: 3px;
}}
.node text {{
# color: #fdf6e3 !important;
fill: #fdf6e3;
font: 12px sans-serif;
}}
.link {{
fill: none;
stroke: #586e75;
stroke-width: 2px;
}}
</style>
</head>
<body>
<svg width="100vw" height="100vh"></svg>
<script>
var data = {json.dumps(transformed_data)};
var svg = d3.select("svg")
.attr("width", "100vw")
.attr("height", "100vh");
var zoom = d3.zoom()
.scaleExtent([0.5, 5])
.on("zoom", function(event) {{
g.attr("transform", "translate(" + event.transform.x + "," + event.transform.y + ") scale(" + event.transform.k + ") rotate(" + currentRotation + ")");
currentTransform = event.transform;
}});
svg.call(zoom);
var g = svg.append("g");
// .attr("transform", "translate(" + window.innerWidth / 2 + "," + window.innerHeight / 2 + ")");
var currentRotation = 0;
var currentTransform = d3.zoomIdentity;
var isRotating = false;
var lastX = 0;
document.addEventListener("keydown", function(event) {{
if (event.key === "r" || event.key === "R") {{
isRotating = !isRotating;
}}
}});
svg.on("mousedown", function(event) {{
if (isRotating) {{
lastX = event.clientX;
}}
}});
svg.on("mousemove", function(event) {{
if (isRotating) {{
var dx = event.clientX - lastX;
currentRotation += dx * 0.1;
g.attr("transform", "translate(" + currentTransform.x + "," + currentTransform.y + ") scale(" + currentTransform.k + ") rotate(" + currentRotation + ")");
lastX = event.clientX;
}}
}});
svg.on("mouseup", function() {{
isRotating = false;
}});
var tree = d3.tree()
.size([360, Math.min(window.innerWidth, window.innerHeight) / 2 - 100])
.separation(function(a, b) {{ return (a.parent === b.parent ? 1 : 2) / a.depth; }});
var root = d3.hierarchy(data);
tree(root);
var link = g.selectAll(".link")
.data(root.links())
.enter().append("path")
.attr("class", "link")
.attr("d", d3.linkRadial()
.angle(function(d) {{ return d.x / 180 * Math.PI; }})
.radius(function(d) {{ return d.y; }}));
var node = g.selectAll(".node")
.data(root.descendants())
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {{ return "translate(" + radialPoint(d.x, d.y) + ")"; }});
node.append("circle")
.attr("r", 4.5);
node.append("text")
.attr("dy", ".31em")
.attr("x", 10)
.attr("text-anchor", "start")
.attr("transform", function(d) {{
return "rotate(" + (d.x - 90) + ") translate(10, 0)";
}})
.html(function(d) {{
return d.data.name;
}});
function radialPoint(x, y) {{
return [(y = +y) * Math.cos((x - 90) / 180 * Math.PI), y * Math.sin((x - 90) / 180 * Math.PI)];
}}
</script>
</body>
</html>
"""
# Write the HTML content to a file
with open("d3_mindmap.html", "w") as f:
f.write(html_content)
print("D3.js mind map HTML generated as 'd3_mindmap.html'.")
# }}}
@ -561,6 +745,7 @@ def show(parent_id, flat=False, filters_all=None, filters_any=None, color="grey"
console.print("")
print_pretty(project_data, color=color, show_description=show_description, show_id=show_id)
console.print("")
generate_d3_mindmap_html(project_data, show_description=show_description, show_id=show_id)
return True
# }}}

Loading…
Cancel
Save