Save and open documents as .num (zipped JSON)
Datei › Speichern writes a .num file: a ZIP (fflate) laid out like OpenDocument -- an uncompressed "mimetype" entry first (application/x-numolus), meta.json (format version, ISO 8601 creation time) and document.json, the same JSON the .json export writes. Opening a .num (file dialog or drag & drop) unpacks it and offers the same replace/append choice as a .json. Non-ZIPs, foreign ZIPs, a missing document.json and a newer format version fail with a clear message. The zip code is loaded on first use, like xlsx, so the main bundle does not grow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,7 @@ Eine browserbasierte Tabellenkalkulation nach dem Vorbild von **Apple Numbers**.
|
||||
```bash
|
||||
npm install
|
||||
npm run dev # Vite-Devserver
|
||||
npm run test # Vitest-Suite (Engine + Store + IO), 566 Tests
|
||||
npm run test # Vitest-Suite (Engine + Store + IO), 570 Tests
|
||||
npm run build # Typecheck + Produktionsbuild
|
||||
npm run lint # ESLint (flat config)
|
||||
```
|
||||
@@ -1088,15 +1088,16 @@ Alles clientseitig (`Blob` + `URL.createObjectURL` + `<a download>` + revoke).
|
||||
### Export
|
||||
| Format | Inhalt |
|
||||
|--------|--------|
|
||||
| `.json` | **Natives Format**, verlustfreier Round-Trip: alle Blätter, alle Tabellen-/Diagramm-Objekte mit Position & Größe, Rohformeln, Spaltenbreiten, Tab-Reihenfolge, aktives Objekt, Zellauswahl. |
|
||||
| `.num` | **Speicherformat** (Datei › Speichern): ZIP-Container mit demselben JSON wie `.json`, nur kleiner. Aufbau wie OpenDocument: zuerst `mimetype` (`application/x-numolus`, unkomprimiert), dann `meta.json` (Format-Version, Erstellzeit als ISO 8601) und `document.json`. Eine Datei aus einer neueren Format-Version wird mit klarer Meldung abgelehnt. |
|
||||
| `.json` | **Natives Format** (unkomprimiert), verlustfreier Round-Trip: alle Blätter, alle Tabellen-/Diagramm-Objekte mit Position & Größe, Rohformeln, Spaltenbreiten, Tab-Reihenfolge, aktives Objekt, Zellauswahl. |
|
||||
| `.csv` | Aktive Tabelle, **berechnete Werte**, RFC-4180-Quoting, Trennzeichen `,`/`;` wählbar, `\r\n`, optional UTF-8-BOM. |
|
||||
| `.xlsx` | Arbeitsmappe via SheetJS, **ein Worksheet je Tabellen-Objekt**. Formeln als echte Excel-Formeln (`;`→`,`, `AVG`→`AVERAGE`), immer mit gecachtem Wert. |
|
||||
| `.png` | Gewähltes Diagramm-Objekt über `chart.toBase64Image()`. |
|
||||
|
||||
### Import
|
||||
`<input type="file">` **und** Drag & Drop auf die Canvas; `.json` `.csv` `.xlsx`.
|
||||
`<input type="file">` **und** Drag & Drop auf die Canvas; `.num` `.json` `.csv` `.xlsx`.
|
||||
|
||||
- **`.json`** → Dokument *ersetzen* (Rückfrage) oder Blätter *anhängen*.
|
||||
- **`.num`** / **`.json`** → Dokument *ersetzen* (Rückfrage) oder Blätter *anhängen*.
|
||||
**v1-Dokumente** (altes Ein-Raster-Format) werden automatisch nach v2
|
||||
migriert (je altes Blatt ein Blatt mit einer gleichnamigen Tabelle). Schema
|
||||
wird validiert; bei Fehler klare Meldung, **kein Teil-Import**.
|
||||
@@ -1132,7 +1133,7 @@ Grundrechenarten: `Übersicht!B2 = =SUM(Umsatz!B2:E2)`, `D2 = =B2-C2`,
|
||||
|
||||
## Tests
|
||||
|
||||
`npm run test` — Vitest, 566 Tests:
|
||||
`npm run test` — Vitest, 570 Tests:
|
||||
|
||||
- **lexer / parser** — Präzedenz & Assoziativität (`^` vor `*/` vor `+-`, `^`
|
||||
rechts, `-2^2 = -(2^2)`), lokale/qualifizierte/quoted Bezüge, `!` **und** `::`,
|
||||
@@ -1500,7 +1501,7 @@ Grundrechenarten: `Übersicht!B2 = =SUM(Umsatz!B2:E2)`, `D2 = =B2-C2`,
|
||||
src/
|
||||
engine/ # Formel-Engine (Eigenbau) + Unit-Tests
|
||||
store/ # reaktiver Dokument-Store (v2 Canvas-Modell), Formatierung
|
||||
io/ # csv / json (Eigenbau, inkl. v1→v2), xlsx (SheetJS, lazy)
|
||||
io/ # csv / json (Eigenbau, inkl. v1→v2), num (ZIP via fflate, lazy), xlsx (SheetJS, lazy)
|
||||
components/ # AppToolbar, SettingsPanel, FormulaBar, SheetCanvas, CanvasObject,
|
||||
# TableGrid, ChartView, TextBox, ButtonView, MacrosModal, SheetTabs,
|
||||
# StatusBar, TheLogo, …
|
||||
|
||||
Reference in New Issue
Block a user