Skip to content

Commit 98491b9

Browse files
committed
fix: Make translate_only.py and convert_to_html.py work as CLI tools from any directory
- Resolve relative paths relative to script directory (Path(__file__).parent) - Support absolute paths directly - Add validation to prevent empty output files - Add detailed error messages and debugging info - Maintain compatibility with main.py when run from script directory
1 parent 2cde74b commit 98491b9

File tree

4 files changed

+155
-19
lines changed

4 files changed

+155
-19
lines changed

docs/pages/mindmaps/neetcode_ontology_agent_evolved_zh-TW.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>NeetCode Agent Evolved Mindmap (繁體中文) - NeetCode Mind Maps</title>
6+
<title>NeetCode Agent Evolved Mindmap (ZH-TW) - NeetCode Mind Maps</title>
77
<style>
88
* { margin: 0; padding: 0; box-sizing: border-box; }
99
html, body { height: 100%; }

tools/ai-markmap-agent/README.md

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -243,50 +243,73 @@ The output will be saved to:
243243

244244
If you want to translate a specific English file:
245245

246-
**Important**: Run the command from the `tools/ai-markmap-agent/` directory, or use absolute paths.
246+
**Important**:
247+
- **Default output location**: When using `--output`, files are saved to the specified path
248+
- **Auto-detection**: Without `--output`, files are saved to `docs/mindmaps/` (configured in `config.yaml`)
249+
- **Version history**: The main pipeline also saves to `outputs/versions/v1/` for tracking, but `translate_only.py` only saves to the final location
250+
251+
**Working with `docs/mindmaps/` directory:**
247252

248253
**Unix/macOS:**
249254
```bash
250255
# Navigate to the script directory first
251256
cd tools/ai-markmap-agent
252257

253-
# Translate a specific file (auto-detects output path)
258+
# Translate a specific file (auto-detects output to docs/mindmaps/)
254259
python translate_only.py --input ../../docs/mindmaps/neetcode_ontology_agent_evolved_en.md
255260

256-
# Or with explicit output path
261+
# Or with explicit output path to docs/mindmaps/
257262
python translate_only.py \
258263
--input ../../docs/mindmaps/neetcode_ontology_agent_evolved_en.md \
259264
--output ../../docs/mindmaps/neetcode_ontology_agent_evolved_zh-TW.md
265+
266+
# Translate and generate HTML in one step
267+
python translate_only.py \
268+
--input ../../docs/mindmaps/neetcode_ontology_agent_evolved_en.md \
269+
--output ../../docs/mindmaps/neetcode_ontology_agent_evolved_zh-TW.md \
270+
--html
260271
```
261272

262273
**Windows PowerShell:**
263274
```powershell
264275
# Navigate to the script directory first
265276
cd tools\ai-markmap-agent
266277
267-
# Translate a specific file (auto-detects output path)
278+
# Translate a specific file (auto-detects output to docs\mindmaps\)
268279
python translate_only.py --input ..\..\docs\mindmaps\neetcode_ontology_agent_evolved_en.md
269280
270-
# Or with explicit output path
281+
# Or with explicit output path to docs\mindmaps\
271282
python translate_only.py `
272283
--input ..\..\docs\mindmaps\neetcode_ontology_agent_evolved_en.md `
273284
--output ..\..\docs\mindmaps\neetcode_ontology_agent_evolved_zh-TW.md
285+
286+
# Translate and generate HTML in one step
287+
python translate_only.py `
288+
--input ..\..\docs\mindmaps\neetcode_ontology_agent_evolved_en.md `
289+
--output ..\..\docs\mindmaps\neetcode_ontology_agent_evolved_zh-TW.md `
290+
--html
274291
```
275292

276-
**Alternative: Use absolute paths from any directory:**
293+
**From Project Root (Alternative):**
277294
```bash
278-
# Unix/macOS
295+
# Unix/macOS - from project root
279296
python tools/ai-markmap-agent/translate_only.py \
280297
--input docs/mindmaps/neetcode_ontology_agent_evolved_en.md \
281298
--output docs/mindmaps/neetcode_ontology_agent_evolved_zh-TW.md
282299
```
283300

284301
```powershell
285-
# Windows PowerShell
302+
# Windows PowerShell - from project root
286303
python tools\ai-markmap-agent\translate_only.py `
287304
--input docs\mindmaps\neetcode_ontology_agent_evolved_en.md `
288305
--output docs\mindmaps\neetcode_ontology_agent_evolved_zh-TW.md
289306
```
307+
308+
**Note on Output Locations:**
309+
- **Version History** (main pipeline only): `tools/ai-markmap-agent/outputs/versions/v1/` (for tracking changes)
310+
- **Final Output** (translate_only.py): `docs/mindmaps/` (for actual use)
311+
- When using `--output`, the file is saved to the specified path
312+
- When not using `--output`, it auto-detects based on config (saves to `docs/mindmaps/`)
290313
**Method 3: Translate and Generate HTML in One Step**
291314

292315
```bash
@@ -326,8 +349,15 @@ python translate_only.py --model gpt-4o
326349

