4.8 KiB
Dateiformat & Speicherstruktur von ink-notes
Dieses Dokument beschreibt die Speicherstruktur, die JSON-Dateiformate und die Versionshistorie, mit denen ink-notes Dokumente auf dem Dateisystem ablegt.
1. Verzeichnisstruktur
Notizbücher werden standardmäßig unter dem XDG-Datenpfad gespeichert:
~/.local/share/ink-notes/
└── notebooks/
├── <notebook_id_1>/
│ ├── manifest.json
│ ├── manifest.json.v0.bak (optional, Migrations-Backup)
│ ├── page_1.json
│ ├── page_1.json.corrupt-1775460000 (optional, Quarantäne bei Parsefehlern)
│ ├── page_2.json
│ └── ...
└── <notebook_id_2>/
├── manifest.json
└── page_1.json
2. Dokumenten-Manifest (manifest.json)
Das Manifest enthält Metadaten über das gesamte Dokument sowie die Reihenfolge und IDs aller Seiten:
{
"format_version": 1,
"id": "notebook-a1b2c3d4",
"title": "Mathematik Vorlesung",
"pages": [
{
"id": 1,
"background": "Grid5mm"
},
{
"id": 2,
"background": "DotGrid"
}
],
"page_ids": [1, 2],
"current_page_index": 0,
"next_page_id": 3,
"next_stroke_id": 42,
"created_at": 1775460000,
"modified_at": 1775463600
}
Felder:
format_version: Format-Versionsnummer (aktuell1, bei unversionierten Legacy-Dateien implizit0).id: Eindeutige ID des Notizbuchs (z. B. UUID oder"default").title: Vom Nutzer vergebener Anzeigename des Notizbuchs.pages: Geordnete Liste von Seitenmetadaten (id, optionalbackground).page_ids: Abwärtskompatible Liste der Seiten-IDs.current_page_index: Index der zuletzt aktiven Seite für Session-Restore.next_page_id: Inkrementierender ID-Zähler für neue Seiten.next_stroke_id: Globaler ID-Zähler für neue Striche.created_at/modified_at: UNIX-Zeitstempel in Sekunden.
3. Seitendatei (page_<id>.json)
Jede Seite wird in einer eigenen Datei gespeichert, um Lazy-Loading und schnelles inkrementelles Speichern zu ermöglichen.
{
"format_version": 1,
"id": 1,
"background": "Grid5mm",
"strokes": [
{
"id": 1,
"color": [0.12, 0.12, 0.14, 1.0],
"samples": [
{
"x": 350.2,
"y": 420.5,
"p": 0.65,
"t": 12.345
},
{
"x": 352.1,
"y": 425.8,
"p": 0.70,
"t": 12.355
}
],
"shape": null
},
{
"id": 2,
"color": [0.15, 0.35, 0.85, 1.0],
"samples": [],
"shape": {
"Rectangle": {
"top_left": { "x": 500.0, "y": 600.0 },
"width": 300.0,
"height": 200.0
}
}
}
]
}
Felder:
format_version: Format-Versionsnummer (1).id: Eindeutige ID der Seite.background: Papiermuster (Blank,Grid5mm,Lined,DotGrid).strokes: Liste der auf der Seite gezeichneten Striche und Vektorformen.id: Eindeutige ID des Strichs.color: RGBA-Farbwerte im Bereich[0.0, 1.0].samples: Rohabtastpunkte entlang des Pfads (x,yin DIN-A4-Einheiten,pDruckwert in[0.0, 1.0],tZeitstempel in Sekunden).shape: Optionales Enum für geometrische Vektorformen:Line { start, end }Rectangle { top_left, width, height }Circle { center, radius }Axes { origin, x_end, y_end, has_arrows }Triangle { p1, p2, p3 }Rhombus { center, width, height }Octahedron { center, radius }
4. Datensicherheit & Migration
Atomares Schreiben
- Daten werden in
<ziel>.tmp.<pid>.<nanos>serialisiert und perfsyncauf das Speichermedium geschrieben. - Mittels
std::fs::rename("<ziel>.tmp", "<ziel>")wird die Zieldatei auf POSIX-Systemen atomar ersetzt.
Quarantäne bei Parsefehlern
Wird eine Seitendatei beim Laden als fehlerhaft erkannt (z. B. unvollständiges oder korruptes JSON), wird sie nicht stillschweigend gelöscht oder überschrieben, sondern nach page_<id>.json.corrupt-<unix_ts> verschoben. Die Ersatzseite wird als schreibgeschützt markiert.
Migrations-Backups
Beim ersten Speichern einer Datei im Legacy-Format (Version 0) wird vor dem Überschreiben ein Backup *.v0.bak angelegt (z. B. manifest.json.v0.bak, page_1.json.v0.bak).
5. Versionshistorie
| Version | Status | Beschreibung |
|---|---|---|
| 0 | Legacy | Unversioniertes Format. format_version fehlt in JSON. Implizit als Version 0 interpretiert. |
| 1 | Aktuell | Einführung von format_version: u32 in manifest.json und page_<id>.json. Seiten-Hintergrund im Manifest gecached (pages: Vec<PageMeta>). Strenges Versionsmatching (neuere Versionen werden abgelehnt). Automatische Migration mit *.v0.bak. |