Implementing a BlocNote with Jodit
Tags: mithril, localstorage, javascript, richeditor
Published: 2020-11-17 14:47:31

Here is the first draft of a personnal project.

It's implemented using Mithril, but you can use whatever frontend library you want (uhtml,react,vue...jquery...).

The main point is that it uses the Meiosis pattern and BrowserFS for localStorage.

For the css part I use w3css.

Actual features :

  - You can save a note
  - You can display the notes list
  - You can edit a note

more to come....


You can test it here [BN](https://flems.io/#0=N4IgzgxgTg9gNnEAuA2gBgDRoLoZAMwEs4BTMZFUAOwEMBbE5EAOgAsAXOxPCGK9kvyYAeBuxoACWgwC8AHRAA3QiQDuABxhR2Cib36D28kKsIATdqxlmSyiCQC0pi6wwTCVQu0I04DyL4kMgCMCgB8clTCcB4A1hJQJHDGYOwAnqRgrCQkOiASrIn4xhzs6mBIAPSVEGZUAFZgzBBwMACuZvhwNInNMHSVNPU0AB6VMQBGYJX1MGZelQDMzAAszMHBM3NezHQezWBgupURUZBQhOrsEmBQECXsZRXVtQ1NLe2d3b28A0Oj40IU0qACFYKowCQoAAxADKlQATMw0MjKhNwZCoPgmnsqMxGuFhJVzpd2KdhCSrjc7g8nlUanVGs1Wh0uj0SH0-sMxpNprN5uwlqt1pt+TtcfijiAwkTKWTItE4gkkil0plsrldIUSMUFC86rsaAILr4bGBCABzTz6d79SoAVmF9vtNUOlToRqhPjgZst1r4OP2EEO4UiYai80Uem6h2MqkWDn04g8UNDVAkEmE2RoNigpwzWcWYRBrQgEgAcjABGBM5VWEXIgXChITo3a9nc-nM5CIN4+O4zMYaOp1MdyZVI2EJJEQHhIaRe4QA0wVkgAJwAdhAAF8MNR6IwkCxGrOQEnDEwbdcGFALSQJDIJDe7xcqDBw1eJChI24wOoaFQbhtHAbgTG0jx8G4MRuB46jgdgD7TumX4KJGChuAof4Aeh04gMBOEKGBEFUARIAxKRsHgQo2AANzhpUABU0Y0IcZASAxlSRJ+wEAMIxjWj4KPGDj4SAdFUJ+MR8SxAm4cJwRoGgEjCZoHjGgoXEBtcXQkCMPGGFCiGoYQf7dGkSA6SMNESL4foOF4JB0BU9gGFACjiZ+dDzIhAAUhD6CQv6EAAXvej4IgAHG4vCtFARkgGYPSxFoAF3goACUD5ThIwBtok7BtFA6Z0Mw7BQG0qQ+QABsIhA3GqQQKPgfDsP4IUkEgAAkwDmqF27qFZejwFoXXADFWjbroLQycYXl1XNDjdf5fAkJN0pEoQYRVelkSTSRElafVnqIblyEZrwbT8EgEiYG2GbzKZNBpAAogKI24RMpaxOhd0SA96hmc9IwA1oULXQob5UCQP1nUNBj8K9XhaBI4MgDDGYZokOYkGY0LECQPEtYYqPoxjWM2Lj+PlgeJOzr9kJgPQRCZCjX7YLtH6HW06iJQIiElakWN0D56UeYdqSerJAtlSQ9DMAEVA+c+gVHQIQE856O0HVQqQ2YuAaIQAgvrOs+dzvMkFrkTVBIsK5NzEh46QsJpKkjmRPgl0mzc9vqHCIs5b9YIwBCUJwswHgSwgPmmFQZgh6LQcYmHsJ9FQRAWoVJA+adGN5xI2KowAMjAEC+LC7ApWlaOw7uBde32iuW4HsN54Q+ASD5ze5-nveWOCEgkOJvcZntI8F7JiQAI5tIQiQ+QA5NiC+J7Xq97dblS277EiI5Xbnpw3S7ppCBXqHvWgBz3GakNcjOKCQILgZX6aPtf+cCCM7Co-f0N063GNK7wG8OoVGsIaBtAfhaHouYJCkDhgIKgbQ-r3jgAvAAlwKEghVSa92WlQAAqgAJSLqjUo5R6RtBGLHC0nJKgaETETfglRLCOTIJUKhNCJwhyoK0HMlQ0AJk-q1HGXgPAWmJDQB+zB1BUAtLg-OukSAQGujQE2TRf4XwPnnMeGNb5wJMuwSs1Yn7EROr9POwji4AElYQABUFGWJgMAy4xdDGGRZm+asjiMZKJUXrRuGjWAhyBiDRI2iMa6JvrkCQMArjH1kigCxGNCLwDMKRAAPqRS6uYYhQ0yThDAySMwKFEkUgBJSQC2StAU-+48FCEA9NXDCIAsl1JHr-UxL9ynjxiKkYxZAumQVwm0npI8mrATgL1P+LS2m-XZrDUR+9EJQ1UBIAAUtsdgPkFAAGIllaBwu-PO0yi4AHFrprkUmM3u0yACyAARa6G5rnFJuO1WEdzrorFeRUiQREX4VFifEgMNz84AoDI866cTAlgrzhCnWnzoUgp1nCjGCKwAAA1YTIthW8gyUBUZoXab3boci2g0DvKjfAbkSX525nw3M11jkj0jlCdg1imkkENmAEELESAADYVjEOsddMqbRoZ-N3G8xplKSAPJ1BAuA7AADq5hLDXUWIpX625170S3gqogUMbIIACQk2JHdWE2RHB7I+-ZjaBM7ubTWLdzqHTUY6t+ySsghOBrFMG9cJKN07plFlecPUJOYOTB5c8RZvIzM6gQOd4353+oDN6hLcKQxmSmvOaanqhP9ZmwiX0fE6K1r3aVACfWqC0ddT2Qbj4htdePCQibs5hpHvml6GbUafVLt9Olra-omQBgWv1oNi0gGzRpP5o8K35yrbcqRJA62Bu9lfN5+jzz8EQgcqAzA7zsC0QANV8BKgOw784yo7j5AAhDu9gmV8qFSoMPEe+jmaCAPIhdQsA6BXB2dO-of1kFEAgKwFQcVUYLrwbeu9X7pDNxfUVd9vdEM-sfFVBm9BFrAAwwwbcVU3ntuTXOhBhg12Prebqt52JmCqAuAIJ22cCMq0fW4BtJsu5QCgKGlN9HyYsZ8mxzjdqm68eikw9gYBQ1ISvXDMA8AOStAtD5CW1YRZp0QcejNq9h26rQ4u-Ti60XRrnqzLjwbN1zsE7LMw8woCL0qAvNwXdOP41k1lFtw7Pw4boF+2SgWWyVGYMzY0PkROZRkFOfA8txDaDAGqywQH-MZQkLB+p5G3U62uBdXdj5-OBeYKQORlhc1to1km4APtGYBc81Jy61xaPkd1Ve5JS785CfxvW8TndyY4xY9TBg-G-l2ZzMJgblNSDDZVlZ4+PGoBSfhk+nK8mr2fimyxwmK3EJgXwPgKEdiYAV1fGpx9mUFMVdI8ALb+Mds6bcHdmbB4WsKYjQGeWwTa0ZrjdlweGb5a5FPee7OGmyBaeewTaTmUaMmZ0W2XRKH0wfZ1uJDeVAbZEMELAyQX73ACDoLaxt-ZEhxzDvjaxhPO5sdGzl3WMQqeOX5j5aCPnmKHGulJfiYK+AtH8rEa6AcYtms+910gIn8ZIYXXXWn77kdPh8j+NbqQMgdUsvpVyEg65JIAXNIDX6MoYQAYzwnxve769QjwxlRv1t50tyAMnB4HATBgCMW3ySHc2Fvn-TL2AtYY-m-2Qtk7O7g7p8qAqRUMzC2V2NfiqNhJJhoCmWlddfqx8IIoNwPUGpIAUB6EYTh1WsEuYpAaNEPS3g8EgJSEDK50R3Gi4WCK9x85iBAQXqOgkhIzduCQbhdf1PAN9-dZbcJO4YIbodJSAH++b2bECOVpqHFZrxfiddwdA7q8Vj06gfJk9zCxpndB0qZYXQH8MQf0zKDUOp8QatRc6wj-o1X8DHz36NBVaLU4c5v46hIFVN2qNBphVERm9k+FGjjlCD5MOOoIPndJntnvVGrp-gIMwN2iHuEulG4FgTAeHjgYgUrlnr+A1GgRyJgXpm4MLHsmPiAGfutv7hzPtNfk+CnumFfLPhmKfNzP7AuuDjiMOOQd5hILfqoOQW4N3gwW2DwefL9pfvtB6B4H9tbAxGoUxEAlMuxGoZxIfCTumPtodlAMdqduIj5IYRHgrrbGVOImFv+jxKwD0ITDYMwHAXAGkD5EgggG4KshIAQmpMEAKobLxk9OYW0AdtIVQBjjODwP0OoPjFAEwBMDQBMEkKePOMooEkwBsGgEgAiGuE3vuAwEwAcOQLEStkwIxBICqssDxLCLCBIGsMEIsBspdPeAiGgMEGuP8mkBsgBLvBaMQDZHHBICCFoHeBINjtiFDDWBxJEBwFwMAK7kXr1OIkgK7lALmC7m7tuAxBgAxOsTqKDPsUgDQPgMaEsW7m1MFGsR4NkExntFUUDGVB6gXP+lIFoB6DEKFKUT0RWMtDGBIGcr4N0BaPccMWYBsnwEaI4emOWLLHABIIMewBHDAJUG+FAF8e1OxLoQsXAMAA4E5A4MItcY4DmPUBVN-ApGgAAKQ0ROAkATCxBeDEm6StTTIODkmUlIDUk0nbiu5mBpDABV6DFUC14Y5PEjFslQCvFzFUB4kYAClCnNT8AOD4D0DEDmQnpQiJS0AYCMw6z+Bej4A0QqnsntQ8n2gV55KODZCWgcA8nMD2jbh4nAAwAPxYitCqAOAjBICQYOaCB7SsDBD4YtSklICLACoDQukIihmqnTIRloDRn1hxnmmhR5ErDJkrCpnhkdHJn2g5kJnBARTJkCqFkWmBHRkMYJiYjtw5nql7DuFIC1n4BBnBAYCsAIgdmLAdkrAdn2gdlllmlqkalNkKB2wWgwD3gELWLoTBHej6kARgBGkXAmnDmqAkD2nfw-JoCV49Cik8lJkjA3TbjVnF42DAC3zGj+D-gQBrGZkjBBlQCXGbFgy7kbFbGVygLBADQ3DwDmASD7I5B7nV5il5nHloCPFMQQCUkgZylnnASXmGL+ANTElpDqAdTZo0T-gOZrG7kik16QUIWIkxDAA4XzByJIAlnHnUU0QflQjbEQR0A8m-lKYxCQm7IOZmCnnCTAQGJIAxitQQbEBmAvlbGu5MVIDZp7RnnUlrbOAaoSC8k0QyUqQwBqSGQ1YwVQBKaZqqSuQqWqGDwjEwWpBwW6Fnmyp3jCmjDnkarKV2lgnfz14wDbiNIWjAAeneBlx+DVJil7AOakDbg0BjTDSEp3FejsCqVCIpGkAYBnniCfRkkIBiUMUxTdDlAdTpXDiQh0VaBbFYR3mUW7kKWl7KXAGJVBUJWxXJX4n0WEo-nHlsUAW7IQBtXRXbGvmJCQllTxXCSVW1USBlSpVQCMWVzMWNV-nsWAVcU8U1k2EYU9VKlDWEr8CsCJiQY+hdwPxUDpRLFqKxAWiwA5KMKxRIC7L4DBCXWXUdUDWcmmplRSWWAbUiU+RzBmB7XJGd5HXtBxynUjQXUHZzXEk1X3WImPVrUvVbW2CCCfUHU-UnXjSEoXVXWo0dXBIek1VDXLWPUY1Qh9UJjARnl40ylJX8Uk37XfXHV-VI3nVtUQDA0uTGg4wrVDWuBnlM1Qgs1lRDWiUkl+VICc1QC3VY3sBmAE0g1k2WAS13Ugm80y2g1y2WBkU5gUUWhUW-m0UVWg32AIA0T80xBWgCU6jsA0ReX+S+D3V+hIBfki1S2l5EA6VCWbXi3VVS1mAWRzypBQ2u39WK0PUO1e3O0iUK1JVg282e1O0+0q24VyIOCkDnE8lRmPmRBnkTDsCARp3Px8AjVSUrQ0TAEeA2ku5fTYWq1rHUVKXJ1m3soW2+WG3+XmBmCkA0TulQhdAhx+lN2CD61skOA2C8AymNx51Qw0S00RVMZ0Xw3U1mD-XhXymRW91fxW1G1C1j2FS6VID6XGg0SqCQYCA3lqKYUhwynqAdXp1ikU3LH+COHxyqC14SCV2VkQUJAWjJE+SYCf1YDMAIg4FKTJ0SDgU3Sv3v1f2f3rBrjpTn0Z0S0IoEkblMksmVxtAQaJggntDfxYUMmIOtQVQMUZG9gj1DwOCxB4kiSYhGkLiYP52EkwDBTkP4NJCZFEP0lEl4OjUEPUOj3sOUPMPSUpJ4jCQPQ1W+0JgX1IDCNJWiMu7Z1imSOkCiXaWb1eJg0hw4yt23leDmQoiLDA3yMs17ESMmQiPsRkXqWuQOAw38AVDSWp3CQX1nn6Me0k2wMZ1GOMxSN+lt3PnX1ZA5id22OCNiM5h3gK0eVfWHUz1z3nWKS7m02A0mmF28Ipgl0Dpl2x0Wjx0m0a1WTkXiIOAXBOU5NL2tQC1C3A3JFmDWX1UFM5iEAVRID2i0m3XOLKqXAS3dqML8DsFQhmPmjD2JDdDeAPzA2aEgISAJVsnADAHSUJWtMgJeMekTP9VTNJPF39qd4dUXAjikCnGLgPxumaPpC15OnA3bMAwkDAAvE6xiJ8BIBxJqJaM3RgAdWUTsAx1q3FPAEbOxB5VdUsM1MSXjUsVNX-kcX0270l6HnNN2M1lMO9gfNrFri-klVQvKX1UAv5UMVAv9AgtTUtX00dVmCwA8w8KJgd6xAdMkt31UAOAU2aD9PHxICDNGhZ5DxrMpM-Pr06UjTb1QhEvUtksk2LOGSOOCuqC0uPrTOjpmTrFfQCtxI0t0veOR3e3CU+hUuKtkv86d4is+PT2-Wz3xMQvxOxMKuksSvKsel6sSBThZ3ESqvB0atitauWs6uC4k22vLNiOyOOvR0RMI001hV01tVj3Bu7Jmuwv93iuSvSZjQb0jQuVhtnURuKRT1U2GvRMJMF0ytPQsMMu3NikpFsXgRDy4h2VlUCpHkgUHm7l5PFU0T0MeA2C+nBAdUQbKKUtnkynzAwDAClUZkV6OUOkIgPnYUwCMt3MsvDNDxflIDJ0dXmg2DJHPnDtUmKR0kDsdHVsBtRPxMHYmkFvD1EAjA4x3qNKaDaAASm1Nvk6tut0ekd330uXn09CpOd7evRuuu0suNp1vs-OfvEvfvksC79tosbuvujUAcusWs-veOAcxtdOPZ-tQdfQIfAfuvoewdIeGDCkeAVvQt8lRsrvvvxAwdKuev2vdIoekdYdKuYdUc50DvKUG3W0J2m31vq1P0LtRtKGAS7J8dXMyk3PD0EW0vscTMrAvO8dzC+DAC3stsRk5uPTmRYWcfElxLQsV5HtMsnvqPse1762aeosuCEc0RrtmfeNPunHgQwDpuROZu023gTAf1YBYCiy7uOfBvOc0CudgOrBQMyeJR+BStic2cN6eeI3hsHvjuTtinTtsvpOfO7kYM2mGcDtVtHmQdgemfKVWdeld0BlREc0EqfsrvSsqdIBF2cul0DsvvEc9BldvsOR0CIuUXccV4d1GjG3nGQumdJsYtYXfOl2pcpjikNdxTkdCveOwONdTdusUt9OFvNkP7+Sml8LfzseQdleyP9v72OCFXH2Ym+CQe0c0ctc5f2UbvKdjrmRcucc5NV0V6sdG3sd-NMpYV70OSH32B53HdwDrcwDddYWjdQzjdBMu7-tfQlda7neE5XN91lMEoVNfQVe3dytpPMcQdRuJB-gBhsto+ytcv5chw+nheuVRvJ6p6nHnH40c0tQ9OEqpHNSJAS3-hQxwA0-Ghs8ARJCHEs+BTdud1nHc9C-33M-HFi8OAPci90-CTgjS-l2UUS+s+U9JB+Dgj8+S9J7q8FPC+09LYc2kA9Bc9y8JgtCyxM9HGs8oda82-2Mm+y-PmPr55oxiTa1JVj3G9M9VisDtvwAS2OFwD4Ay2QabEy2qC+9zzSP9w5Azw9Ci-CTx-aC9Ndebcm19dXcwsQ8xTywhkDsRTMCLDF-F98n09wDyyxnMcCrMACp1919l9J7wDyyLCXel6jvMBrhd9d+N-m-N9gDZkDvF9F8l+LBEc5-98FkDsrDBC1-18Cq9+nXyxlnT9rid-d9riL+59gAbht+NOF+j9j+M398RR7919z-1-j-l-yxrh78bhrAb+b-H8V9gAKR78RTLCH9b-98bB79riz-z8F+z-PPlXyhZd91+3fcfgAAEGA8wSQErHw4ZdOiA0PatfzoD58oWB-Uft-wr50BQBuXGvoAJwG7AeyZ5ZPhcS3YP8N+xAugH2QSph9RKQ-T-tgP964Cp+ULGfhfwb7AC6AAqQPr4HwB78Vga-R-jQN34Dt7QWAkvjQKigJVI+lgaPmf0IHz8r+TfXAWuFD6JASA5A3pgO3v4QCe+PAt-gX2YHSCjBGA0zv-y4FAC0BwQfARqnAGiDtwe0GAaIngHlsB2XfRYCgOADX84AFgjVFINL7AC4A9gyttYOIFwBW+lAgwU-z8GD8oWw-L-qwJKzsDTOnAogSEJX4cCRB1AkIeIKhaSCR+Zgvwafwy7KDL+KQuALfz0FUDIBIQ4wZgNMHBC-Bv-TwQAJUENCwh64XIfUK2ZkB3mJPe+v6RsDFdhIgsXIBBhsqgUsmidBwM-Rrb4dCmDpeYTxwn4rYJaLlaYaKVmHOVbOiw2lssL2GVxj+K2GykXk8ERQsuZ5LYYXgI4bAfk0ZNXggD16qBCeebAapnzKoQcSuKVD3qQETDq922uvL8p5Vro+UV6YpW2r8L8ABVm6lzc2hCIFpwiqqOvF4Ti1a6IjLaAtDEejXMCXMZmK0c9gBi0DiB+AwNGtKRwlo1p3hd3L6MSMvZkioqZ5SkdVyhikdaRVXZJuyJ+YMjSR17FwbAJ8Cdw7hzHDolaRGCoDhItw2yp4PtB8lBRbgkUbKKhaZcfBZ5OgLJxC5xswuSkBSBXjq62c+RV7ckRqK1FtdMmc7LVE8Ih5AdsOJNM0RMHxh0dtW0mTVth3daOjnR83WNmcJ05TskgrLEZnIB0AQ9-SB3L4viUJFQxjRTI4GpqKdGkBORXLLHrSVjECi4ejkL0XFR9FWsoQ2YwXkI0Q6ejhICY-GAj2XpI9XI5rCjt4wLHujaxHpAsWVxga5iHRpYmAImPvCMdM6RYjDhS3rG5iSxCYMsfAjTqti+xHogcR2K7E7diIe-Xks4MiCuC4Byoi4VCw3ACpqKUokcVqJw78A9+TTa4R2OC4WiNOoCJptGUVGriEBtLTwWuG8GSjfBJ4y2lK08Hl5HyxNfEfHX3IEjc2qnIkRe35Gmjxh+IlduXwyqQhkx9IoCSaKirXjhRSsFUZYLXAIgUBEJEUYgNVHICnxX4mwISVERtBWu0YkgOmPJEIT3ByEhwahPVGgTl2PQCCTlT-GVdZmpY9gtsPw4Gc0AZE02mJwKZbla8PE4GjKPXG5cIOLTeAmnSrDjUlux7QgKezMBfCzOCnXSDyVGZxIrmxnCptJP6CXFJKkFKNt4zMiyTdO8k9RiRKUkOVNyRTFjsZxohcSaIRwwzhiOckGsouZ1Hzn5zc4oh7QosFSb6QRBEt-x549jiZLubFt4Apbeydk13JzsiKQjYKV+SOFhSi2UwSKQIEckCTYpWkqNp0wxGhT-RqUkthlIckuT4pCYPKTpLoDJTCppxNKXACilOT3yVU8Ho42CkojLmtUiKQ1IylzsmmdJAzv1P1rCcwALPZitczABDNs4DgfqRgBmm0lRYhJZchNLGk20RpU0nyPNJpJzT+pgXW0cFIKkTtlu3UqKX1NpLRTE650laZ8TWlLkNptJHaQtNYbLSRpq0iaRtIcAPStpe0tqSp34lOUUpdU4qbO005DSmpdJa6ZiVuk6x7p2076c9OJKvSbp70z0B-Thm7Sgpf0r8h1MBknSSp2TIaXFOGlLk3p601GVtKwA0lFpRJSGeNLJlJoKZC0zGbdzGr9AcZXU+qVFMGnnSypxMnWKTLunkzZpT0paYjJJnIz6Z004WVTOZlmQkOjPG1r9JZkU1huA6PRsFKp5QxCUnrLCPtL+kqz-xXI9ZvKyVlyyDZLElaLLKejS8jpjcXGZzIEDts54FvEarU3mANN+pWzTNmAEjGuye29TCoGhM-Hy9DWEtKJkKKIl+y6mDTB8mc0zbfBqmWLUav7IabUU45J1EYAnMuY1MU5FQZ+unL+ojBM5v4qOe7IqCLAg5Xs70pxzDmk9OOYQYmgINrnVyleFoBuf1QYHNzFeGTduUInkGdype9c+gVoJ0GG8Q5LcnuWQIpQp8x5CYBXkPLUEWiH6acyngz1Tw88OeS8lEJ0WZz5yzy7PJIBxNpZzsFhfElyfnNXk2AJavAM0Oz3rKjlzIO2NiixCKRnh2gFwQyKsncjDkiyaw+nheUNERc3JQbFNjFwe5P0g573BigZwfL4sOKKwHiIbGhBNNd6+VJwKfXWJYxYgTgfKv71vkARQqZ1aAI0iUxvpIuICgGtdVRpJd8mMC7Tq3P+kOkx2P8isgpFUHm8YE18mBA4FjK+Nb6ndJSEHIkASjgGnksBt-UCJ-1AGv5fUS-TEXeSJFv9dttwroHCQSaN9fxsMO8aXEVi-C++kpFgWyLRFb9XzuIpRC-0sAjRX8kAyUjyL-OXRH6eMPiJUBgAAEWVMPScUeBAGNYDwEagcgGIoYPQbcFANiAkA0gNKA8DWE8UuLaSQncWVDNgAP5s4aAGwBaCga8k4l-Mm6YktRmLB7Qa4VJVAw6puKPQB9dUmrVcWeBSlunOpnIiUpoAfF6cDwA5GCWhLwlMpBgDWHKXiJgAsSh5neWOaQV+phzR5sczbYZL+lWjcUsUqqWegHAky9IJUvcVMt+lN0ZgBFBeYhKwlESzpcCjUT4Z-0IygZdo37yVwjlUyttjMvcWOBQRtUhLg-BoglLWW4U2ZQIC-JrKpOrS7ZR0rYhPK3lGkmlLpLnYOAtU1bBZScqGp9siZ4KtSVctKWOBDpcXZloGJnaPLXlTLP5Uw3OIfLNlbSnZb8teVYr3mgK1rgZxBUfiNGoyiFWcockwrLlUbTFYwveZ3KUViXP5RisJVHCcVXy9pZEuGLXLkpJK27AJPJVgqjm1Kvtk1MpXHLYVDKwlazNa4sqhmbK9FS8uuUYjuVWy3lbssxUYiDluklyaKorwwrIKkKvScCxS7irZVEPRlcFGcR0Aco7KtVfCrtUgYUQAqXFd8r5WYrXVrXIVbTObI+VklUDM1QGoCAS5ggRSuVdcvshUA4I7zCact1Ko4rB4-KWNfMvAjCT5VbzCyKXAqgLiN2QkwyeKsD7eN5lVqimiatr7lTy1VK+ZQdlLUela1xy+tfgD1bnKxlHVcFYSVGAdrtGP9Z0meW7W4g+1JzDcM6SjZHUwl4axwIXglpHUnoM6ntSMEbUMUp1rsINXq1XWjUF1G6wIO2vCxgxd1M6nyLyUcUJh11M6+dTKT3VJjD1hKY9UGp8jjqZZZ5S9UGsJIeBr1i6j9SOvvVIBH1gQHyBjKjaQh4iIVf9WBp8DPr5RUDFkSQHA3Lrt1RpcDQeuIDGhmyCG6DWeopFYaaAn6lxZBrw3AamZUbbwFQGVJhkiyR5ISSyN9ksL0ydggaLRtLGES-VVGishKJY0Jgs55ZRjdRSLUQ9i5t4S5gxo6ijtmNsEuMWeSLm8axNEZZOtxp9KyaS58mlYAJqk0ZjhIFJOgK7j40dQhUkmkkXBI6rsdIRFY0pg3R67sAlNRw8zS93i5bklNFJVIO3CFIOakALm7wPgDSBKahaFmyEYLQJSCapJXVT6bnW4maaQJYjJObnUmrNVwWbVELfYyTnnjXZJ81imC0Ar00lNgLKqa7PPmZbpqrVJLVFqirEdUtoUmpgZ3i1ZaStEAXLaluSk5yBJtW4rTlrK0STyuNTOdgAwS3ZbStxm6TSlqYrdbUtLkvrXVo61DaBRUbdjmNrC0GdJt7WwbYyK01zytyC2rYk5OW0EtVtwE8rRDx7CNxr5cwS5nxJPmKaytBwhVUnSM1rbyRvHfch4CPl3aRgSmi7RpM+3fkrtM26LT2pmF6qz5LU5+slpHHPbxOJtI+bsLe0faIdTK6HU5NB2dao26nH2SCSXmwKNNf25kSpFblLyOu72zrfvIYW8aHuTG48hJqJ046Oq6nQImeMu33aDtNCuOufN+0PbcdCYdTqOwZ2acqdPElnZkxcn86UdEPdThXN52gIK5TOuCYLtu3S7qdHO4Gup3U2S6kA6mmXUyLl0uSNdiug7bToYVCo1dhmvXbLvU4TaHyYO3Yfhg27WbbNW5G3UD2-hHCrdCKdtaa0UgC7yFRrcNtNqV1kaRp-4MnOwGQ3Zp213u6JhNKD2GArd6isPVfSuJ+M76RDQTVUUJixRZiFlaUbprN55jRq9AVItrO0Ue7ItOO+zoGx92gL8AEABSBuCt00B4+yGhvRSnd3htYmXu4BZXoBqKQD2+AV3Q1MLEJh1Fn0CVK3qr197rtEe+JgiC6ICpoQiwK3YbQ4Al0JUyGpfa1BH0dQKaJejvRm3ckA0IoG4HiM9GegghXd4IXsUPrLXogeEY+yhQdl30Od99yNDcGuGdDqardEANIABGQ1f6AId+5Gu3sn2d6s2ikCYLUBWD96JUDgddchs30wHEg5kX9vYwH0IGnocB1A7uoAPnUD2j+ivVmyrYbgzAEUCYFbqnWCBkN5By+sXui4P7gDe+ihcjQQVIKmmi+rcggZyCX6898ddg1QewOptS9HO8vXu3DYkGIAiwFYDQCt3NtLQMAZDTIcnL8HcD9Bp-YwfOqLB8A9oYIBMHtBW7SGNAZkshv0PMl+DQBsvVPui5oBBUEUBraLrPIxAGAa+xpFvpoMpszDQhiwym1qBmBxDa4K3SlDkSD7uDARqlNvrb2e6VD+B-dvgDXBXDBD+u3KTkHUDzLhOoTYmmWpsAIaUjqUFwx6UIX36J95hkA9EftAbgEQCIK3c4q7ZqKy1VRpQ3QaKMMGu9yNEgP-0FQL67DKkQqBc2Q1wQoAFzeo4UY8PFHw2a4CAAiA3ATB4jJmxI1kb6M9H0jTazI8kfmO7Mwj4+vAyIZTYCoNwiwFInXs6NzycYyG7qoMc2NedQFKwFYMXwFRW6DS0jdRfcdMMRHGjqh5ozgc6D2hBUVugQL4GQ2-HOe6xgo+cef0xM0Aa4LcRFCt1pB1eIcZDTCYQCd0gTgBl48MaaNZsDsjJRYKQcONOB9uyGr7gIGePTGtdnh4E7ic+gHUMDB1M45Ea2Pd7UTCRiHrAcWNrrEDW6t9TesoM3riTIJtQ7sjXCtGhTbBpyhwbSBOHRT66jk8JHX1oHxTrJ0arKawPImwTJJ69sIYuOULUal1K3YlCgDYKWTNRpY0lDFPSmKpJp3dchr1MGmeTKphJnyfeO7IBUgRF05UcCAFNjjCpxXgCNON2n3DzOsk8jQOxcUzAbpgEVQd6Pum+Dfpxk7LsDPnUHMwZ0M7if-AAiETXpSM2mdhNaK8jO+uk5qaDMHt9tMxsXe6c32ZnHAm+3k-mdBOcVOgyhmnWRsR457Z53B-mi2fqM160ABxxsxD35qN6vT-ZlvTGd70-G+65Zwc+OYH38GZ9EJ+fWOeXqymJzRphiiSSXPTm7Th+4-afoXMb6L9-x8cxfv4Ov739UJ3EyST-1cH1FF57-dQdzPhHwDZgSA+eanPQHDTV+ptSSXgNSnkDQiV844EtOTnl6352064YBqEHiDOJ3s5M2XoRmgLrUaM2BaYOILkFapx7X2b7pKmtBV5stWud4PYX+DYhiQ1IZfPL0FDch+C7GvmCKG7TGhrQzod3MkNHChhyi8YcID8GJgkhmgKwdIutQHDQR685hecP8HvDvhxiyEYEu4W+6El+o7EdjNximzy9ZY9kcCMHmlLSRlS6EaQs4HNDZRio7xel5xA1LrUOo3adaPBB2jjF1Y5Jc-N91rL-BsYxMamOMXlL1l4y-3Q0v2W7TOxvYxMB7P+6MLy9bqu5d9PaWLqVxm44xfuPuWnjdp-AJ8e+MGWAT7lgE88YhMRQzz0FlZsvXTNwnKLuVnM703iZmAEQqRKw4xcJM2XVzfdSq7Sayt-ngL3QTvO5cpO6sYzaFw7TBYQuIH3LP5mbl1blO9XQL95lNuOrGu6GDLWFsJe5amtIH+r2Vvi-hfQOUWsLebOK9qeCAuWLTPVyi9adNO-nWSSl7a8tZXOjUSSe15U2Fb2PXWSL9VzqlsQL257h9qWx60XryM1NojXZ-y0ydC0PWBzp1+6wxWb00Bw9qWj3aOYpPjaB9cBqG6PoT1hbp9s++c5DcW3sHlzH57FpVrRsbntFH10Q0fpP1n6Ub4lfc16cBZHn4bWxeJieftAf7ibaVW8zDYRu3nQbCNh8xAdd2w2ALO1gG4C0wPsmDrfNt81ybJtc25TrNqm+GwgskHObYWuC7zdS2IX3rYN8NswdQuy2tiU1ig6LdRuSmCLlNtKqIfAPEWNbDFci0za2LkWJbhtlNnRe0MTW7rNTNixbYYpsXrbo1fdlYa3G2HHbWNxwzrc1vCWDbHt33Q5jEv03RqEll25HdSO5HemeNqvXJY6vn1UtylqOwHYYpp3Y77tjE7pfKOm3RqVR6O4ZaoAetcbKtlNuZcssR3pe3RnMQrbC1eXy7bNlNo5cmPJ2KtYW1y3XaqtQdU7nlnuznfiY+X9jBdj0w8ev1NacYQ96LhFcjJj3orGdjhgBGcbN3JboChK7cZrvJWl7rJXwDPbcPgnITY9gq8XYKsH379WJqCwFd+sMVKrxd2q8HdztDGfrKWsLa1eqMY2+779pq2XeVst2GTHdiHjU3fPcGQHAt+azFrlsi2G7WxS6--fXsA1BTyD0iTXdmvF3ZrZpwG4qaWvynYH0C3BxfaDMbWx7F1nm1-ewf91trYSrBzUzIcnWKHdD463NYQc23wLLp502PdTOOBgru97h+PaIc6WSAG4YR41sbtRnsLxd-h0rfjsV2AawjzE99ZLO33C77p0+3w7UfZnBHCTavT7aV0qPvTlZ6Gxo4BFVmn78TBRw2aV3pF4WWRI8BsCQAvIdwuAMiHEHICoAiih4EAHsH7jEBTwhURAEeHITPAOEcaw6nQh8eFBiAUApECiBWDugvAUT3AfsBPB4B0gGFJgHKEKLToDwTASJxcD8ATD6A-jqAIE5ADBPKEYT2hL8ASe+PCnMsegDE+RCoginJUVJyAHSdeOsnu4Tx3k6hAvgPAMAEp2U4qfVBLo6gcJzU+VivgYAUAuJ6iAeiChpngz5gGQEdASh2nnTzJ8QquDOO8ASGJgCCHLAPJnoJ6HcEAA)


```html
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jodit/3.4.11/jodit.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/BrowserFS/2.0.0/browserfs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jodit/3.4.11/jodit.min.js"></script>


<div class="w3-container">
  <div id="app">
  
  </div>
</div>

```

```js
const merge = mergerino

const [div, span, ul, button, li] = ["div", "span", "ul", "button", "li"]

console.log(span)

const state = {
    count: 0,
    displayEditor: "block",
    displayExplorer: "none",
    contentEditor : "",
    readedFileContent: "",
    readedFileName: "",
    sesamfiles : []
}

const update = m.stream();
const states = m.stream.scan(merge, state, update)
const actions = Actions(update)

// Setup FileSystem
function setupFS() {
    BrowserFS.install(window);
    BrowserFS.configure({
        fs: "LocalStorage"
    }, function(e) {
        if (e) {
            throw e;
        }
        fs = require('fs');
    });
}

// Setup Editor
function setupEditor() {
    let saveButton = {
        text: "save",
        tooltip: "Sauvegarder le contenu de l'éditeur",
        iconURL: "https://uxwing.com/wp-content/themes/uxwing/download/03-text-editing/save.png",
        exec: actions.saveEditor
    }
    let listNotesButton = {
        text: "LIST",
        tooltip: "Lister les notes",
        exec: actions.showExplorer
    }
    let options = [
        "bold", "|", "underline", "|", ,
        "ul",
        "align", "|",
        "image", "|",
        saveButton,
        listNotesButton, "|",
        "fullsize", "|"
    ]
    editor = new Jodit("#editor", {
        sizeLG: 900,
        sizeMD: 700,
        sizeSM: 400,
        buttons: options,
        buttonsMD: options,
        buttonsSM: options,
        buttonsXS: options,
        enter: "div",
        language: "fr",
        uploader: {
            insertImageAsBase64URI: true
        },
        imageDefaultWidth: 300
    });
}

// Define all actions of the app
function Actions (update) {
  const actions = {
      showExplorer: function () {
          actions.readDir()
          update({
              displayEditor: "none",
              displayExplorer: "block",
          })
      },
      showEditor: function () {
          update({
              displayEditor: "block",
              displayExplorer: "none"
          })
      },
      saveEditor: function () {
        let content = editor.getEditorValue()                
        if (!content) return;
        let filename = prompt("nom du fichier : ")
        if (!filename) return;
        filename = `sesam-${filename}`
        update({
          contentEditor: content
        })
        fs.writeFile(filename, content, function(err) {
          fs.readFile(filename, function(err, contents) { 
            console.log(states().contentEditor);
          });
        });
      },
      readDir : function () {
         fs.readdir('/', (e, files) => {
            const sesamfiles = files.filter((f) => f.startsWith("sesam") )
            const count = sesamfiles.length
            update({ sesamfiles, count })
          })           
      },
      readFile: function (readedFileName) {
        fs.readFile(readedFileName, function(err, content) { 
            const readedFileContent = bufferToString(content)             
            update({readedFileContent, readedFileName})
            actions.showEditor()
            editor.setEditorValue(states().readedFileContent) 
        });
      }
  }
  return actions;
}

// Render a file item
function renderFileItem (filename) {
  const vnode = m("li", {onclick: () => actions.readFile(filename)}, filename)
  return vnode
}

function Explorer (state) {
  return  [ 
    m(div, "Explorer " + `nbre de fichiers : ${state.count}`),
    m(button,{onclick:actions.showEditor} ,"showeditor"),
    m(div, state.sesamfiles.map(renderFileItem))
  ]
}

function view(state, actions) {
  let style = (status) => ({style: `display:${status}`})
  m.render(app, [
   m(div, style(state.displayExplorer), Explorer(state)),
   m(div, style(state.displayEditor), m("#editor")) 
  ])
}

function main () {  
  setupFS()
  states.map(state =>  view(state, actions)) 
  setupEditor()
}

main()

/**** tools ***/
function bufferToString(buff) {
  return  String.fromCharCode.apply(null, new Uint16Array(buff)) 
}
```