327350
For converting Markdown files to HTML without running the full pipeline:
328351

352+
**Important**: Run from `tools/ai-markmap-agent/` directory, or use absolute paths.
353+
354+
**Basic Usage:**
355+
329356
```bash
330-
# Basic conversion (output: input.html)
357+
# Navigate to script directory
358+
cd tools/ai-markmap-agent
359+
360+
# Basic conversion (output: input.html in same directory)
331361
python convert_to_html.py input.md
332362

333363
# Specify output file
@@ -340,6 +370,50 @@ python convert_to_html.py input.md -t "My Mind Map"
340370
python convert_to_html.py input.md --template templates/custom.html
341371
```
342372

373+
**Working with `docs/mindmaps/` directory:**
374+
375+
```bash
376+
# From tools/ai-markmap-agent/ directory
377+
# Convert English version
378+
python convert_to_html.py \
379+
../../docs/mindmaps/neetcode_ontology_agent_evolved_en.md \
380+
-o ../../docs/pages/mindmaps/neetcode_ontology_agent_evolved_en.html \
381+
-t "NeetCode Agent Evolved Mindmap (EN)"
382+
383+
# Convert Traditional Chinese version
384+
python convert_to_html.py \
385+
../../docs/mindmaps/neetcode_ontology_agent_evolved_zh-TW.md \
386+
-o ../../docs/pages/mindmaps/neetcode_ontology_agent_evolved_zh-TW.html \
387+
-t "NeetCode Agent Evolved Mindmap (繁體中文)"
388+
```
389+
390+
**Windows PowerShell:**
391+
392+
```powershell
393+
# From tools\ai-markmap-agent\ directory
394+
# Convert English version
395+
python convert_to_html.py `
396+
..\..\docs\mindmaps\neetcode_ontology_agent_evolved_en.md `
397+
-o ..\..\docs\pages\mindmaps\neetcode_ontology_agent_evolved_en.html `
398+
-t "NeetCode Agent Evolved Mindmap (EN)"
399+
400+
# Convert Traditional Chinese version
401+
python convert_to_html.py `
402+
..\..\docs\mindmaps\neetcode_ontology_agent_evolved_zh-TW.md `
403+
-o ..\..\docs\pages\mindmaps\neetcode_ontology_agent_evolved_zh-TW.html `
404+
-t "NeetCode Agent Evolved Mindmap (繁體中文)"
405+
```
406+
407+
**From Project Root (Alternative):**
408+
409+
```bash
410+
# From project root directory
411+
python tools/ai-markmap-agent/convert_to_html.py \
412+
docs/mindmaps/neetcode_ontology_agent_evolved_en.md \
413+
-o docs/pages/mindmaps/neetcode_ontology_agent_evolved_en.html \
414+
-t "NeetCode Agent Evolved Mindmap (EN)"
415+
```
416+
343417
This tool is **completely independent** of the main pipeline and only requires:
344418
- Python 3.10+
345419
- `jinja2` package

