mindmap.export module¶
- mindmap.export.build_markdown_html(markdown_text: str) str¶
- mindmap.export.build_markmap_data(markdown_text: str) str¶
- mindmap.export.build_markmap_html(markmap_text: str) str¶
- mindmap.export.build_mermaid_html(mermaid_text: str) str¶
- mindmap.export.build_parser() ArgumentParser¶
- mindmap.export.export_extension(export_type: str) str¶
- mindmap.export.export_json(document: MindmapDocument) str¶
- mindmap.export.export_mindmap(export_type: str, macos_access: str) Tuple[str, str]¶
- mindmap.export.export_yaml(document: MindmapDocument) str¶
- mindmap.export.main(argv: Sequence[str] | None = None, docs_dir: str | None = None) int¶
- mindmap.export.markdown_data(document: MindmapDocument) str¶
- mindmap.export.markdown_html(document: MindmapDocument, markdown_text: str | None = None) str¶
- mindmap.export.markmap(document: MindmapDocument) str¶
- mindmap.export.markmap_html(document: MindmapDocument, markmap_text: str | None = None) str¶
- mindmap.export.mermaid(document: MindmapDocument) str¶
- mindmap.export.mermaid_html(document: MindmapDocument, mermaid_text: str | None = None) str¶
- mindmap.export.open_file(path: str) None¶
- mindmap.export.resolve_output_path(output: str | None, export_type: str, docs_dir: str | None = None) str¶
- mindmap.export.write_output(output_path: str, output: str, source: str, export_type: str) None¶
Source code for export.py¶
1import argparse
2import json
3import os
4import subprocess
5import sys
6import uuid
7from typing import Optional, Sequence, Tuple
8
9import markdown
10import mindmap.mindmap as mm
11import mindmap.serialization as mms
12
13MARKMAP_DATA_TEMPLATE = """---
14markmap:
15colorFreezeLevel: {{colorFreezeLevel}}
16initialExpandLevel: -1
17---
18{{markmap}}
19"""
20
21MARKMAP_TEMPLATE = """
22<div class="markmap">
23<script type="text/template">
24{{markmap}}
25</script>
26</div>
27"""
28
29MERMAID_TEMPLATE = """
30<div class="mermaid">
31%%{init: {"theme": "light"}}%%
32{{mermaid}}
33</div>
34"""
35
36MARKMAP_HTML_TEMPLATE = """
37<!DOCTYPE html><html lang="en">
38<head>
39<meta charset="UTF-8" />
40<meta name="viewport" content="width=device-width, initial-scale=1.0" />
41<title>{{title}}</title>
42<style>
43svg.markmap{width:100%;height:100vh;}
44</style>
45<script src="https://cdn.jsdelivr.net/npm/markmap-autoloader@latest"></script>
46</head><body>
47{{body}}
48</body></html>
49"""
50
51MERMAID_HTML_TEMPLATE = """
52<!DOCTYPE html><html lang="en">
53<head>
54<meta charset="UTF-8" />
55<meta name="viewport" content="width=device-width, initial-scale=1.0" />
56<title>{{title}}</title>
57<style>
58svg.mermaid{width:100%;height:100vh;}
59</style>
60<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
61<script>
62document.addEventListener('DOMContentLoaded', () => {
63 mermaid.initialize({ startOnLoad: true });
64});
65</script>
66</head><body>
67{{body}}
68</body></html>
69"""
70
71MARKDOWN_HTML_TEMPLATE = """
72<!DOCTYPE html><html lang="en">
73<head>
74<meta charset="UTF-8" />
75<meta name="viewport" content="width=device-width, initial-scale=1.0" />
76<title>{{title}}</title>
77<style>
78body{font-family:Helvetica,Arial,sans-serif;}
79h2{margin-block-start:0;margin-block-end:0}
80hr{margin-block-start:0;margin-block-end:0}
81ul{margin-block-start:8px}
82</style>
83</head><body>
84{{body}}
85</body></html>
86"""
87
88
89def build_markmap_data(markdown_text: str) -> str:
90 return MARKMAP_DATA_TEMPLATE.replace("{{colorFreezeLevel}}", "3").replace(
91 "{{markmap}}", markdown_text
92 )
93
94
95def build_markmap_html(markmap_text: str) -> str:
96 content = MARKMAP_TEMPLATE.replace("{{markmap}}", markmap_text)
97 html = MARKMAP_HTML_TEMPLATE.replace("{{title}}", "Markmap")
98 return html.replace("{{body}}", content)
99
100
101def build_mermaid_html(mermaid_text: str) -> str:
102 content = MERMAID_TEMPLATE.replace("{{mermaid}}", mermaid_text)
103 html = MERMAID_HTML_TEMPLATE.replace("{{title}}", "Mermaid")
104 return html.replace("{{body}}", content)
105
106
107def build_markdown_html(markdown_text: str) -> str:
108 body_html = markdown.markdown(markdown_text)
109 body_html = body_html.replace("</h2>", "</h2><hr/>")
110 html = MARKDOWN_HTML_TEMPLATE.replace("{{title}}", "Mindmap")
111 return html.replace("{{body}}", body_html)
112
113
114def open_file(path: str) -> None:
115 if sys.platform.startswith("darwin"):
116 subprocess.Popen(["open", path])
117 elif sys.platform.startswith("win"):
118 os.startfile(path) # type: ignore[attr-defined]
119 else:
120 subprocess.Popen(["xdg-open", path])
121
122
123def export_extension(export_type: str) -> str:
124 if export_type.endswith("_html"):
125 return ".htm"
126 if export_type == "json":
127 return ".json"
128 if export_type == "yaml":
129 return ".yaml"
130 if export_type == "mermaid":
131 return ".mmd"
132 if export_type in ("markmap", "markdown"):
133 return ".md"
134 return ".txt"
135
136
137def resolve_output_path(
138 output: Optional[str], export_type: str, docs_dir: Optional[str] = None
139) -> str:
140 extension = export_extension(export_type)
141 if output:
142 if os.path.isdir(output):
143 os.makedirs(output, exist_ok=True)
144 return os.path.join(os.path.abspath(output), f"{uuid.uuid4()}{extension}")
145
146 output_path = os.path.abspath(output)
147 output_dir = os.path.dirname(output_path)
148 if output_dir:
149 os.makedirs(output_dir, exist_ok=True)
150 return output_path
151
152 if docs_dir is None:
153 docs_dir = os.path.join(os.getcwd(), "docs")
154 os.makedirs(docs_dir, exist_ok=True)
155 return os.path.join(docs_dir, f"{uuid.uuid4()}{extension}")
156
157
158def mermaid(document: mm.MindmapDocument) -> str:
159 return mms.serialize_mindmap_simple(document.mindmap)
160
161
162def markmap(document: mm.MindmapDocument) -> str:
163 markdown_text = mms.serialize_mindmap_markdown(
164 document.mindmap, include_notes=False
165 )
166 return build_markmap_data(markdown_text)
167
168
169def markdown_data(document: mm.MindmapDocument) -> str:
170 return mms.serialize_mindmap_markdown(document.mindmap, include_notes=True)
171
172
173def export_json(document: mm.MindmapDocument) -> str:
174 guid_mapping = {}
175 mms.build_mapping(document.mindmap, guid_mapping)
176 data = mms.serialize_object(document.mindmap, guid_mapping)
177 return json.dumps(data, indent=1)
178
179
180def export_yaml(document: mm.MindmapDocument) -> str:
181 import yaml
182
183 guid_mapping = {}
184 mms.build_mapping(document.mindmap, guid_mapping)
185 data = mms.serialize_object(document.mindmap, guid_mapping)
186 return yaml.dump(data, sort_keys=False)
187
188
189def mermaid_html(
190 document: mm.MindmapDocument, mermaid_text: Optional[str] = None
191) -> str:
192 if mermaid_text is None:
193 mermaid_text = mermaid(document)
194 return build_mermaid_html(mermaid_text)
195
196
197def markmap_html(
198 document: mm.MindmapDocument, markmap_text: Optional[str] = None
199) -> str:
200 if markmap_text is None:
201 markmap_text = markmap(document)
202 return build_markmap_html(markmap_text)
203
204
205def markdown_html(
206 document: mm.MindmapDocument, markdown_text: Optional[str] = None
207) -> str:
208 if markdown_text is None:
209 markdown_text = markdown_data(document)
210 return build_markdown_html(markdown_text)
211
212
213def export_mindmap(export_type: str, macos_access: str) -> Tuple[str, str]:
214 document = mm.MindmapDocument(macos_access=macos_access)
215 document.get_mindmap(mode="content")
216
217 if export_type == "mermaid_html":
218 data = mermaid(document)
219 return data, mermaid_html(document, data)
220
221 if export_type == "markmap_html":
222 data = markmap(document)
223 return data, markmap_html(document, data)
224
225 if export_type == "markdown_html":
226 data = markdown_data(document)
227 return data, markdown_html(document, data)
228
229 if export_type == "json":
230 data = export_json(document)
231 return data, data
232
233 if export_type == "yaml":
234 data = export_yaml(document)
235 return data, data
236
237 if export_type == "mermaid":
238 data = mermaid(document)
239 return data, data
240
241 if export_type == "markmap":
242 data = markmap(document)
243 return data, data
244
245 data = markdown_data(document)
246 return data, data
247
248
249def write_output(output_path: str, output: str, source: str, export_type: str) -> None:
250 with open(output_path, "w", encoding="utf-8") as f:
251 f.write(output)
252
253 if export_type == "markdown_html":
254 markdown_path = os.path.splitext(output_path)[0] + ".md"
255 with open(markdown_path, "w", encoding="utf-8") as f:
256 f.write(source)
257
258
259def build_parser() -> argparse.ArgumentParser:
260 parser = argparse.ArgumentParser(
261 description=(
262 "Export the current MindManager mindmap to HTML or data-only output "
263 "for mermaid, markmap, markdown, JSON, or YAML."
264 )
265 )
266 parser.add_argument(
267 "--type",
268 required=True,
269 choices=(
270 "mermaid_html",
271 "markmap_html",
272 "markdown_html",
273 "json",
274 "yaml",
275 "mermaid",
276 "markmap",
277 "markdown",
278 ),
279 help="Export type to generate (HTML or data-only).",
280 )
281 parser.add_argument(
282 "--output",
283 help=(
284 "Output file path. Defaults to docs/<uuid> plus an extension based on "
285 "--type."
286 ),
287 )
288 mode_group = parser.add_mutually_exclusive_group()
289 mode_group.add_argument(
290 "--open",
291 action="store_true",
292 help="Open the generated output file after export.",
293 )
294 mode_group.add_argument(
295 "--stream",
296 action="store_true",
297 help="Write the generated output to stdout instead of writing a file.",
298 )
299 parser.add_argument(
300 "--macos-access",
301 default="applescript",
302 choices=("applescript", "appscript"),
303 help="macOS MindManager access method.",
304 )
305 return parser
306
307
308def main(argv: Optional[Sequence[str]] = None, docs_dir: Optional[str] = None) -> int:
309 parser = build_parser()
310 args = parser.parse_args(argv)
311
312 source, output = export_mindmap(args.type, args.macos_access)
313
314 if args.stream:
315 sys.stdout.write(output)
316 return 0
317
318 output_path = resolve_output_path(args.output, args.type, docs_dir=docs_dir)
319 write_output(output_path, output, source, args.type)
320 print(output_path)
321
322 if args.open:
323 open_file(output_path)
324
325 return 0
326
327
328if __name__ == "__main__":
329 raise SystemExit(main())