freeplane-and-yaml 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,40 @@
1
+ import sys
2
+ import os
3
+ from .convert import convert_yaml_file # Import your conversion logic
4
+
5
+
6
+ def main():
7
+ # Check for the correct number of arguments
8
+ if len(sys.argv) != 3:
9
+ print("Usage: convert input.yaml output_directory")
10
+ sys.exit(1)
11
+
12
+ # Parse arguments
13
+ input_file = sys.argv[1]
14
+ output_dir = sys.argv[2]
15
+
16
+ # Validate the input YAML file
17
+ if not input_file.endswith(".yaml"):
18
+ print(f"Error: {input_file} is not a valid YAML file.")
19
+ sys.exit(1)
20
+
21
+ if not os.path.isfile(input_file):
22
+ print(f"Error: Input file {input_file} does not exist.")
23
+ sys.exit(1)
24
+
25
+ # Validate the output directory
26
+ if not os.path.isdir(output_dir):
27
+ print(f"Error: Output directory {output_dir} does not exist.")
28
+ sys.exit(1)
29
+
30
+ # Generate the `.m` file name based on the input file
31
+ base_name = os.path.basename(input_file).replace(".yaml", ".mm")
32
+ output_file = os.path.join(output_dir, base_name)
33
+
34
+ # Perform the conversion
35
+ try:
36
+ convert_yaml_file(input_file, output_file)
37
+ print(f"Conversion complete: {output_file}")
38
+ except Exception as e:
39
+ print(f"Error during conversion: {e}")
40
+ sys.exit(1)
@@ -0,0 +1,100 @@
1
+ import yaml
2
+ from xml.etree.ElementTree import Element, SubElement, tostring
3
+ from xml.dom import minidom
4
+ import uuid
5
+ import argparse
6
+ import os
7
+
8
+ def generate_node_id():
9
+ """Generate a unique ID for a node."""
10
+ return f"ID_{str(uuid.uuid4()).replace('-', '_')}"
11
+
12
+ def create_note_element(note_text):
13
+ """Create a richcontent note element with the given text."""
14
+ richcontent = Element('richcontent', {
15
+ 'TYPE': 'NOTE',
16
+ 'CONTENT-TYPE': 'xml/'
17
+ })
18
+ html = SubElement(richcontent, 'html')
19
+ head = SubElement(html, 'head')
20
+ body = SubElement(html, 'body')
21
+ p = SubElement(body, 'p')
22
+ p.text = note_text
23
+ return richcontent
24
+
25
+ def add_node_recursive(parent_element, node_data, position=None):
26
+ """Recursively add nodes to the mind map."""
27
+ # Create node element with basic attributes
28
+ node_attrs = {
29
+ 'TEXT': node_data['title'],
30
+ 'ID': generate_node_id()
31
+ }
32
+ if position:
33
+ node_attrs['POSITION'] = position
34
+
35
+ node = SubElement(parent_element, 'node', node_attrs)
36
+
37
+ # Add note if present
38
+ if 'note' in node_data:
39
+ node.append(create_note_element(node_data['note']))
40
+
41
+ # Process children if present
42
+ if 'children' in node_data:
43
+ # Alternate positions for children
44
+ positions = ['right', 'left']
45
+ position_index = 0
46
+
47
+ for child_key, child_data in node_data['children'].items():
48
+ # Alternate between right and left for top-level children
49
+ child_position = positions[position_index % 2] if parent_element.tag == 'map' else None
50
+ position_index += 1
51
+ add_node_recursive(node, child_data, child_position)
52
+
53
+ def converter(yaml_content):
54
+ """Convert YAML content to Freeplane mind map format."""
55
+ # Parse YAML content
56
+ data = yaml.safe_load(yaml_content)
57
+
58
+ # Create the base map element
59
+ map_elem = Element('map', {'version': '1.9.13'})
60
+
61
+ # Add the root node and its children
62
+ add_node_recursive(map_elem, data['root'])
63
+
64
+ # Convert to string and pretty print
65
+ rough_string = tostring(map_elem, 'utf-8')
66
+ reparsed = minidom.parseString(rough_string)
67
+ pretty_xml = reparsed.toprettyxml(indent=" ")
68
+
69
+ # Add XML declaration
70
+ if not pretty_xml.startswith('<?xml'):
71
+ pretty_xml = '<?xml version="1.0" encoding="UTF-8"?>\n' + pretty_xml
72
+
73
+ return pretty_xml
74
+
75
+ def convert_yaml_file(yaml_file_path, output_file_path):
76
+ """Convert a YAML file to a Freeplane mind map file."""
77
+ with open(yaml_file_path, 'r', encoding='utf-8') as yaml_file:
78
+ yaml_content = yaml_file.read()
79
+
80
+ mind_map_xml = converter(yaml_content)
81
+
82
+ with open(output_file_path, 'w', encoding='utf-8') as mm_file:
83
+ mm_file.write(mind_map_xml)
84
+
85
+ # Example usage:
86
+ if __name__ == "__main__":
87
+ parser = argparse.ArgumentParser(description='Convert YAML file to Freeplane mind map')
88
+ parser.add_argument('input_file', help='Input YAML file path')
89
+ parser.add_argument('output_dir', help='Output directory for the mind map file')
90
+
91
+ args = parser.parse_args()
92
+
93
+ # Create output directory if it doesn't exist
94
+ os.makedirs(args.output_dir, exist_ok=True)
95
+
96
+ # Generate output filename based on input filename
97
+ input_basename = os.path.splitext(os.path.basename(args.input_file))[0]
98
+ output_file = os.path.join(args.output_dir, f"{input_basename}.mm")
99
+
100
+ convert_yaml_file(args.input_file, output_file)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Romilly Cocking
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,133 @@
1
+ Metadata-Version: 2.1
2
+ Name: freeplane-and-yaml
3
+ Version: 0.1.1
4
+ Summary: A tool to convert YAML files to Freeplane MM format
5
+ Home-page: https://github.com/romilly/freeplane-and-yaml
6
+ Author: Romilly Cocking
7
+ Author-email: romilly.cocking@gmail.com
8
+ License: MIT
9
+ Platform: UNKNOWN
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: PyYAML
17
+
18
+ # YAML to Freeplane Converter
19
+
20
+ A Python tool that converts YAML files into Freeplane mind maps. This allows you to generate mind maps programmatically from structured YAML data.
21
+
22
+ The YAML file can be created using [Claude AI](https://claude.ai/chat/). A suitable prompt is given [below](#converting-documents-to-mind-maps-using-claude-ai).
23
+
24
+ You can read about how it got written using AI on [medium](https://medium.com/@romillyc/build-your-own-mind-map-tools-with-ai-b193564f2464?sk=b353aa7d16d6412e4aae8f3eab0ec554).
25
+ That's a friend link so you can read it even if you're not a subscriber.
26
+
27
+ ## Installation
28
+
29
+ First, clone this repository:
30
+
31
+ ```bash
32
+ # clone the project from GitHub
33
+ git clone https://github.com/romilly/freeplane-and-yaml.git
34
+ cd freeplane-and-yaml
35
+ ```
36
+
37
+ This project requires Python and should be run in a virtual environment:
38
+
39
+ ```bash
40
+ # Create and activate virtual environment
41
+ python -m venv venv
42
+ source venv/bin/activate # On Windows use: venv\Scripts\activate
43
+
44
+ # Install required packages
45
+ pip install pyyaml
46
+ ```
47
+
48
+ ## Usage
49
+
50
+ The code should be run from the `src` directory after activating the virtual environment. Your YAML file should follow the schema defined in `schema/mindmap-schema.json`. Here's an example structure:
51
+
52
+ ```yaml
53
+ root:
54
+ title: "Your Main Topic"
55
+ note: "Optional note for the main topic"
56
+ children:
57
+ subtopic1:
58
+ title: "Subtopic 1"
59
+ note: "Optional note for subtopic 1"
60
+ children:
61
+ # ... more nested topics
62
+ subtopic2:
63
+ title: "Subtopic 2"
64
+ # ... and so on
65
+ ```
66
+
67
+ ### YAML Schema Requirements
68
+
69
+ The YAML must conform to these rules:
70
+ - Must have a root node with a title and at least one child
71
+ - Each node requires a title
72
+ - Notes are optional
73
+ - Child node keys must be alphanumeric (including underscores)
74
+ - No additional properties are allowed beyond title, note, and children
75
+
76
+ For full schema details, see `schema/mindmap-schema.json`.
77
+
78
+ ### Converting Documents to Mind Maps using Claude AI
79
+
80
+ You can use Claude Sonnet to automatically convert documents (PDFs, articles, specifications, etc.) into the required YAML format. Here's the workflow:
81
+
82
+ 1. Share your document and the schema (from `schema/mindmap-schema.json`)with Claude Sonnet.
83
+ 2. Use this prompt:
84
+ ```
85
+ I've uploaded a document and a schema file. I'd like you to summarise the document as a yaml file following the schema that I uploaded.
86
+ ```
87
+ 3. Claude will generate a YAML file that follows the schema
88
+ 4. Save Claude's output as a .yaml file
89
+ 5. Convert it to a mind map using this tool
90
+
91
+ This workflow is useful for:
92
+ - Summarizing academic papers
93
+ - Converting product requirements documents (PRDs)
94
+ - Creating structured summaries of technical documentation
95
+ - Organizing research notes
96
+
97
+ ### Converting YAML to Mind Map
98
+
99
+ To convert a YAML file to a Freeplane mind map:
100
+
101
+ ```python
102
+ from freeplane_and_yaml.convert_yaml_to_freeplane import convert_yaml_file
103
+
104
+ # Convert YAML to mind map
105
+ convert_yaml_file('path/to/your/input.yaml', 'output.mm')
106
+ ```
107
+
108
+ The generated `.mm` file can be opened in Freeplane. When you first open the file, Freeplane will show this warning dialog because the file wasn't created by Freeplane itself:
109
+
110
+ ![Freeplane Warning Dialog](images/warning-dialog.png)
111
+
112
+ This is normal and expected — click OK to load the mind map.
113
+
114
+ Here's an example of how the output looks:
115
+
116
+ ![Example Mind Map](images/Screenshot%20at%202025-02-12%2010-43-23.png)
117
+
118
+ ## Features
119
+
120
+ - Converts YAML structured data to Freeplane mind map format
121
+ - Supports hierarchical node structure
122
+ - Includes node titles and optional notes
123
+ - Automatically alternates between right and left positions for top-level nodes
124
+ - Generates unique IDs for each node
125
+ - Validates input against JSON schema
126
+
127
+ ## License
128
+
129
+ Apologiresd to readers from the USA. This README uses UK spelling.
130
+
131
+ This project is licensed under the MIT Licence — see the [LICENCE](LICENSE) file for details.
132
+
133
+
@@ -0,0 +1,9 @@
1
+ freeplane_and_yaml/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ freeplane_and_yaml/cli.py,sha256=qeUJXw2MqCf6Kv7c-K63-srGj339beL4JTrAXi5_-3c,1213
3
+ freeplane_and_yaml/convert.py,sha256=dyQLt2FlmCgsQOnutnp1DyLXzqk-guazL8TZwTH0vHI,3440
4
+ freeplane_and_yaml-0.1.1.dist-info/LICENSE,sha256=gCmvBRHqGZibjt4wyMG81SeYWMKuhoGFVQh_Kn1wZ98,1072
5
+ freeplane_and_yaml-0.1.1.dist-info/METADATA,sha256=rK9H4NH6Z7rx89SzQs8c-ZtccsPrztOl6ukMyJ0CO78,4420
6
+ freeplane_and_yaml-0.1.1.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
7
+ freeplane_and_yaml-0.1.1.dist-info/entry_points.txt,sha256=kWuCk_RZlzcO9h7yk7uJ4dtJiccQxBocEuQPVt6qzxo,57
8
+ freeplane_and_yaml-0.1.1.dist-info/top_level.txt,sha256=UY6T4vy985r4DAfWpM1D_n6t0cEis5SxtfkPPd-xDhQ,19
9
+ freeplane_and_yaml-0.1.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.45.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ convert = freeplane_and_yaml.cli:main
3
+
@@ -0,0 +1 @@
1
+ freeplane_and_yaml