tools/ai-markmap-agent/convert_to_html.py

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def convert_file_to_html(
9898
Convert a Markdown file to HTML (programmatic interface).
9999
100100
Args:
101-
input_path: Path to input Markdown file
101+
input_path: Path to input Markdown file (can be relative or absolute)
102102
output_path: Path to output HTML file (default: same as input with .html)
103103
title: Optional HTML page title
104104
template_path: Optional custom template path
@@ -108,14 +108,26 @@ def convert_file_to_html(
108108
109109
This function can be imported and used programmatically.
110110
"""
111-
input_path = Path(input_path).resolve()
111+
# Resolve input path (handles both absolute and relative paths)
112+
input_path = Path(input_path)
113+
if not input_path.is_absolute():
114+
# If relative, resolve relative to current working directory
115+
# (This is correct for programmatic calls where paths are already resolved)
116+
input_path = input_path.resolve()
117+
else:
118+
input_path = input_path.resolve()
119+
112120
if not input_path.exists():
113121
raise FileNotFoundError(f"Input file not found: {input_path}")
114122

115123
if output_path is None:
116124
output_path = input_path.with_suffix(".html")
117125
else:
118-
output_path = Path(output_path).resolve()
126+
output_path = Path(output_path)
127+
if not output_path.is_absolute():
128+
output_path = output_path.resolve()
129+
else:
130+
output_path = output_path.resolve()
119131

120132
output_path.parent.mkdir(parents=True, exist_ok=True)
121133

@@ -183,10 +195,21 @@ def main() -> int:
183195
args = parser.parse_args()
184196

185197
try:
198+
# Get script base directory for resolving relative paths (CLI tool behavior)
199+
script_base_dir = Path(__file__).parent
200+
186201
# Resolve input path
187-
input_path = Path(args.input).resolve()
202+
# Relative paths are resolved relative to script directory, not current working directory
203+
input_path = Path(args.input)
204+
if not input_path.is_absolute():
205+
input_path = (script_base_dir / input_path).resolve()
206+
else:
207+
input_path = input_path.resolve()
208+
188209
if not input_path.exists():
189210
print(f"❌ Error: Input file not found: {input_path}")
211+
print(f" Resolved from: {args.input}")
212+
print(f" Script directory: {script_base_dir}")
190213
return 1
191214

192215
if not input_path.is_file():
@@ -195,7 +218,12 @@ def main() -> int:
195218

196219
# Determine output path
197220
if args.output:
198-
output_path = Path(args.output).resolve()
221+
output_path = Path(args.output)
222+
# Resolve relative paths relative to script directory (CLI tool behavior)
223+
if not output_path.is_absolute():
224+
output_path = (script_base_dir / output_path).resolve()
225+
else:
226+
output_path = output_path.resolve()
199227
else:
200228
output_path = input_path.with_suffix(".html")
201229

tools/ai-markmap-agent/translate_only.py

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,34 @@ def translate_file(
9595
print("\n⏳ Translating...")
9696
translated = translator.translate(content, "general")
9797

98+
# Validate translation result
99+
if not translated:
100+
raise ValueError("Translation returned empty content. Check API key and model configuration.")
101+
if len(translated.strip()) == 0:
102+
raise ValueError("Translation returned only whitespace. Check API response.")
103+
104+
print(f" Raw translation: {len(translated)} chars")
105+
98106
# Clean up LLM artifacts
99107
translated = clean_translated_content(translated)
100-
print(f" ✓ Translated to {len(translated)} chars")
108+
109+
# Validate cleaned content
110+
if not translated or len(translated.strip()) == 0:
111+
raise ValueError("After cleaning, translation is empty. Check clean_translated_content function.")
112+
113+
print(f" ✓ Cleaned translation: {len(translated)} chars, {len(translated.splitlines())} lines")
101114

102115
# Save output
103116
output_path.parent.mkdir(parents=True, exist_ok=True)
104117
output_path.write_text(translated, encoding="utf-8")
105-
print(f"\n💾 Saved: {output_path}")
118+
119+
# Verify file was written
120+
if not output_path.exists():
121+
raise IOError(f"Failed to write output file: {output_path}")
122+
if output_path.stat().st_size == 0:
123+
raise IOError(f"Output file is empty: {output_path}")
124+
125+
print(f"\n💾 Saved: {output_path} ({output_path.stat().st_size} bytes)")
106126

107127
return translated
108128

@@ -170,11 +190,21 @@ def main() -> int:
170190
print("\n❌ Error: OpenAI API key is required.")
171191
return 1
172192

193+
# Get script base directory for resolving relative paths
194+
script_base_dir = Path(__file__).parent
195+
173196
# Determine input file
174197
if args.input:
175198
input_path = Path(args.input)
199+
# Resolve relative paths relative to script directory (CLI tool behavior)
200+
if not input_path.is_absolute():
201+
input_path = (script_base_dir / input_path).resolve()
202+
else:
203+
input_path = input_path.resolve()
204+
176205
if not input_path.exists():
177206
print(f"\n❌ Error: Input file not found: {args.input}")
207+
print(f" Resolved path: {input_path}")
178208
return 1
179209
else:
180210
input_path = find_latest_english_output(config)
@@ -190,6 +220,11 @@ def main() -> int:
190220
# Determine output file
191221
if args.output:
192222
output_path = Path(args.output)
223+
# Resolve relative paths relative to script directory (CLI tool behavior)
224+
if not output_path.is_absolute():
225+
output_path = (script_base_dir / output_path).resolve()
226+
else:
227+
output_path = output_path.resolve()
193228
else:
194229
# Replace language suffix in filename (only at the end!)
195230
stem = input_path.stem
@@ -231,8 +266,7 @@ def main() -> int:
231266

232267
# Get HTML output directory from config
233268
final_dirs = config.get("output", {}).get("final_dirs", {})
234-
base_dir = Path(__file__).parent
235-
html_output_dir = (base_dir / final_dirs.get("html", "outputs/final")).resolve()
269+
html_output_dir = (script_base_dir / final_dirs.get("html", "outputs/final")).resolve()
236270
html_output_dir.mkdir(parents=True, exist_ok=True)
237271

238272
html_path = html_output_dir / f"{output_path.stem}.html"

0 commit comments

Comments
 (0)