{"componentChunkName":"component---src-templates-article-js","path":"/projects/texmindmapper","result":{"data":{"markdownRemark":{"frontmatter":{"title":"TexMindMapper - visualise your thesis","date":"1.7.2020","cover":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABQAD/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABLRMQF7KP/8QAGBAAAgMAAAAAAAAAAAAAAAAAAAECBDP/2gAIAQEAAQUCiVdmiJV0R//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABgQAAIDAAAAAAAAAAAAAAAAAAAQAXKB/9oACAEBAAY/AjHNV//EABoQAQEBAQADAAAAAAAAAAAAAAEAESExcYH/2gAIAQEAAT8hBlz7K2eOSm/ZJzzf/9oADAMBAAIAAwAAABDDD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABsQAQADAQADAAAAAAAAAAAAAAEAETEhQWHx/9oACAEBAAE/EEWoj5ZSzcZ11HoIlVfmG7fQjiqn/9k=","aspectRatio":1.7777777777777777,"src":"/static/b5a930b2ccf5ba3bbe2c468658666973/69755/tmm_cover.jpg","srcSet":"/static/b5a930b2ccf5ba3bbe2c468658666973/49b36/tmm_cover.jpg 512w,\n/static/b5a930b2ccf5ba3bbe2c468658666973/16310/tmm_cover.jpg 1024w,\n/static/b5a930b2ccf5ba3bbe2c468658666973/69755/tmm_cover.jpg 2048w,\n/static/b5a930b2ccf5ba3bbe2c468658666973/3d647/tmm_cover.jpg 3072w,\n/static/b5a930b2ccf5ba3bbe2c468658666973/cf7c5/tmm_cover.jpg 4096w,\n/static/b5a930b2ccf5ba3bbe2c468658666973/8a0c2/tmm_cover.jpg 4146w","sizes":"(max-width: 2048px) 100vw, 2048px"}}}},"html":"<blockquote>\n<p>Writing your thesis. Ah what an arduous task! Like probably many of us, I also encountered a point where comprehending the entire scope of the thesis was overflowing to every umaginable direction. I wanted - no, needed - a way to visualise what I was doing, for example a simple mind map.</p>\n<p>However, being as lazy as I am, I did not want to have a mindmap that I had to manually update every time I made changes to the thesis structure. It simply <strong>had</strong> to be automated.</p>\n</blockquote>\n<h2>A map for your thoughts</h2>\n<p>I started playing around with the excellent <a href=\"https://tobloef.com/text2mindmap/\">mind-map tool</a> I found online, which allowed creating mind-maps using tabbed text. This was something I could definitely use as a base for my implementation. But I wanted more. I wanted a process fully integrated to my workflow. By bare minimum, I wanted to have a system that would update the mind map every time I updated my thesis. Additionally, having a list of previous versions would be nice as well: one could observe what had been changed over time.</p>\n<h2>Seeing the tree from the woods</h2>\n<p>Information-wise, I naturally wanted to present as much as I could. When parsing the text in my thesis, I might as well analyse some information of it. This process of parsing and information extraction can be seen in more detail at the <a href=\"/projects/pytextree\">pytextree</a> post. The most prominent information that would be presented is:</p>\n<p><a href=\"https://www.overleaf.com/learn/latex/Environments\">https://www.overleaf.com/learn/latex/Environments</a></p>\n<ol>\n<li>Child-parent relations of chapters and sub-chapters as edges</li>\n<li>Word count in the sections as the node sizes</li>\n<li>\n<p>References presented as dotted line edges</p>\n<ul>\n<li>Line colour describing the source</li>\n</ul>\n</li>\n<li>Elements presented as nodes\n- Different colours for different types of Elements</li>\n</ol>\n<div class=\"gatsby-highlight\" data-language=\"py\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-py line-numbers\"><code class=\"language-py\"><span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>Root<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> Root <span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5502</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n└── <span class=\"token operator\">&lt;</span>TEnv <span class=\"token punctuation\">[</span>document<span class=\"token punctuation\">]</span><span class=\"token operator\">></span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">None</span> <span class=\"token punctuation\">(</span><span class=\"token number\">114</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5500</span><span class=\"token punctuation\">)</span>\n   ├── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>section<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> S1 <span class=\"token punctuation\">(</span><span class=\"token number\">144</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1129</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   │   ├── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>subsection<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> S1<span class=\"token punctuation\">.</span>S1 <span class=\"token punctuation\">(</span><span class=\"token number\">619</span><span class=\"token punctuation\">,</span> <span class=\"token number\">869</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   │   └── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>subsection<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> S1<span class=\"token punctuation\">.</span>S2 <span class=\"token punctuation\">(</span><span class=\"token number\">870</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1129</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   ├── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>section<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> S2 <span class=\"token punctuation\">(</span><span class=\"token number\">1130</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2542</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   │   └── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>subsection<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> S2<span class=\"token punctuation\">.</span>S1 <span class=\"token punctuation\">(</span><span class=\"token number\">1460</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2542</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   │       ├── <span class=\"token operator\">&lt;</span>TEnv <span class=\"token punctuation\">[</span>itemize<span class=\"token punctuation\">]</span><span class=\"token operator\">></span><span class=\"token punctuation\">:</span> <span class=\"token builtin\">list</span><span class=\"token punctuation\">:</span>mylist <span class=\"token punctuation\">(</span><span class=\"token number\">1606</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1867</span><span class=\"token punctuation\">)</span>\n   │       │   ├── <span class=\"token operator\">&lt;</span>TEnv <span class=\"token punctuation\">[</span>itemize<span class=\"token punctuation\">]</span><span class=\"token operator\">></span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">None</span> <span class=\"token punctuation\">(</span><span class=\"token number\">1695</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1771</span><span class=\"token punctuation\">)</span>\n   │       │   └── <span class=\"token operator\">&lt;</span>TEnv <span class=\"token punctuation\">[</span>itemize<span class=\"token punctuation\">]</span><span class=\"token operator\">></span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">None</span> <span class=\"token punctuation\">(</span><span class=\"token number\">1776</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1853</span><span class=\"token punctuation\">)</span>\n   │       ├── <span class=\"token operator\">&lt;</span>TEnv <span class=\"token punctuation\">[</span>itemize<span class=\"token punctuation\">]</span><span class=\"token operator\">></span><span class=\"token punctuation\">:</span> <span class=\"token builtin\">list</span><span class=\"token punctuation\">:</span>mylist <span class=\"token punctuation\">(</span><span class=\"token number\">1869</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1959</span><span class=\"token punctuation\">)</span>\n   │       ├── <span class=\"token operator\">&lt;</span>TEnv <span class=\"token punctuation\">[</span>tabular<span class=\"token punctuation\">]</span><span class=\"token operator\">></span><span class=\"token punctuation\">:</span> table<span class=\"token punctuation\">:</span>synonyms <span class=\"token punctuation\">(</span><span class=\"token number\">2032</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2136</span><span class=\"token punctuation\">)</span>\n   │       ├── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>subsubsection<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> S2<span class=\"token punctuation\">.</span>S1<span class=\"token punctuation\">.</span>S1 <span class=\"token punctuation\">(</span><span class=\"token number\">2140</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2230</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   │       └── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>subsubsection<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> S2<span class=\"token punctuation\">.</span>S1<span class=\"token punctuation\">.</span>S2 <span class=\"token punctuation\">(</span><span class=\"token number\">2231</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2542</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   ├── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>section<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> S3 <span class=\"token punctuation\">(</span><span class=\"token number\">2543</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5485</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   │   ├── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>paragraph<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> This <span class=\"token keyword\">is</span> a paragraph <span class=\"token punctuation\">(</span><span class=\"token number\">3417</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4368</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   │   ├── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>paragraph<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> And have another paragraph <span class=\"token punctuation\">(</span><span class=\"token number\">4369</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5299</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   │   └── <span class=\"token operator\">&lt;</span>TNode <span class=\"token punctuation\">[</span>subsection<span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span> S3<span class=\"token punctuation\">.</span>S1  <span class=\"token punctuation\">(</span><span class=\"token number\">5300</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5484</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span>\n   └── <span class=\"token operator\">&lt;</span>TEnv <span class=\"token punctuation\">[</span>appendices<span class=\"token punctuation\">]</span><span class=\"token operator\">></span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">None</span> <span class=\"token punctuation\">(</span><span class=\"token number\">5435</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5485</span><span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p><em>Example tree structure of a document, produced with the pytextree</em></p>\n<p>Also, as I used comments in the document extensively as a way to structure and draft my writing, I wanted a way to add these to the graph as well. This way I could plan and see what I had planned, but not implemented yet, in my thesis: I planned to use comments prefixed with a special tag to denote special nodes on the graph. For example:</p>\n<table>\n<thead>\n<tr>\n<th>Tag</th>\n<th>Meaning</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"language-text\">%c:</code></td>\n<td>Comment</td>\n<td>Special colour</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">%l:</code></td>\n<td>Label</td>\n<td>Special colour</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">%par:</code></td>\n<td>Paragraph</td>\n<td>Special colour</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">%p:XX:</code></td>\n<td>Progress</td>\n<td>Colour node based on progress (XX)</td>\n</tr>\n</tbody>\n</table>\n<p>Hence, for example the following little snippet would be portrayed as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"tex\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-tex line-numbers\"><code class=\"language-tex\"><span class=\"token function selector\">\\documentclass</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">article</span><span class=\"token punctuation\">}</span>\n<span class=\"token function selector\">\\begin</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">document</span><span class=\"token punctuation\">}</span>\n   <span class=\"token function selector\">\\section</span><span class=\"token punctuation\">{</span><span class=\"token headline class-name\">S1</span><span class=\"token punctuation\">}</span><span class=\"token function selector\">\\label</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">sec:S1</span><span class=\"token punctuation\">}</span>\n   <span class=\"token comment\">%c: TODO: add more Lorem</span>\n   Lorem ipsum dolor sit amet.\n\n   <span class=\"token function selector\">\\subsection</span><span class=\"token punctuation\">{</span><span class=\"token headline class-name\">S1.S1</span><span class=\"token punctuation\">}</span><span class=\"token function selector\">\\label</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">sec:S1S1</span><span class=\"token punctuation\">}</span>\n   <span class=\"token comment\">%l: This is good lorem </span>\n   At vero eos et accusamus. Lorem: <span class=\"token function selector\">\\ref</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">sec:S1</span><span class=\"token punctuation\">}</span>.\n\n   <span class=\"token function selector\">\\section</span><span class=\"token punctuation\">{</span><span class=\"token headline class-name\">S2</span><span class=\"token punctuation\">}</span>\n   <span class=\"token comment\">%p:00</span>\n\n<span class=\"token function selector\">\\end</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">document</span><span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p><em>What I had: The original raw LaTeX document with extremely meaningful and original content.</em></p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-text line-numbers\"><code class=\"language-text\">&lt;TNode [Root]: Root (0, 13)&gt;\n└── &lt;TEnv [document]&gt;: None (1, 13)\n   ├── &lt;TNode [section]: S1 (2, 5)&gt;\n   │   ├── &lt;TNode [subsection]: S1.S1 (6, 9)&gt;\n   └── &lt;TNode [section]: S2 (10, 13)&gt;</code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p><em>What I got: The document above, parsed using <code class=\"language-text\">pytextree</code>. Each <code class=\"language-text\">TNode</code> would contain the related parsed special comments.</em></p>\n<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 682px; '>\n      <span class='gatsby-resp-image-background-image' style=\"padding-bottom: 39.361702127659576%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsSAAALEgHS3X78AAABgElEQVQoz21SvUoDQRC+R9FKfAMrGxvxGWwEBX0DRTDaGBACYi9a2EREEbVQNGlS+NsISRONGjFeLpfc7eVyP/tzn7t3SZDTgZldZna++WZmtSiKkBblo5whpCFCJpUGEIIPYyol4hyR10s0DFUACklTQc5cMNoCp6a823Fi6fEGp9d5nBVOcHSZR+WlHPuFLKTEvy3he30ZejaDZm4TzHVjv6aM1z6HUV2BXt1Aq76HQJJpdLqoNUw4bi9mSikdduBLRq5lgRgtBE4XXIJFQiSAPT+CYYX4+LLRcVQSx+pViKl9jsldjouyFz9k/ckcVDqYOKxj695IRpAalTab62J0wcbIvI3pjAPqOTh+9pEtSC0GeHglENQHkwx44OHuk2DnyUTxLRmNiGeaaMxwbptgfKmNscU2ZtZMdAkZ1BvWt2yCWu0derP1Z3npuxaEHBYJoBsEpmmDMSarysal4QLJRqXpeT642qxqX8ZEH+A3u+FS/vs2MVCKxW8m6XMgP7RGWSohiW59AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"></span>\n  <img class='gatsby-resp-image-image' alt='LaTex Willer: most wanted!' title='LaTex Willer: most wanted!' src='/static/337242de24a3e3b8c12f2f17191692e8/160a3/parsed.png' srcset='/static/337242de24a3e3b8c12f2f17191692e8/4dcb9/parsed.png 188w,\n/static/337242de24a3e3b8c12f2f17191692e8/5ff7e/parsed.png 375w,\n/static/337242de24a3e3b8c12f2f17191692e8/160a3/parsed.png 682w' sizes='(max-width: 682px) 100vw, 682px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy'>\n    </span><br>\n<em>What I wanted: a sketch of how I wanted the content above to eventually be presented.</em></p>\n<p>This way, I could manually keep track of my progress already when writing the LaTeX document, and did not have to implement any more complex algorithms to the parser itself. Moreover, the special comments would be nicely searchable within the project and hence provided a systematic way to add more stable and considered comments throughout the text.</p>\n<hr>\n<h2>Putting it all together</h2>\n<p>Using by prior knowledge on a couple of projects, I decided to host the parsing service along with the web UI backend as a single Flask app. Some routes would work as an <code class=\"language-text\">restAPI</code> endpoints to parse documents into format which would be ready to visualise using the front-end. Using the version of <code class=\"language-text\">text2MindMap</code> <a href=\"https://github.com/tobloef\">tobloef</a> had made as a reference, I managed to scurry up a quite logical solution combining my parser, and his mind map visualisation into a one single working webapp.</p>\n<p>Moreover, having the text editor with the parsed document as a tabbed text in the UI provided a nice way to test different combinations of content: a change in the text would be reflected in the graph and could, optimistically, provide a bit more insight on how to structure the document.</p>\n<h3>Reverse traverse the tree!</h3>\n<p>For the front-end, I managed to find a non-minimized version of the previously mentioned mind map tool. By staring at the code long enough and poking around it, I managed to reverse engineer its functionality up to the point which allowed me to use it for my own, seemingly nefarious, purposes. Breaking up the gargantuan class into smaller, more logical and easily handleable pieces helped the process - but only up to a certain point.\nMore about this a bit later... Main thing being that I managed to make the solution work, and was able to make adjustments to it as needed!</p>\n<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 750px; '>\n      <span class='gatsby-resp-image-background-image' style=\"padding-bottom: 48.93617021276595%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACBklEQVQoz22SWW/aUBCF/f+l9r2R2kCUUKD5CVXVVukmQdsECEtCGhxwDHi5NnjF9texSZo+5Eqjc+0ZnTtzzmivDg44PjmmflTnsH5I7ahGrb6PxtsGrXaLZrtJsyVxekrrzWsaL1/QbJzI/4dciZJvv2ujmeY9lm0RJzHpLiXLduwkyvtzJ5OIu13Y+s/mtenNlNFkjO04FfHaWle4Wq+IwoBcitIsl0cyAqXjbj1s3yYYnpEkKZs4JNntGyhDMwyDsRCWJI7r4Cq3Ql8pJrbJn+VvksCAIkVtFOdLg8XsjvjHd6Jix2x4Aas5hTycFzla2cnl8BLj3ngiVIKuiwo8ZvqI0Lsj8a4JnAle6JP7G7LIRPkLerai3//ELtxUpJolI/Z6PRbGAuWpB1IHWwjT0EJfTNElt3YUtv6FeLsidD1yIfaDEDfacG3pJFkpTiGmLE36g35F+DhuiaUEpQHuxYDOh49EWYJvdPA9m/PuL2adb5hS0FvPuXLn4tRKRs7Qlqslw9GwMuGR0BF0Be3A56s+5uxqRBD5RGnEwFrRv5qguh3iwOHWnjHdRhSJu9ewdHUgHd7L+jyNvCcO4wgnjUW3iFxc3kjHXd3k9ud70WxZEUz8kLW/hsSuNkKbL+aMxqNqXf6NXHYp8f8u5lW5nDudzLgRtYrKhCgv2BifSdWo+v4LuXvkNjY28KAAAAAASUVORK5CYII='); background-size: cover; display: block;\"></span>\n  <img class='gatsby-resp-image-image' alt='Tabby colours!' title='Tabby colours!' src='/static/eb0d642846fdc005990d150be3688c8f/1d69c/old_ui.png' srcset='/static/eb0d642846fdc005990d150be3688c8f/4dcb9/old_ui.png 188w,\n/static/eb0d642846fdc005990d150be3688c8f/5ff7e/old_ui.png 375w,\n/static/eb0d642846fdc005990d150be3688c8f/1d69c/old_ui.png 750w,\n/static/eb0d642846fdc005990d150be3688c8f/78797/old_ui.png 1125w,\n/static/eb0d642846fdc005990d150be3688c8f/aa440/old_ui.png 1500w,\n/static/eb0d642846fdc005990d150be3688c8f/5551c/old_ui.png 1763w' sizes='(max-width: 750px) 100vw, 750px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy'>\n    </span>\n<em>Using the reverse engineered <code class=\"language-text\">text2mindmap</code> code and my own parser, this UI was created with most of the planned functionality included</em></p>\n<h3>Git gud</h3>\n<p>I was mainly writing my thesis using Overleaf. Especially with the professional tier features obtained through the university license, I found it extremely useful. Moreover, it had a github integration which I found intriguing. Having messed around with some git hooks on previous projects, I was considering a functionality, which would automatically update the map whenever I would update my thesis: Having a history of what I had done would allow me to check my progress over time.</p>\n<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 645px; '>\n      <span class='gatsby-resp-image-background-image' style=\"padding-bottom: 59.04255319148937%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7DAAAOwwHHb6hkAAACgUlEQVQoz42SS08TURiG+5PUv0BMjLqEFkI0wX9hXLggrlwoiIZgTEyIOw1uVAioXOTeyq0tLaWlLXRunfu00+v08bRcwsaESZ6Z95xk3vN97/lCkcEIw4+G6Q/3M/JkhKHhIaEHGIgMEB4MExmKEBZErhG+tnfn4V1uPejj9v0+7j2OEDqIH5BIxkkeJinrZVRNRSur4qvgVTwI2gStFs1mg8YFQbsl9gPqzTqz+X3mBC+i3xmN/iC0u7eDIn42bYPTsyJqWcEwdcqGRq1Rw2j6mIKADpeP0fApVK2eLgkyDYh6LaZPTwglDuLomo5r2SiSjFyScYS2TQu/5rOs5BjdmedbMXlleOZZrMk5lgRPkwlmZJsVu8Gi7hB6tTDGu+gkb7beMrk9xfjaBOObE4wJJEfqGZzaZV4nVvhaTBC3FUq+jVWvcmSprEopfpbSpCs1ivU2oVgqRlbLkpaOyCjHPY7kDGk5zerZMa1upyKyuKHyOb/Hx/Q208kos5kkusj4QJPYFV39ykrErQqhYr6IX/FxHRfP8S5wqbo+uiuRUNaJFZeEq3/ebxs6te4hHXTP41gzqIn8PLdKtVIllM1lsV0bwzIwLbNHV9u2g2TliZbmiJ0JUttoRganmmJT3mF9dZHcygJy4a/IdwNbXJLmiQpzJzkc1+kZWbZ1Rde02Wz1iuq+9w8zpLJfUI1P7EVHKSQXycenmEk8ZzL2jIKyIyps/t+wu67Va2JYAjbUE9ygcd6xyLQdW6LyfpTKh5fEEinmixYbJYes6d7E8Hz+gk5AO2j2Vm2Rlb/4B/f3CvmjAlslk2XVYf9mFXZ6Zl0udefakAcCTbcol00c2+UfMDdRRoCQ6JUAAAAASUVORK5CYII='); background-size: cover; display: block;\"></span>\n  <img class='gatsby-resp-image-image' alt='Versions mean progress, right?' title='Versions mean progress, right?' src='/static/cf81da05cb4c185cac5d41ac0ad6b446/af192/versions.png' srcset='/static/cf81da05cb4c185cac5d41ac0ad6b446/4dcb9/versions.png 188w,\n/static/cf81da05cb4c185cac5d41ac0ad6b446/5ff7e/versions.png 375w,\n/static/cf81da05cb4c185cac5d41ac0ad6b446/af192/versions.png 645w' sizes='(max-width: 645px) 100vw, 645px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy'>\n    </span>\n<em>Chaos documented in history!</em></p>\n<p>To automate the process, I wrote a small <a href=\"https://www.git-scm.com/docs/githooks#_pre_push\">git-hook</a> for the <code class=\"language-text\">pre-push</code> action. It would ask the user to input a description of the push in question and then try uploading it to the <strong>mongoDB</strong> on cloud with specific <code class=\"language-text\">USER</code> and <code class=\"language-text\">PROJECT</code> IDs for later retrieval. Not very secure, I admit, but hey, it works for this sort of MVP.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-bash line-numbers\"><code class=\"language-bash\"><span class=\"token shebang important\">#!/bin/bash</span>\n\n<span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"Preparing to upload latest version to MindMapper\"</span>\n<span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"Please insert update message (within quotes):\"</span>\n\n<span class=\"token comment\">#read MSG</span>\n<span class=\"token builtin class-name\">read</span> MSG <span class=\"token operator\">&lt;</span> /dev/tty\n\n\n<span class=\"token comment\"># Uploading setup:</span>\n<span class=\"token assign-left variable\">USER_ID</span><span class=\"token operator\">=</span>\n<span class=\"token assign-left variable\">PROJECT</span><span class=\"token operator\">=</span>\n<span class=\"token assign-left variable\">PARSER</span><span class=\"token operator\">=</span>\n\n<span class=\"token comment\"># File to parse and upload:</span>\n<span class=\"token assign-left variable\">FILE</span><span class=\"token operator\">=</span>\n\n<span class=\"token comment\"># read the selected file contents:</span>\n<span class=\"token assign-left variable\">JSON</span><span class=\"token operator\">=</span><span class=\"token punctuation\">$(</span>python -c <span class=\"token string\">\"import json,sys;f=open(sys.argv[1],'r');d=f.read();print(json.dumps({'msg':sys.argv[2],'txt':d}));f.close()\"</span> <span class=\"token variable\">$FILE</span> <span class=\"token variable\">$MSG</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token assign-left variable\">URL</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://tex-mind-mapper.herokuapp.com//parse/<span class=\"token variable\">$PARSER</span>/<span class=\"token variable\">$USER_ID</span>/<span class=\"token variable\">$PROJECT</span>\"</span>\n<span class=\"token assign-left variable\">STATUS</span><span class=\"token operator\">=</span><span class=\"token variable\"><span class=\"token variable\">$(</span><span class=\"token function\">curl</span> -H <span class=\"token string\">'Content-Type: application/json'</span> -X PUT -d <span class=\"token string\">\"<span class=\"token variable\">$JSON</span>\"</span> $URL --write-out %<span class=\"token punctuation\">{</span>http_code<span class=\"token punctuation\">}</span> --output /dev/null --silent<span class=\"token variable\">)</span></span>\n\n<span class=\"token builtin class-name\">echo</span> Response: <span class=\"token variable\">$STATUS</span>\n\n<span class=\"token comment\"># If the script runs successfully, allow push</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">[</span> <span class=\"token variable\">$STATUS</span> -eq <span class=\"token number\">202</span> <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">then</span>\n    <span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"UPLOAD OK\"</span>\n    <span class=\"token builtin class-name\">exit</span> <span class=\"token number\">0</span>\n<span class=\"token keyword\">else</span>\n    <span class=\"token comment\"># Otherwise raise</span>\n    <span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"UPLOAD FAILED\"</span>\n    <span class=\"token builtin class-name\">exit</span> <span class=\"token number\">1</span>\n<span class=\"token keyword\">fi</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>*The code for <strong>git push hook</strong> used to automate uploading a version of the LaTeX document as a mind map to a <strong>mongoDB</strong> database*</p>\n<h3>Too much features, too little functionality</h3>\n<p>However - a relatively big however actually - the code was absolutely abysmal. </p>\n<p>Firstly, making even smallest changes required always checking the existing code for something that would brake; I had to constantly remove things that I hope I did not need to reduce the clutter (which sometimes felt like pulling the cork from a rowing boat in full, blissful ignorance of its role) and most of the time, things ended up working, eventually, with me having no idea why. Needless to say, the trial-and-error approach had gotten out of hand.</p>\n<p>Secondly, the solution of using a \"self made\" class for the graph visualisation instead of some third-party library, which was consistent, documented and updated, was rather unnecessary. Additionally, the visualisation was cumbersome to style, which I also wanted to change. I also wanted to add support for mobile devices, which turned out to be quite a struggle with the existing script compared to the ready-made solutions provided by third party libraries.</p>\n<p>Thirdly, as I played around with the tool, I felt that some of the features I had added were not actually that useful. For example, having the version history was not as convenient as I had hoped. The extra effort of writing the description when pushing and having an additional database for such a tool felt like an overkill - especially when I was not satisfied even with the basic features. Moreover, as there was not way of comparing two versions (other than having them open on two separate windows) I did not find it useful of a tool for observing the progress.</p>\n<p>Lastly, as I did not really like the solution of sending complete files to the server to be processed as it felt risky.</p>\n<p>No, I wanted a simple solution, which I would completely know what was going on and where and had minimal clutter.</p>\n<h3><code class=\"language-text\">tl:dr</code></h3>\n<ul>\n<li>no want upkeep code I did not write</li>\n<li>plenty of bugs and hot-fixes with chewing gum </li>\n<li>some features not as useful as I had hoped</li>\n<li>me lazy</li>\n</ul>\n<p>---> start from scratch.</p>\n<hr>\n<h2>Fresh start</h2>\n<p>So, once again I was at the drawing board, but now with much more experience and clear needs. The backend of my little app (parsing, serving) I already was quite satisfied with, or I could easily just copy&#x26;paste the parts I needed, so what I essentially was missing, was the UI part.</p>\n<p>To reduce the effort of developing far too many features at the same time, without a proper plan of how to make them properly work with each other, I decided to got with the plan of <em>\"start with the bare minimum and build from there\"</em>, which, in hindsight, would had been best to adapt straight from the beginning. Oh how greed sometimes takes the hold of you when you get excited! Also, as this was practically my first time working with <em>JavaScript</em> to such an extent, a lot of the content was honestly quite trash-bin quality from the get-go...</p>\n<p>For the UI, I needed (at bare minimum, remember) a library to visualise a mind-map, i.e. a graph. I found two considerable options for this: <a href=\"https://observablehq.com/@d3/force-directed-graph\">force directed graph of D3.js</a> and the <a href=\"https://visjs.github.io/vis-network/examples/\">network graph of vis.js</a>. </p>\n<p>After reading some reviews and playing around with simple tutorials on both, I felt that the vis.js was more suitable for my needs: less hassle, no extra data structures needed and nice, editable layout. Moreover, the maps had some organising physics already built in (by far more smart people than me) which would hopefully allow me to make my graphs nice and tidy to look at - hopefully.</p>\n<h3>Cut everything!</h3>\n<p>And lo, I started creating once again. First, I removed all the references to the old <code class=\"language-text\">text2mindmap</code> tool (which I was really happy about anyway) along with practically all of the UI: all the versions, side bars, tabs and navigation would be written anew, hopefully a bit more systematically. I also removed the support for any graphs retrieved from a database: I felt that uploading the <code class=\"language-text\">LaTeX</code> files at the time when you wanted to process the document, was as much - or even less - of a hassle as storing them in some unknown database via git push actions. <em>Keep it simple, stupid</em>, right?</p>\n<p>Then, I added the <code class=\"language-text\">vis.js</code> into the system, allowing me to tweak and style the UI with some hard-coded example graphs. Oh, how easy such thing could be when things were logically divided and documented (I'm looking at you, my reverse engineered Frankenstein's monster).</p>\n<p>Finally, I implemented a script to parse the files already on the client side for the content: now only the text would be sent to the back-end to be parsed into a tree and eventually returned in a graph format which the could be easily understood by the added network component of the <code class=\"language-text\">vis.js</code> library.</p>\n<hr>\n<h2>Shiny!</h2>\n<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 750px; '>\n      <span class='gatsby-resp-image-background-image' style=\"padding-bottom: 64.36170212765958%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACKUlEQVQ4y32TWW/aUBBG+Rd9qY3vtc0qwIBZbEwSCMaYJQmEQtYqqVo1VaUoqvrQSn3vayv1/54aZwNlefg00vXM8Xx35iZ0w2BD+m00Igmpo2gCKQ0yRgE1KRBCR+r6Q95DvFNCiFXSpqSQqKpGNp2iaeVpVXv0O3P62x75ioFpmOhS8lxtQkYfNrSCSQW7nGURepwettkeVrEXDQaBzziosVPbwpYubzUlAuuRk8f6NaCIY1JL0ip47Awd2sMiecfAskzm05BwNqATNvBbDS7HIdmMiaaJjYZiYGxzBRNJCrJEvzTAntbpH3eZLA44nJ9w4NX5fb3k89xn16lyteyRSulo4hngvRRNJaz16PXq7IUOf3+cU3cqBH6RnldkPNvhz68Lrj/5dPMBdqqGKtSXgZrQcHZzHL0fMb8Ycj4Y4VgeWtrCKBToD9vsTdr09138WgsvXUN5DagmNfqRtW7Uzay6z7y5oOu6HM/2ePfhhMPukl4lJOeaBHaAk2lFrpRXOowu2CpnKFXS/Pt2yZeTgF2/y9nNMdOrMduTMqNuh2beZVE5wtTNh/t/MhQhb/dvZVtLJzlbbLEctHCtCBQEDKZtRl6HYaRG2okHeA9bhybW90/eQQ1D8kZRcLIFvp77/Lyc8P10xs34I42mzag4iffvse4Fy+t/TMkUI3tA0TapFsvYJYtqzqKZcdCj5/dcd0+Amwkitr8aVCY6y8XdmxjyZdhK/wExd5LZG1v7GAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"></span>\n  <img class='gatsby-resp-image-image' alt='My thesis!' title='My thesis!' src='/static/0112ff2cdb11a1417b54c1320fa69c27/1d69c/tmm.png' srcset='/static/0112ff2cdb11a1417b54c1320fa69c27/4dcb9/tmm.png 188w,\n/static/0112ff2cdb11a1417b54c1320fa69c27/5ff7e/tmm.png 375w,\n/static/0112ff2cdb11a1417b54c1320fa69c27/1d69c/tmm.png 750w,\n/static/0112ff2cdb11a1417b54c1320fa69c27/f3c12/tmm.png 764w' sizes='(max-width: 750px) 100vw, 750px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy'>\n    </span>\n<em>My thesis!</em></p>\n<p>In the end, I had made a product which I was rather happy with. It was simple, styled and was not abundant with partially working features. The users could upload several <code class=\"language-text\">tex</code> files, which would be scanned and combined into a single string on the client's side, then sent to the back-end to be parsed into a graph, sent back and rendered into a graph.</p>\n<p>Most of the features initially planned still existed in the final product: I could still use the special labels to create nodes from comments within the <code class=\"language-text\">tex</code> files. The different elements in the document were presented in different colours, and references within the document were shown as dotted lines. Moreover, the word count within each section or element was shown as a <code class=\"language-text\">tooltip</code> and reflected by the node size.</p>\n<p>Finally, I could unleash the hidden beauty of my thesis and stop procrastinating on actually writing it.</p>\n<h3>But...</h3>\n<p>Like always, there were many things I wish to see improved. </p>\n<p><strong>Traffic and security</strong><br>\nA lot of the functionality present in the tool is not tied to the python implementation in any logical manner. The traffic caused by sending the text to the back-end and back is completely unnecessary: all of the processing could be done on the client's computer if the parsing script was reimplemented in, for example, JavaScript, thus removing the need of sending possibly sensitive information over the network. </p>\n<p><strong>Map organisation</strong><br>\nThe mind-map generated looks satisfyingly beautiful indeed, but is it as valuable in the sense of obtaining insights on the structure and content of the parsed document? The force simulation used by the library takes into account all of the edges present in the graph, including the references: therefore the map cannot organise into a logical structure of fanning out into sections, subsections, sub-subsections etc.. Also, some other mode for the graph, such as a more tree-like presentation could bring out more of the structure. </p>\n<p><strong>Features? Maybe?</strong><br>\nI also feel that having the small text editor on the side to play around with the structure was quite helpful when drafting the content. Naturally, one could simply go and use other more suitable tools for this, but at least a button to copy the parsed document as tabbed text, json, or similar would be quite interesting to have.  </p>\n<hr>\n<p>Overall, I was quite satisfied with what had been done. You can still go and play around with the tool, for the repo and improve upon it! I hope that this'll provide some insight, or at least entertainment, to others struggling with projects written in <code class=\"language-text\">LaTeX</code>.</p>"}},"pageContext":{"slug":"texmindmapper","navContext":{"next":{"path":"/projects/cropperhead","title":"CropperHead - auto cropper AI","slug":"cropperhead","links":["https://www.github.com/PebbleBonk/CropperHead","https://www.github.com/PebbleBonk/CropperHeadUI","https://cropper-head.herokuapp.com"]},"prev":{"path":"/projects/datalibrarian","title":"DataLibrarian - Collect your data","slug":"datalibrarian","links":["https://www.github.com/PebbleBonk/Librarian"]}},"links":["https://www.github.com/PebbleBonk/TexMindMapper","https://tex-mind-mapper.herokuapp.com"]}}}