Skip to content

Commit 1dce605

Browse files
committed
refactor: Unify HTML conversion to use standalone tool
- Remove duplicate HTML conversion code from html_converter.py - Keep only versioning support methods in MarkMapHTMLConverter - All HTML conversion now uses convert_to_html.py - Remove embedded template code, use templates/markmap.html file - Update translate_only.py to use standalone tool - Remove use_standalone_tool config option (now default behavior) - Update documentation This eliminates code duplication and ensures a single source of truth for HTML conversion functionality.
1 parent 39df7a0 commit 1dce605

File tree

6 files changed

+155
-507
lines changed

6 files changed

+155
-507
lines changed

tools/ai-markmap-agent/README.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -242,15 +242,13 @@ It can be used to convert any Markmap Markdown file to interactive HTML.
242242

243243
### Integration with Pipeline
244244

245-
The standalone tool can be integrated with the main pipeline. To use it instead of the internal converter, set in `config/config.yaml`:
245+
The standalone tool is **automatically used** by the main pipeline. The pipeline
246+
calls `convert_to_html.py` programmatically to generate HTML files. This maintains
247+
**decoupling** (the tool can run independently) while enabling **integration**
248+
(the pipeline calls it automatically).
246249

247-
```yaml
248-
output:
249-
html:
250-
use_standalone_tool: true # Use convert_to_html.py instead of internal converter
251-
```
252-
253-
This maintains **decoupling** (the tool can run independently) while allowing **integration** (the pipeline can call it programmatically).
250+
The HTML template is stored in `templates/markmap.html` and can be customized
251+
without modifying code.
254252
```
255253
256254
### API Keys

tools/ai-markmap-agent/config/config.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,7 @@ output:
347347

348348
html:
349349
template: "templates/markmap.html"
350-
# Use standalone convert_to_html.py tool instead of internal converter
351-
# This allows decoupling while maintaining integration
352-
use_standalone_tool: false # Set to true to use convert_to_html.py
350+
# HTML conversion is handled by the standalone convert_to_html.py tool
353351
include_styles: true
354352
include_scripts: true
355353
title: "AI Evolved Markmap"

tools/ai-markmap-agent/convert_to_html.py

Lines changed: 8 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def __init__(self, template_path: str | Path | None = None):
3434
Initialize the converter.
3535
3636
Args:
37-
template_path: Path to HTML template (optional)
37+
template_path: Path to HTML template (optional, defaults to templates/markmap.html)
3838
"""
3939
self.base_dir = Path(__file__).parent
4040

@@ -46,109 +46,13 @@ def __init__(self, template_path: str | Path | None = None):
4646
else:
4747
template_path = self.base_dir / "templates" / "markmap.html"
4848

49-
if template_path.exists():
50-
self.template = Template(template_path.read_text(encoding="utf-8"))
51-
else:
52-
# Use default template
53-
self.template = Template(self._default_template())
54-
55-
def _default_template(self) -> str:
56-
"""Return default HTML template."""
57-
return """<!DOCTYPE html>
58-
<html lang="en">
59-
<head>
60-
<meta charset="UTF-8">
61-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
62-
<title>{{ title }} - NeetCode Mind Maps</title>
63-
<style>
64-
* { margin: 0; padding: 0; box-sizing: border-box; }
65-
html, body { height: 100%; }
66-
.markmap { width: 100%; height: 100%; }
67-
.markmap > svg { width: 100%; height: 100%; }
68-
#topbar {
69-
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
70-
background: #fff; border-bottom: 1px solid #e5e7eb;
71-
padding: 8px 16px; display: flex; gap: 8px;
72-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
73-
font-size: 13px;
74-
}
75-
#topbar button {
76-
padding: 4px 12px; border: 1px solid #d1d5db;
77-
border-radius: 4px; background: #fff; cursor: pointer;
78-
}
79-
#topbar button:hover { background: #f3f4f6; }
80-
.markmap { margin-top: 40px; height: calc(100% - 40px); }
81-
</style>
82-
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
83-
<script src="https://cdn.jsdelivr.net/npm/markmap-view"></script>
84-
<script src="https://cdn.jsdelivr.net/npm/markmap-lib"></script>
85-
<script src="https://cdn.jsdelivr.net/npm/markmap-toolbar"></script>
86-
<script>
87-
function fitView() {
88-
var svg = document.querySelector('.markmap > svg');
89-
if (svg && svg.mm) svg.mm.fit();
90-
}
91-
function expandAll() {
92-
var svg = document.querySelector('.markmap > svg');
93-
if (svg && svg.mm) {
94-
var root = svg.mm.state.data;
95-
(function expand(n) {
96-
n.payload = Object.assign({}, n.payload, { fold: 0 });
97-
if (n.children) n.children.forEach(expand);
98-
})(root);
99-
svg.mm.setData(root); svg.mm.fit();
100-
}
101-
}
102-
function collapseAll() {
103-
var svg = document.querySelector('.markmap > svg');
104-
if (svg && svg.mm) {
105-
var root = svg.mm.state.data;
106-
root.children && root.children.forEach(function collapse(n) {
107-
if (n.children && n.children.length) {
108-
n.payload = Object.assign({}, n.payload, { fold: 1 });
109-
n.children.forEach(collapse);
110-
}
111-
});
112-
svg.mm.setData(root); svg.mm.fit();
113-
}
114-
}
115-
document.addEventListener('DOMContentLoaded', function() {
116-
const { Transformer, Markmap } = window.markmap;
117-
const transformer = new Transformer();
118-
const markdown = `{{ markdown_content | safe }}`;
119-
const { root } = transformer.transform(markdown);
120-
const svg = d3.select('.markmap').append('svg');
121-
const mm = Markmap.create(svg.node(), { color: (node) => node.payload?.color || '#f59e0b' }, root);
122-
svg.node().mm = mm;
123-
if (window.markmap && window.markmap.Toolbar) {
124-
const toolbar = new window.markmap.Toolbar();
125-
toolbar.attach(mm);
126-
setTimeout(function() {
127-
document.querySelectorAll('.mm-toolbar').forEach(function(toolbar) {
128-
toolbar.querySelectorAll('.mm-toolbar-item').forEach(function(item) {
129-
if ((item.title || '').toLowerCase().includes('dark')) item.remove();
130-
});
131-
var brand = toolbar.querySelector('.mm-toolbar-brand');
132-
if (brand) {
133-
brand.innerHTML = '🟡 NeetCode';
134-
brand.href = '#'; brand.onclick = function(e) { e.preventDefault(); };
135-
brand.style.fontSize = '12px'; brand.style.color = '#666';
136-
}
137-
});
138-
}, 200);
139-
}
140-
});
141-
</script>
142-
</head>
143-
<body>
144-
<div id="topbar">
145-
<button onclick="fitView()">Fit View</button>
146-
<button onclick="expandAll()">Expand All</button>
147-
<button onclick="collapseAll()">Collapse All</button>
148-
</div>
149-
<div class="markmap"></div>
150-
</body>
151-
</html>"""
49+
if not template_path.exists():
50+
raise FileNotFoundError(
51+
f"Template file not found: {template_path}\n"
52+
"Please ensure templates/markmap.html exists or specify a custom template path."
53+
)
54+
55+
self.template = Template(template_path.read_text(encoding="utf-8"))
15256

15357
def convert(
15458
self,

tools/ai-markmap-agent/src/graph.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,8 @@ def run_post_processing(state: WorkflowState) -> WorkflowState:
815815
def save_outputs(state: WorkflowState) -> WorkflowState:
816816
"""
817817
Phase 7: Save all outputs to files.
818+
819+
Uses the standalone convert_to_html.py tool for HTML conversion.
818820
"""
819821
print("\n[Phase 7] Saving outputs...")
820822

@@ -824,20 +826,8 @@ def save_outputs(state: WorkflowState) -> WorkflowState:
824826
print(" ⚠ No outputs to save")
825827
return state
826828

827-
# Check if we should use standalone tool
828-
output_config = config.get("output", {})
829-
html_config = output_config.get("html", {})
830-
use_standalone_tool = html_config.get("use_standalone_tool", False)
831-
832-
if use_standalone_tool:
833-
print(" 🔧 Using standalone HTML converter tool...")
834-
835829
try:
836-
saved = save_all_markmaps(
837-
final_outputs,
838-
config,
839-
use_standalone_tool=use_standalone_tool
840-
)
830+
saved = save_all_markmaps(final_outputs, config)
841831
state["messages"].append(f"Saved {len(saved)} output files")
842832
print(f" ✓ Saved {len(saved)} output files")
843833
except Exception as e:

0 commit comments

Comments
 (0)