release: prepare OneNote Tools 0.2.0

This commit is contained in:
2026-07-22 20:17:09 +02:00
parent edb19bfcc8
commit 41cffdc5d9
19 changed files with 423 additions and 234 deletions

View File

@@ -1,20 +1,27 @@
# Format support
## Version 0.1.0 support matrix
## Version 0.2.0 support matrix
| Input or feature | Status | Tested evidence and boundary |
| ---------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------- |
| Desktop revision-store `.one` | Supported subset | Real 34,904-byte Joplin golden; three pages |
| FSSHTTPB-packaged `.one` | Supported subset | Licensed 17,197-byte Joplin golden; one page; unfragmented data elements |
| Unknown/legacy `.one` variants | Unsupported | File type and format GUIDs are validated before traversal |
| `.onepkg`, single CAB, LZX | Supported subset | Real Joplin package: LZX `0x1203`, three CFDATA blocks, seven entries, five sections, seven pages |
| CAB LZX `0x1303` | Supported extraction | Byte-for-byte rust-cab MIT unit fixture, two text entries |
| CAB without compression | Supported extraction | Byte-for-byte rust-cab MIT unit fixture |
| CAB MSZIP | Supported extraction | rust-cab single-block fixture plus a generated two-block dictionary-chain fixture |
| CAB Quantum | Supported extraction | Pinned compcol qtm.txt payload, generated one-folder CAB, and two-frame state/sentinel tests |
| Multi-cabinet CAB / spanning files | Unsupported | Header flags and spanning folder indexes are rejected |
| `.onetoc2` package entries | Listed only | Files are identified, but notebook hierarchy and section order are not interpreted |
| Standalone `.onetoc2` | Unsupported in the app | The picker accepts only `.one` and `.onepkg` |
| Input or feature | Status | Tested evidence and boundary |
| -------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------- |
| Desktop revision-store `.one` | Supported subset | Real 34,904-byte Joplin golden; three pages and rich content |
| FSSHTTPB package-store `.one` | Supported subset | Licensed 17,197-byte Joplin golden; one page; unfragmented data elements |
| Unknown/legacy `.one` variants | Unsupported | File type and format GUIDs are validated before traversal |
| `.onepkg`, one CAB | Supported subset | Real Joplin LZX package; generated/pinned none, MSZIP, Quantum, and LZX codec fixtures |
| `.onepkg`, complete CAB set | Supported extraction | Licensed five-part libmspack set plus split-block, spanning-file, ordering, and malformed-set tests |
| Missing/inconsistent CAB parts | Rejected | Set ID, indexes, previous/next names, compression, split blocks, and spanning records must agree |
| CAB without compression | Supported extraction | Byte-for-byte rust-cab fixture |
| CAB MSZIP | Supported extraction | rust-cab single block plus generated two-block dictionary-chain fixture |
| CAB Quantum | Supported extraction | Pinned compcol payloads and generated CAB integration fixture |
| CAB LZX | Supported extraction | Real OneNote `0x1203` package and rust-cab `0x1303` fixture |
| `.onetoc2` inside a package | Supported subset | Desktop golden/hierarchy tests; FSSHTTPB dispatch uses a mocked shared-store seam, not a real golden |
| Standalone `.onetoc2` in the app | Not selectable | The picker accepts `.one`, or `.onepkg` together with `.cab` companions |
| Rich text and layout hints | Supported subset | Run formatting, paragraph properties, safe links, and bounded layout metadata |
| Tables | Supported subset | Rows, cells, nested blocks, column widths, locks, borders, and cell backgrounds |
| Images | Supported subset | Lazy, signature/header-validated PNG and JPEG resources; unsafe images stay downloadable only |
| Ink | Supported subset | Bounded delta decoding, strokes, colors, width/height, transparency, and SVG display/export |
| Embedded attachments | Supported subset | `ATTACHMENT_DECLARATION`/file-data resources remain inert until explicit download |
| Export | Supported subset | JSON, text, Markdown, inert HTML, and deterministic static notebook ZIP |
“Supported subset” is intentionally narrower than “all files with this
extension.” A successful open requires the tested desktop or FSSHTTPB OneStore
@@ -22,6 +29,8 @@ structures and content graph nodes. Malformed offsets, counts, references, CAB
checksums, paths, compressed data, and unsupported variants produce bounded
diagnostics or a controlled failure.
## OneStore and package boundaries
FSSHTTPB support covers the OneStore packaging envelope, Storage Index and
Storage Manifest, header/data-root cells, bounded revision chains, Object Group
partitions, resolved object/page-space references, and available Object Data
@@ -31,49 +40,68 @@ the store adapter rejects packages containing fragment records with a
controlled `UNSUPPORTED_FORMAT` error. Excluded object data cannot be
reconstructed from a standalone file and is likewise unsupported.
For a split package, the browser must receive the `.onepkg` and every linked
`.cab` companion in one selection. The extractor validates a complete,
uniquely indexed cabinet chain before decoding. It reassembles split CFDATA
blocks, preserves codec state across cabinets, and reconciles the CAB
`continued from previous`, `continued to next`, and `continued both` file
records. Partial sets are not opened heuristically.
The default LZX limit accepts CAB window sizes through 8 MiB, but compatibility
claims are fixture-backed only for window bits 18 (`0x1203`) and 19 (`0x1303`).
MSZIP validates the `CK` prefix, limits each compressed block to 32 KiB + 12,
decodes into a fixed-size output buffer, requires the declared output length,
and carries at most 32 KiB of history between blocks in one folder. The MSZIP
tests establish CAB extraction behavior; no redistributable MSZIP-compressed
OneNote export is currently present, so they do not establish producer-specific
`.onepkg` compatibility.
and carries at most 32 KiB of history between blocks in one logical folder.
Quantum validates level/window metadata, bounds its window to 2 MiB by default,
requires full 32 KiB intermediate frames, preserves its arithmetic models and
LZ window across frames, and injects exactly one `0xFF` CAB block sentinel.
Trailer padding is limited to the documented 0..4 zero bytes; match, frame,
output, operation, and cancellation bounds are enforced. Its tests likewise
establish CAB extraction behavior only: no redistributable Quantum-compressed
OneNote export is currently present.
LZ window across frames/cabinets, and injects exactly one `0xFF` CAB block
sentinel. Trailer, match, frame, output, operation, and cancellation bounds are
enforced.
Trailing CAB data is ignored with a warning. Reserved CAB areas are bounded and
skipped. CAB names are decoded as strict UTF-8; unmarked valid UTF-8 receives a
warning, while invalid non-ASCII legacy-code-page names are rejected rather
than guessed.
## Extracted OneNote data
## Notebook and page model
The supported section paths currently return:
Supported `.onetoc2` stores provide authored section order, nested section
groups, display names, identities, and colors. Exact normalized paths take
precedence; same-directory file identity is a guarded fallback. Recycle-bin
entries are omitted, duplicate/cyclic references are diagnosed, and readable
sections not reachable from a TOC are appended deterministically. Page levels
are interpreted as a page/subpage tree.
- section display name;
- page ID, title, created/updated timestamp when available, and page level;
- visible Unicode/extended-ASCII rich text as plain text and a text preview;
- diagnostics tied to an offset, structure, or page where available.
The supported section path returns:
It does not preserve visual position, rich-text formatting, list formatting,
tables, images, ink, equations, embedded files, audio/video, active links,
page versions/conflicts, or exports. Unsupported content objects remain visible
as diagnostics instead of being silently presented as parsed.
- section/page identities, names, timestamps, page levels, and diagnostics;
- outlines and recursively nested content blocks;
- rich-text runs with bold, italic, underline, strikeout, super/subscript,
font, size, foreground/highlight color, paragraph alignment/spacing, and
allow-listed `http`, `https`, and `mailto` links;
- tables, lazy PNG/JPEG images, embedded-file declarations, and decoded ink;
- bounded layout hints such as offsets, maximum dimensions, and alignment.
Within a supported `.onepkg`, each `.one` entry is parsed independently.
Malformed or unsupported sections are marked failed/unsupported while other
sections remain available. Package navigation is temporary normalized-path
order until `.onetoc2` interpretation is implemented.
This is not a pixel-perfect OneNote renderer. Equations, audio/video, page
versions/conflicts, and producer-specific structures outside the golden corpus
are not represented. Encountered unsupported object kinds remain visible as
diagnostics. Active notebook HTML/SVG is never injected.
## Export
All exports are created inside the existing local parser worker. They include a
versioned parser/support manifest, the readable page hierarchy, diagnostics,
and unsupported-content summaries. The static ZIP contains inert semantic HTML
plus JSON, text, Markdown, warnings, and bounded resources. Resource names are
normalized, potentially active attachment suffixes are neutralized, and only
validated image types may be embedded for automatic display.
Export is a representation of the parser-supported subset, not a round trip:
it neither emits `.one`/`.onepkg` nor promises full OneNote visual fidelity.
## Test fixtures
The exact hashes, source revisions, licences, expected page names, and CAB
The exact hashes, source revisions, licences, expected content, and CAB
structures are recorded in
[`tests/fixtures/README.md`](../tests/fixtures/README.md). Tests use no private
notebooks and do not treat a synthetic archive as proof of Microsoft OneNote