Repository navigation
Open and write FreeMind/Freeplane .mm maps - #1
Conversation
FreeMind's .mm is the de facto open interchange format for mind maps, so Cartocortex reads and writes it. Reading is the strict XML parser from the old .xmind files (no DOCTYPE, predefined entities only), on plain and gzipped files: texts (richcontent keeps its line order), notes (richcontent and the old map/Note hook), links, links between topics (arrowlink), folding, fill and text colour, bold / italic, priority (full-N) and progress (0%-100%) icons. Left-side top-level topics open as a logic-left or two-sided map. Writing goes the other way (Save as .mm and a new "Export FreeMind" button): one root node per sheet, so extra sheets may not show in FreeMind itself, and structures beyond the sideways layouts, pictures, relationships, summaries, per-word style and floating positions are not carried. The xmindxml entity decoder is exported for the reader. Agent: Vibe (Mistral, glm-5-latest-short) Relu-par-humain: Martin-PB
The first commit of this branch wrote App.tsx and README.md with the parts it did not mean to change double-encoded: every non-ASCII character (the command-key shortcut signs, arrows, ellipses) had become mojibake. Both files are rebuilt from main with the same .mm edits, so the branch now only changes what the FreeMind support needs. Agent: Vibe (Mistral, glm-5-latest-short) Relu-par-humain: Martin-PB
thierrysays
left a comment
There was a problem hiding this comment.
Relecture de la PR : le code est propre, un seul test échoue, et c'est un défaut du test (pas du lecteur).
À corriger avant fusion : a gzipped .mm opens like a plain one (src/freemind.test.ts, ligne 54)
Le test compare deux lectures du même fichier avec toEqual, mais chaque lecture génère de nouveaux identifiants (crypto.randomUUID()), y compris pour topicLink (remappé vers ces ids). Les deux résultats ne sont donc jamais égaux. C'est l'unique échec : en local, tsc passe et 82 tests sur 83 passent.
Proposition : comparer les cartes sans les identifiants.
const noIds = (r: Node[]) => JSON.stringify(r, (k, v) => (k === "id" || k === "topicLink" ? undefined : v));
// ...
expect(noIds(await fromFreemindBytes(gz))).toBe(noIds(await fromFreemindBytes(plain)));(à importer : Node depuis ./model, qui exporte déjà mk utilisé dans ce fichier.) Je n'ai pas exécuté ce correctif ; relance npm test après modification.
Point de CI. ci.yml ne se déclenche que sur main et feat/*, donc pas sur mp-*. Pour que la CI tourne sur la PR, deux options : nommer les branches feat/…, ou ajouter un déclencheur pull_request à ci.yml.
Reste à faire à la main (ta liste de vérifications) : ouvrir un vrai .mm créé dans FreeMind ou Freeplane, vérifier le rendu, puis réexporter depuis Cartocortex et rouvrir dans Freeplane. Ni l'agent ni la relecture n'ont pu le faire.
Le reste me va : lecteur XML strict (DOCTYPE refusé), couleurs validées en #rrggbb, échappement XML à l'écriture, et import qui ne remplace jamais le fichier source.
|
Correction à ma relecture : le point sur la CI était faux. |
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ranch Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Intention
Le format
.mmde FreeMind/Freeplane est le format d'échange ouvert de facto pour les cartes heuristiques (c'est aussi le format d'export de Coggle). Cette PR est la première étape du programme de compatibilité lecture/écriture avec tous les formats de mind map : un format par PR.Réalisation
src/freemind.ts(nouveau) : lecteur/écrivain.mmsur fichiers en clair et gzippés (décompression détectée par magic bytes).src/files.ts: branchemmdansdocBytes/parseDoc, filtre Ouvrir (.mm) et Enregistrer sous (« FreeMind / Freeplane (.mm) »).src/App.tsx: entrée « FreeMind (.mm) » du menu Export, après OPML.src/freemind.test.ts: 6 tests vitest (échantillon FreeMind, layout left, gzip, erreurs, aller-retour couleurs/texte/progression, hookmap/Notede FreeMind 0.9).src/files.test.ts: bloc d'aller-retour.mmviadocBytes/parseDoc.src/xmindxml.ts: le décodeur d'entités XML est exporté pour le lecteur.README.md: documentation de l'ouverture/enregistrement.mmet des pertes à l'export.Lecture : parseur XML strict (pas de DOCTYPE, entités prédéfinies seulement), textes (richcontent en conservant l'ordre des lignes via les tranches brutes), notes (richcontent et l'ancien hook
map/Note), liens, liens entre topics (arrowlink), pliage, couleurs de fond et de texte, gras/italique, icônes de priorité (full-N) et de progression (0-100 %). Un sujet de premier niveau positionné à gauche ouvre une carte logique gauche ou bilatérale (réordonnancement droite d'abord).Écriture : « Enregistrer sous .mm » + entrée Export (un
<node>par feuille,<p>par ligne). Un nœud racine par sheet : les feuilles supplémentaires peuvent ne pas s'afficher dans FreeMind lui-même. Les structures au-delà des layouts latéraux, images, relations, résumés, styles par mot et positions flottantes ne sont pas transportées.Ce que l'agent a fait et ce que l'humain a changé
npm test,tscetnpm run buildn'ont PAS été tournés par l'agent (pas de Node dans le sandbox) : à lancer avant fusion (voir ci-dessous). Pas de CI automatique :ci.ymlne se déclenche que surmainetfeat/*, pas sur les branchesmp-*.Vérifications humaines
npm testpasse (tests existants + nouveaux).npm run build(tsc + vite) passe..mmréel créé dans FreeMind/Freeplane, vérifier le rendu ; réexporter depuis Cartocortex et rouvrir dans Freeplane.Mise à jour (correctif d'encodage) : le premier commit (
d07eeb7) écrivaitApp.tsxetREADME.mdavec leurs parties inchangées doublement encodées — tous les caractères non ASCII (raccourcis ⌘, flèches, points de suspension) étaient du mojibake. Le commit75c75abreconstruit ces deux fichiers depuismainavec les mêmes ajouts.mm: la branche ne change plus que ce que le support FreeMind demande. La PR #2 (MindManager.mmap) est basée sur la branche corrigée.