From 423f7adf1aef0ed15f708ddac37865616105bbf3 Mon Sep 17 00:00:00 2001 From: clover caruso Date: Tue, 8 Sep 2026 11:35:35 -0700 Subject: [PATCH] feat: edit outline layout and saved expansion without rewriting content Add typed position, width and saved collapse edits with a typed user-width reader flag. Preserve identities, content, unknown properties and history, and reject protected or ambiguous ancestry before publication. Cold OneNote captures verify five layout/default edits and replacement of an existing native wrapping reservation. Tests cover 768 stateful changes, publication interruptions, 12-client mixed layout/paragraph fuzzing, and core/offline regressions. Assisted-by: gpt-6-astra --- corpus/outline-edit/README.md | 24 +- .../layout/candidate/synthetic.one | Bin 0 -> 104504 bytes .../outline-edit/layout/cold/commands.jsonl | 3 + corpus/outline-edit/layout/cold/machine.json | 1 + .../cold/notebook/Open Notebook.onetoc2 | Bin 0 -> 4800 bytes .../layout/cold/notebook/synthetic.one | Bin 0 -> 108656 bytes .../layout/cold/read/environment.json | 7 + .../layout/cold/read/hierarchy.xml | 2 + .../layout/cold/read/page-000.xml | 4 + .../layout/cold/read/page-001.xml | 4 + .../layout/cold/read/page-002.xml | 5 + .../layout/cold/read/page-003.xml | 5 + .../layout/cold/read/page-004.xml | 5 + .../layout/cold/read/page-005.xml | 5 + .../layout/cold/read/page-006.xml | 5 + .../layout/cold/read/page-007.xml | 5 + .../layout/cold/read/page-008.xml | 5 + .../layout/cold/read/page-009.xml | 5 + .../layout/cold/read/page-010.xml | 4 + .../layout/cold/read/page-011.xml | 5 + .../layout/cold/read/page-012.xml | 5 + .../layout/cold/read/page-013.xml | 20 + .../layout/cold/read/page-014.xml | 5 + .../layout/cold/read/payloads.json | 1 + corpus/outline-edit/layout/cold/run.json | 18 + .../outline-edit/layout/cold/scripts/cold.ps1 | 1 + .../outline-edit/layout/cold/scripts/read.ps1 | 1 + corpus/outline-edit/layout/cold/source.json | 8 + corpus/outline-edit/layout/cold/teardown.json | 1 + .../reserved-width/candidate/synthetic.one | Bin 0 -> 134960 bytes .../reserved-width/cold/commands.jsonl | 3 + .../reserved-width/cold/machine.json | 1 + .../cold/notebook/Open Notebook.onetoc2 | Bin 0 -> 4800 bytes .../cold/notebook/synthetic.one | Bin 0 -> 134960 bytes .../reserved-width/cold/read/environment.json | 7 + .../reserved-width/cold/read/hierarchy.xml | 2 + .../reserved-width/cold/read/page-000.xml | 5 + .../reserved-width/cold/read/page-001.xml | 2 + .../reserved-width/cold/read/page-002.xml | 20 + .../reserved-width/cold/read/page-003.xml | 5 + .../reserved-width/cold/read/page-004.xml | 5 + .../reserved-width/cold/read/page-005.xml | 2 + .../reserved-width/cold/read/page-006.xml | 5 + .../reserved-width/cold/read/page-007.xml | 5 + .../reserved-width/cold/read/page-008.xml | 2 + .../reserved-width/cold/read/page-009.xml | 5 + .../reserved-width/cold/read/page-010.xml | 2 + .../reserved-width/cold/read/page-011.xml | 4 + .../reserved-width/cold/read/page-012.xml | 5 + .../reserved-width/cold/read/page-013.xml | 5 + .../reserved-width/cold/read/page-014.xml | 5 + .../reserved-width/cold/read/payloads.json | 1 + .../outline-edit/reserved-width/cold/run.json | 18 + .../reserved-width/cold/scripts/cold.ps1 | 1 + .../reserved-width/cold/scripts/read.ps1 | 1 + .../reserved-width/cold/source.json | 8 + .../reserved-width/cold/teardown.json | 1 + crates/onestore/README.md | 6 + crates/onestore/src/commit.rs | 13 + crates/onestore/src/document.rs | 3 + crates/onestore/src/lib.rs | 2 + crates/onestore/src/outline.rs | 197 ++++++++ crates/onestore/tests/outline.rs | 428 ++++++++++++++++++ fuzz/fuzz_targets/paragraph.rs | 57 ++- tools/test_outline_edit.py | 72 ++- 65 files changed, 1046 insertions(+), 6 deletions(-) create mode 100644 corpus/outline-edit/layout/candidate/synthetic.one create mode 100644 corpus/outline-edit/layout/cold/commands.jsonl create mode 100644 corpus/outline-edit/layout/cold/machine.json create mode 100644 corpus/outline-edit/layout/cold/notebook/Open Notebook.onetoc2 create mode 100644 corpus/outline-edit/layout/cold/notebook/synthetic.one create mode 100644 corpus/outline-edit/layout/cold/read/environment.json create mode 100644 corpus/outline-edit/layout/cold/read/hierarchy.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-000.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-001.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-002.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-003.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-004.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-005.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-006.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-007.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-008.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-009.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-010.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-011.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-012.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-013.xml create mode 100644 corpus/outline-edit/layout/cold/read/page-014.xml create mode 120000 corpus/outline-edit/layout/cold/read/payloads.json create mode 100644 corpus/outline-edit/layout/cold/run.json create mode 120000 corpus/outline-edit/layout/cold/scripts/cold.ps1 create mode 120000 corpus/outline-edit/layout/cold/scripts/read.ps1 create mode 100644 corpus/outline-edit/layout/cold/source.json create mode 100644 corpus/outline-edit/layout/cold/teardown.json create mode 100644 corpus/outline-edit/reserved-width/candidate/synthetic.one create mode 100644 corpus/outline-edit/reserved-width/cold/commands.jsonl create mode 100644 corpus/outline-edit/reserved-width/cold/machine.json create mode 100644 corpus/outline-edit/reserved-width/cold/notebook/Open Notebook.onetoc2 create mode 100644 corpus/outline-edit/reserved-width/cold/notebook/synthetic.one create mode 100644 corpus/outline-edit/reserved-width/cold/read/environment.json create mode 100644 corpus/outline-edit/reserved-width/cold/read/hierarchy.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-000.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-001.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-002.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-003.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-004.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-005.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-006.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-007.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-008.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-009.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-010.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-011.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-012.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-013.xml create mode 100644 corpus/outline-edit/reserved-width/cold/read/page-014.xml create mode 120000 corpus/outline-edit/reserved-width/cold/read/payloads.json create mode 100644 corpus/outline-edit/reserved-width/cold/run.json create mode 120000 corpus/outline-edit/reserved-width/cold/scripts/cold.ps1 create mode 120000 corpus/outline-edit/reserved-width/cold/scripts/read.ps1 create mode 100644 corpus/outline-edit/reserved-width/cold/source.json create mode 100644 corpus/outline-edit/reserved-width/cold/teardown.json create mode 100644 crates/onestore/src/outline.rs create mode 100644 crates/onestore/tests/outline.rs diff --git a/corpus/outline-edit/README.md b/corpus/outline-edit/README.md index ceef168c198769c378a97ea093322fa2b6e8503f..8079748ea71c25f764ac72b539e8158dd01d5497 100644 --- a/corpus/outline-edit/README.md +++ b/corpus/outline-edit/README.md @@ -17,7 +17,7 @@ movement retains them. Native XML can reorder outlines by their positions while the file's page child order remains unchanged. Explicit width sets its native user-size flag; automatic width clears that flag. OneNote regenerates height from content instead of retaining the requested height. These observations -constrain future typed operations; this corpus is not itself a writer feature. +constrain typed operations independently of the native COM replacement behavior. Persisted collapse values survive a cold open. Native keyboard collapse/expand can instead change only the client's cached view, so warm COM XML alone does @@ -38,3 +38,25 @@ Cold-open `OUTPUT/notebook` into another new output directory with the runner, The controller selects the target again after activating the native window and transfers XML as UTF-8 data. Captured authoring scripts retain their exact source; identical immutable artifacts link to one canonical corpus copy. + +`layout/candidate` applies `PreparedEdit::outline` to the five geometry and saved +collapse cases in `before`. `layout/cold` captures that Rust output through a fresh +OneNote cache. Every active identity, child/content/structure reference, child level, +and collapse default survives; text, fields, tags and explicit formatting compare +against native XML. Fixed width renders at 144 points. The automatic 360-point hint +renders narrower for this content. Stored height remains a hint; native XML reports +the content-derived height. All fourteen associated tags and 9,577 explicit format +comparisons pass for both candidate and native-saved images. + +Regenerate the layout candidate with the ignored `export_native_outline_candidates` +test in `crates/onestore/tests/outline.rs`, setting `ONESTORE_OUTLINE_OUTPUT` to a +new absolute directory. Cold-open that directory with `tools/native_runner.py`, +`--expected-pages 15 --collect-notebook`. The captured clone is removed by the runner. + +`reserved-width` starts from native `after`, whose moved outline has a reserved +wrapping width. Rust replaces it with an explicit 144-point width and clears the +obsolete reservation. Native renders at 144 points after a cold reopen, retaining +all 304 active graph objects, ten tags and 8,457 explicit formatting comparisons. +To regenerate, run `resizing_a_native_reserved_width_preserves_content` with +`ONESTORE_RESERVED_WIDTH_OUTPUT` set to a new absolute directory, then cold-open +it with the same runner arguments. diff --git a/corpus/outline-edit/layout/candidate/synthetic.one b/corpus/outline-edit/layout/candidate/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..0ca227b97b0c8cc166350cadeebfbe52b29ab467 GIT binary patch literal 104504 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 vK);3i{xO^h2!O57fRzw7SAeVZHvjoKE%US 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 Qc(&V|H5!T~Cx`R?A0pNB3IG5A literal 0 HcmV?d00001 diff --git a/corpus/outline-edit/layout/cold/read/environment.json b/corpus/outline-edit/layout/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..afecf8746ba15fd5dd0df1a79fcd8c4f79c30955 --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-05C8C84C", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/outline-edit/layout/cold/read/hierarchy.xml b/corpus/outline-edit/layout/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..a31890541f220733156062393588d89acf93b7b3 --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/outline-edit/layout/cold/read/page-000.xml b/corpus/outline-edit/layout/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..e666fa4292021029567a098f8dc7e651c32e55e5 --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-000.xml @@ -0,0 +1,4 @@ + +Target 🦀 é Link label]]> diff --git a/corpus/outline-edit/layout/cold/read/page-001.xml b/corpus/outline-edit/layout/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..68091c51e381eeac4c279aaef3dfc578e746fadd --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-001.xml @@ -0,0 +1,4 @@ + +Target 🦀 é Link label]]> diff --git a/corpus/outline-edit/layout/cold/read/page-002.xml b/corpus/outline-edit/layout/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..576dd53bdf0b7a70adfd38ceca59f1ed1c9673ba --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-002.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/page-003.xml b/corpus/outline-edit/layout/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..b96fce3a90405a7760bfd7ea5e8d21e515cb11cf --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-003.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/page-004.xml b/corpus/outline-edit/layout/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..52ede10a85cec55d38b6911cb8c5ffd59e755edd --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-004.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/page-005.xml b/corpus/outline-edit/layout/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..3d5d0fa37b58dd8bffc9931a41056086fe9093d2 --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-005.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/page-006.xml b/corpus/outline-edit/layout/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..afe24cba8a6412809555bae58376b98a8058e0b2 --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-006.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/page-007.xml b/corpus/outline-edit/layout/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..0f4ac376724d7b218af649dfc71700072e5e42c7 --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-007.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/page-008.xml b/corpus/outline-edit/layout/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..a94836f03deaed3ff3a1f4fd1ea1076739d7066a --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-008.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/page-009.xml b/corpus/outline-edit/layout/cold/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..7e2599c5dc08be4dff5fc536bac00a0f6de0b9cc --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-009.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/page-010.xml b/corpus/outline-edit/layout/cold/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..fd74b69a65ffe036bb147b4598c568b44c1a86aa --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-010.xml @@ -0,0 +1,4 @@ + +Target 🦀 é Link label]]> diff --git a/corpus/outline-edit/layout/cold/read/page-011.xml b/corpus/outline-edit/layout/cold/read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..5049b6e63a3a299f43cad76af33389ff2bc69f4b --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-011.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/page-012.xml b/corpus/outline-edit/layout/cold/read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..da020537ace7fe2193499f0beaa841b8889b8c13 --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-012.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/page-013.xml b/corpus/outline-edit/layout/cold/read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..8821b03a47918aad90f0452fa668f362851e125b --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-013.xml @@ -0,0 +1,20 @@ + +Bold 🦀 italic é color 東京
+End
]]>
Fictitious: café, 東京, مرحبا]]>
diff --git a/corpus/outline-edit/layout/cold/read/page-014.xml b/corpus/outline-edit/layout/cold/read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..aa90414961d5532eee43dfab3eee22764545818a --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/page-014.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/layout/cold/read/payloads.json b/corpus/outline-edit/layout/cold/read/payloads.json new file mode 120000 index 0000000000000000000000000000000000000000..9e1be3e2b6d87478e7c48d278ecac8ee6c97f6d0 --- /dev/null +++ b/corpus/outline-edit/layout/cold/read/payloads.json @@ -0,0 +1 @@ +../../../../paragraph-edit/before/read/payloads.json \ No newline at end of file diff --git a/corpus/outline-edit/layout/cold/run.json b/corpus/outline-edit/layout/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..a13d5e636579e6cf68ae0095e548dce8a9120173 --- /dev/null +++ b/corpus/outline-edit/layout/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/Users/clo/dev/one/evidence/m10/outline-rust-candidate-01", + "expected_pages": 15, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/outline-edit/layout/cold/scripts/cold.ps1 b/corpus/outline-edit/layout/cold/scripts/cold.ps1 new file mode 120000 index 0000000000000000000000000000000000000000..5bc2f1837e1f0b639923a80b79c517c98c5c519a --- /dev/null +++ b/corpus/outline-edit/layout/cold/scripts/cold.ps1 @@ -0,0 +1 @@ +../../../../paragraph-edit/reconciliation/keyboard/scripts/cold.ps1 \ No newline at end of file diff --git a/corpus/outline-edit/layout/cold/scripts/read.ps1 b/corpus/outline-edit/layout/cold/scripts/read.ps1 new file mode 120000 index 0000000000000000000000000000000000000000..85257c76cede599f47da88e69419a767dd6b99ee --- /dev/null +++ b/corpus/outline-edit/layout/cold/scripts/read.ps1 @@ -0,0 +1 @@ +../../../../paragraph-edit/reconciliation/keyboard/scripts/read.ps1 \ No newline at end of file diff --git a/corpus/outline-edit/layout/cold/source.json b/corpus/outline-edit/layout/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..7cc6ed56918be18a168ed0e388481c2c384d2bcb --- /dev/null +++ b/corpus/outline-edit/layout/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "synthetic.one", + "bytes": 104504, + "sha256": "3b000949d72c206f57bcdbf4ebc4aa90a738a0bf7c86f1bf4c226655b5202d59", + "mtime_ns": 1788892375964323634 + } +] diff --git a/corpus/outline-edit/layout/cold/teardown.json b/corpus/outline-edit/layout/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/outline-edit/layout/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/outline-edit/reserved-width/candidate/synthetic.one b/corpus/outline-edit/reserved-width/candidate/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..3797abfd223f3dbf0716ae058fe9f89346c50bfb GIT binary patch literal 134960 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

485@cV}?mZte^Y+`+xjap30e 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 QLtr!naD@PJu?8!D0ECZ1C;$Ke literal 0 HcmV?d00001 diff --git a/corpus/outline-edit/reserved-width/cold/notebook/synthetic.one b/corpus/outline-edit/reserved-width/cold/notebook/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..ac8f7476d676a6e2913fa75cbfc31a7d780806b7 GIT binary patch literal 134960 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 DI%wQf literal 0 HcmV?d00001 diff --git a/corpus/outline-edit/reserved-width/cold/read/environment.json b/corpus/outline-edit/reserved-width/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..9150df5da6f4c05a307886da7295cd2f12e40146 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-6B4076E4", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/outline-edit/reserved-width/cold/read/hierarchy.xml b/corpus/outline-edit/reserved-width/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa2b617fb37a70633188ec3c07eb38540037d3ea --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/outline-edit/reserved-width/cold/read/page-000.xml b/corpus/outline-edit/reserved-width/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..1658edd465fa1c2e554e3f11effbb450360d32ac --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-000.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/reserved-width/cold/read/page-001.xml b/corpus/outline-edit/reserved-width/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3a1907d895cbf6ef494b891a1e435285f976bf0 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-001.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/outline-edit/reserved-width/cold/read/page-002.xml b/corpus/outline-edit/reserved-width/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..b45e2da2204c0516783bcf28a8502206079bbd94 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-002.xml @@ -0,0 +1,20 @@ + +Bold 🦀 italic é color 東京
+End
]]>
Fictitious: café, 東京, مرحبا]]>
diff --git a/corpus/outline-edit/reserved-width/cold/read/page-003.xml b/corpus/outline-edit/reserved-width/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..1a8097183fc21fa6fb3932d87d737ebf037f71fc --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-003.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/reserved-width/cold/read/page-004.xml b/corpus/outline-edit/reserved-width/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..7c62c5933c600efbe24a92ddc0e1c5bc172ff69c --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-004.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/reserved-width/cold/read/page-005.xml b/corpus/outline-edit/reserved-width/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..6069f8963e0537c1b4a07f7de5cfd2c3b90947fc --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-005.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/outline-edit/reserved-width/cold/read/page-006.xml b/corpus/outline-edit/reserved-width/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..02f5f73ba5e1c032f699654c6cfb3f53f2a4a74a --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-006.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/reserved-width/cold/read/page-007.xml b/corpus/outline-edit/reserved-width/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..86cfb2d1f56530e3877c3a1646c9c2e5659db74e --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-007.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/reserved-width/cold/read/page-008.xml b/corpus/outline-edit/reserved-width/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..dff4cd42b2904eabbe62ff65e87d14a3a52cf5e2 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-008.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/outline-edit/reserved-width/cold/read/page-009.xml b/corpus/outline-edit/reserved-width/cold/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..07e669be011b1e226cbc998f5494274c0d4e4875 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-009.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/reserved-width/cold/read/page-010.xml b/corpus/outline-edit/reserved-width/cold/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..4ca98432db431289d758d0253212f451e22e9afd --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-010.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/outline-edit/reserved-width/cold/read/page-011.xml b/corpus/outline-edit/reserved-width/cold/read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..f09a89eefa9c7354316ccb4b2e20a1548279fbe0 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-011.xml @@ -0,0 +1,4 @@ + +Target 🦀 é Link label]]> diff --git a/corpus/outline-edit/reserved-width/cold/read/page-012.xml b/corpus/outline-edit/reserved-width/cold/read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..9a3aab496fdc34e2d9dd143619496264667a1f77 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-012.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/reserved-width/cold/read/page-013.xml b/corpus/outline-edit/reserved-width/cold/read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..187114bab395af694d3e05929ee19621bce06cc6 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-013.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/reserved-width/cold/read/page-014.xml b/corpus/outline-edit/reserved-width/cold/read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..cec9a8249e8b1d630a56cf9bde72886810e0a28c --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/page-014.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/outline-edit/reserved-width/cold/read/payloads.json b/corpus/outline-edit/reserved-width/cold/read/payloads.json new file mode 120000 index 0000000000000000000000000000000000000000..9e1be3e2b6d87478e7c48d278ecac8ee6c97f6d0 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/read/payloads.json @@ -0,0 +1 @@ +../../../../paragraph-edit/before/read/payloads.json \ No newline at end of file diff --git a/corpus/outline-edit/reserved-width/cold/run.json b/corpus/outline-edit/reserved-width/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..ba9e7a84162ac65b942305d1ad4dab920d0a3311 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/Users/clo/dev/one/evidence/m10/outline-reserved-candidate-01", + "expected_pages": 15, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/outline-edit/reserved-width/cold/scripts/cold.ps1 b/corpus/outline-edit/reserved-width/cold/scripts/cold.ps1 new file mode 120000 index 0000000000000000000000000000000000000000..5bc2f1837e1f0b639923a80b79c517c98c5c519a --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/scripts/cold.ps1 @@ -0,0 +1 @@ +../../../../paragraph-edit/reconciliation/keyboard/scripts/cold.ps1 \ No newline at end of file diff --git a/corpus/outline-edit/reserved-width/cold/scripts/read.ps1 b/corpus/outline-edit/reserved-width/cold/scripts/read.ps1 new file mode 120000 index 0000000000000000000000000000000000000000..85257c76cede599f47da88e69419a767dd6b99ee --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/scripts/read.ps1 @@ -0,0 +1 @@ +../../../../paragraph-edit/reconciliation/keyboard/scripts/read.ps1 \ No newline at end of file diff --git a/corpus/outline-edit/reserved-width/cold/source.json b/corpus/outline-edit/reserved-width/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..6a3c9fa808e5ae3c2684a57e7c1a3a6b029dbf11 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "synthetic.one", + "bytes": 134960, + "sha256": "824e9b8a1a521750417197047497f2f1c3dc4cbcb19269fb573da42a26174689", + "mtime_ns": 1788892773150136296 + } +] diff --git a/corpus/outline-edit/reserved-width/cold/teardown.json b/corpus/outline-edit/reserved-width/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/outline-edit/reserved-width/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/crates/onestore/README.md b/crates/onestore/README.md index ba65490e12ddb14398b00f73bc25e4c9851c179d..b8d720610fe1d6c48c165834b4b4449b087b7faf 100644 --- a/crates/onestore/README.md +++ b/crates/onestore/README.md @@ -52,6 +52,7 @@ harness also accepts `--client-profile release`. | `ParagraphSplit`, `PreparedEdit::split` | Split ordinary text at a UTF-16 scalar boundary, retaining the original left identities and moving children to the right | | `ParagraphJoin`, `PreparedEdit::join` | Join adjacent ordinary text while preserving inherited character styles and native text-identity rules | | `TextAttribute`, `PreparedEdit::format` | Change character formatting over a UTF-16 range while sharing immutable styles; preserve unselected runs | +| `OutlineEdit`, `PreparedEdit::outline` | Change ordinary outline position/width or a paragraph's saved expansion default, preserving identities and content | | `PreparedEdit::commit`, `PreparedEdit::commit_file` | Publish the exact prepared image under caller-held exclusion or the conservative filesystem adapter | | `read_file` | Read a snapshot under whole-file exclusion | | `read_snapshot` | Read a validated snapshot through fresh positioned I/O while the caller excludes maintenance | @@ -79,6 +80,11 @@ accepts one `0..0` span for subsequent typing. Retain the `Insertion` value for value creates different object identities. Duplicate insertion identities require reconciliation. Formatting accepts explicit attributes, preserves inherited values, and gives retired immutable styles zero current references while retaining history. +Outline layout edits use points. Width is at least 36 points; an explicit user width +and an automatic maximum-width hint remain distinct. Native layout generates the +rendered height. Saved paragraph collapse defaults can be overridden by the native +client's cached view. [Native layout captures](../../corpus/outline-edit/README.md) +verify these edits through a fresh OneNote cache, including fields and nested content. Paragraph splits preserve character formatting, retain tags on the left, and clone mutable list objects without restarting numbering. The new right paragraph/text identities belong to the retained `ParagraphSplit` intent. Its publication includes diff --git a/crates/onestore/src/commit.rs b/crates/onestore/src/commit.rs index 6bd5ed03294cfd1ec4434876863b98cd958cfce9..7bea20551acafc40915e9a770c2525df04da4073 100644 --- a/crates/onestore/src/commit.rs +++ b/crates/onestore/src/commit.rs @@ -183,6 +183,19 @@ pub struct PreparedEdit<'a> { } impl<'a> PreparedEdit<'a> { + /// Changes outline geometry or a paragraph's saved expansion state, preserving content. + pub fn outline( + source: &'a [u8], + space: ExGuid, + object: ExGuid, + edit: crate::OutlineEdit, + ) -> Result { + Ok(Self { + source, + written: edit.apply(source, space, object)?, + }) + } + /// Joins adjacent ordinary paragraphs with native left-tag and text-identity semantics. pub fn join( source: &'a [u8], diff --git a/crates/onestore/src/document.rs b/crates/onestore/src/document.rs index 73b09fec2798108a938c4f836395d5963d4e7528..b8313ad7c825bb33b38e8bf6b715dc454d4d8068 100644 --- a/crates/onestore/src/document.rs +++ b/crates/onestore/src/document.rs @@ -66,6 +66,8 @@ pub struct Layout { pub x: Option, pub y: Option, pub max_width: Option, + /// An explicit user width when true; false or absent leaves an automatic layout hint. + pub width_set_by_user: Option, pub max_height: Option, } @@ -822,6 +824,7 @@ impl<'a> Element<'a> { x: f.float(0x14001c14, 36.0)?, y: f.float(0x14001c15, 36.0)?, max_width: f.float(0x14001c1b, 36.0)?, + width_set_by_user: f.boolean(0x08001cbd)?, max_height: f.float(0x14001c1c, 36.0)?, }; let format = Format { diff --git a/crates/onestore/src/lib.rs b/crates/onestore/src/lib.rs index 379b01a43e63d64f37c057beb4eaf16c02cb894c..a9c07773f79e5aeacf87c8175a1612e93878101d 100644 --- a/crates/onestore/src/lib.rs +++ b/crates/onestore/src/lib.rs @@ -11,6 +11,7 @@ mod flush; mod formatting; mod insertion; mod objects; +mod outline; mod paragraph; mod properties; #[cfg(feature = "protected")] @@ -32,6 +33,7 @@ pub use files::FileDataReference; pub use formatting::TextAttribute; pub use insertion::Insertion; pub use objects::{Object, ObjectData, ObjectReferences, ResolvedRevision}; +pub use outline::OutlineEdit; pub use paragraph::{ParagraphJoin, ParagraphSplit}; pub use properties::{IdStream, Property, PropertySets, Value}; pub use revisions::{ExGuid, ObjectSpace, Revision, RevisionIndex}; diff --git a/crates/onestore/src/outline.rs b/crates/onestore/src/outline.rs new file mode 100644 index 0000000000000000000000000000000000000000..3c4f01f7cf20aed1e605190ac87eea4ace672711 --- /dev/null +++ b/crates/onestore/src/outline.rs @@ -0,0 +1,197 @@ +use crate::{ + Error, ExGuid, RevisionIndex, Store, + create::current_timestamps, + document::{Document, Kind}, + edit::editable_parents, + write::{PropertyObject, write_revision}, +}; +use serde::{Deserialize, Serialize}; +use std::collections::{BTreeMap, BTreeSet}; + +/// A layout or saved expansion change that preserves content and object identities. +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub enum OutlineEdit { + /// Moves an ordinary page outline to coordinates measured in points. + Position { x: f32, y: f32 }, + /// Changes an ordinary outline's maximum width in points, at least 36. + /// `user_set` distinguishes an explicit width from an automatic layout hint. + /// Height remains content-derived; any previous reserved wrapping width is cleared. + Width { points: f32, user_set: bool }, + /// Sets a paragraph's saved expansion default; native cache-local UI state can override it. + Collapsed(bool), +} + +impl OutlineEdit { + pub(crate) fn apply( + self, + source: &[u8], + space: ExGuid, + object: ExGuid, + ) -> Result, Error> { + let invalid = |message| Error { offset: 0, message }; + let values = match self { + Self::Position { x, y } => { + if !x.is_finite() || !y.is_finite() { + return Err(invalid("Outline coordinates must be finite")); + } + vec![ + (0x14001c14, (x / 36.0).to_le_bytes().to_vec()), + (0x14001c15, (y / 36.0).to_le_bytes().to_vec()), + ] + } + Self::Width { points, user_set } => { + if !points.is_finite() || points < 36.0 { + return Err(invalid( + "Outline width must be finite and at least 36 points", + )); + } + vec![ + (0x14001c1b, (points / 36.0).to_le_bytes().to_vec()), + (0x08001cbd | (u32::from(user_set) << 31), Vec::new()), + ] + } + Self::Collapsed(value) => vec![(0x0c001c11, vec![u8::from(value)])], + }; + let store = Store::parse(source)?; + let index = RevisionIndex::parse(&store)?; + index.validate_current()?; + let document = Document::parse(&index)?; + let pages: Vec<_> = document + .pages()? + .into_iter() + .filter_map(|(sid, page)| (sid == space).then_some(page)) + .collect(); + let [page] = pages.as_slice() else { + return Err(invalid("Outline editing requires a single active page")); + }; + let semantic = &document.spaces[&space]; + let view = &semantic.revisions[&semantic.contexts[&ExGuid::default()]]; + let parents = editable_parents(view, &pages, object)?; + let node = &view.nodes[&object]; + match self { + Self::Collapsed(_) => { + if !matches!(node.kind, Kind::Paragraph { .. }) { + return Err(invalid("Select a paragraph for its saved expansion state")); + } + } + _ => { + if !matches!(node.kind, Kind::Outline { .. }) + || parents.get(&object).map(Vec::as_slice) != Some(pages.as_slice()) + || !view.nodes[page].children.contains(&object) + { + return Err(invalid("Select an ordinary outline directly on the page")); + } + } + } + let mut ancestors = BTreeSet::new(); + let mut pending = vec![object]; + while let Some(id) = pending.pop() { + if !ancestors.insert(id) { + return Err(invalid("Outline ancestry contains a cycle")); + } + if id != *page && parents.get(&id).is_none_or(|parents| parents.len() != 1) { + return Err(invalid("Outline content must have one active parent")); + } + if matches!(view.nodes[&id].kind, Kind::Title) + || view.nodes[&id].extra[0] + .iter() + .any(|field| matches!(field.id, 0x88001cb4 | 0x88001cf9 | 0x88001cb2)) + { + return Err(invalid( + "Title or protected outline content cannot be changed here", + )); + } + pending.extend(parents.get(&id).into_iter().flatten().copied()); + } + let modified = current_timestamps()?.0.to_le_bytes(); + write_revision(source, space, |raw| { + let mut target = PropertyObject::from_object(&raw.objects[&object])?; + target.set( + &values + .iter() + .map(|(id, data)| (*id, data.as_slice())) + .collect::>(), + )?; + if matches!(self, Self::Width { .. }) { + target.remove(&[0x14001cdb])?; + } + if raw.objects[&object].data == crate::ObjectData::Properties(&target.bytes) { + return Ok(BTreeMap::new()); + } + target.set(&[(0x14001d7a, &modified)])?; + let mut changed = BTreeMap::from([(object, target)]); + for id in ancestors { + if id != object { + let mut ancestor = PropertyObject::from_object(&raw.objects[&id])?; + ancestor.set(&[(0x14001d7a, &modified)])?; + changed.insert(id, ancestor); + } + } + Ok(changed) + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn protection_on_the_target_or_ancestor_prevents_layout_edits() { + let source = crate::create_section("layout.one", "Text", "Author").unwrap(); + let store = Store::parse(&source).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + let document = Document::parse(&index).unwrap(); + let (sid, page) = document.pages().unwrap()[0]; + let space = &document.spaces[&sid]; + let view = &space.revisions[&space.contexts[&ExGuid::default()]]; + let outline = *view.nodes[&page] + .children + .iter() + .find(|id| matches!(view.nodes[id].kind, Kind::Outline { .. })) + .unwrap(); + let paragraph = view.nodes[&outline].children[0]; + for target in [outline, page] { + for property in [0x08001cde, 0x08001cb4, 0x08001cf9, 0x08001cb2] { + for enabled in [false, true] { + let bytes = write_revision(&source, sid, |raw| { + let mut object = PropertyObject::from_object(&raw.objects[&target])?; + object.set(&[(property | (u32::from(enabled) << 31), &[])])?; + Ok(BTreeMap::from([(target, object)])) + }) + .unwrap(); + for (object, edit) in [ + (outline, OutlineEdit::Position { x: 72.0, y: 72.0 }), + ( + outline, + OutlineEdit::Width { + points: 144.0, + user_set: true, + }, + ), + (paragraph, OutlineEdit::Collapsed(true)), + ] { + assert_eq!( + edit.apply(&bytes, sid, object).is_err(), + enabled, + "{target} {property:x} {edit:?}" + ); + } + } + } + } + let duplicated = write_revision(&source, sid, |raw| { + let mut object = PropertyObject::from_object(&raw.objects[&outline])?; + let reference = object.reference(paragraph)?; + object.set(&[(0x24001c20, &reference.repeat(2))])?; + Ok(BTreeMap::from([(outline, object)])) + }) + .unwrap(); + assert!( + OutlineEdit::Collapsed(true) + .apply(&duplicated, sid, paragraph) + .is_err() + ); + } +} diff --git a/crates/onestore/tests/outline.rs b/crates/onestore/tests/outline.rs new file mode 100644 index 0000000000000000000000000000000000000000..94be3a4363fbff3f9aa083cd98f53e77cb942bcb --- /dev/null +++ b/crates/onestore/tests/outline.rs @@ -0,0 +1,428 @@ +use onestore::{ + ExGuid, OutlineEdit as Edit, PreparedEdit, RevisionIndex, Store, + document::{Document, Kind}, +}; +use std::collections::BTreeSet; + +#[path = "support/current.rs"] +mod current; +#[path = "support/disk.rs"] +mod disk; + +const SOURCE: &[u8] = include_bytes!("../../../corpus/outline-edit/before/notebook/synthetic.one"); + +fn cases(document: &Document<'_>) -> Vec<(String, ExGuid, ExGuid, Edit)> { + let mut cases = Vec::new(); + for (sid, page) in document.pages().unwrap() { + let space = &document.spaces[&sid]; + let view = &space.revisions[&space.contexts[&ExGuid::default()]]; + let Kind::Metadata { + title: Some(name), .. + } = &view.nodes[&view.roots[&2]].kind + else { + panic!() + }; + let edit = match name.as_str() { + "Move outline" => Edit::Position { x: 180.0, y: 216.0 }, + "Resize outline" => Edit::Width { + points: 144.0, + user_set: true, + }, + "Automatic outline size" => Edit::Width { + points: 360.0, + user_set: false, + }, + "Collapse subtree" => Edit::Collapsed(true), + "Expand subtree" => Edit::Collapsed(false), + _ => continue, + }; + let mut object = *view.nodes[&page] + .children + .iter() + .find(|id| matches!(view.nodes[id].kind, Kind::Outline { .. })) + .unwrap(); + if matches!(edit, Edit::Collapsed(_)) { + object = *view.nodes[&object].children.iter().find(|id| { + view.nodes[id].content.first().is_some_and(|text| matches!( + &view.nodes[text].kind, Kind::RichText { text, .. } if text.starts_with("Target ") + )) + }).unwrap(); + } + cases.push((name.clone(), sid, object, edit)); + } + assert_eq!(cases.len(), 5); + cases +} + +#[test] +fn geometry_and_expansion_preserve_unrelated_properties_objects_and_history() { + let store = Store::parse(SOURCE).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + let document = Document::parse(&index).unwrap(); + for (name, sid, object, edit) in cases(&document) { + let restored = serde_json::from_value(serde_json::to_value(edit).unwrap()).unwrap(); + assert_eq!(edit, restored); + let prepared = PreparedEdit::outline(SOURCE, sid, object, restored).unwrap(); + let after_store = Store::parse(prepared.as_bytes()).unwrap(); + assert!(after_store.checksum_mismatches.is_empty()); + let after_index = RevisionIndex::parse(&after_store).unwrap(); + after_index.validate_current().unwrap(); + let after_document = Document::parse(&after_index).unwrap(); + let space = &document.spaces[&sid]; + let before = &space.revisions[&space.contexts[&ExGuid::default()]]; + let space = &after_document.spaces[&sid]; + let after = &space.revisions[&space.contexts[&ExGuid::default()]]; + let mut changed = BTreeSet::from([before.roots[&2]]); + let mut pending = vec![object]; + while let Some(id) = pending.pop() { + if !changed.insert(id) { + continue; + } + pending.extend(before.nodes.iter().filter_map(|(parent, node)| { + node.children + .iter() + .chain(&node.content) + .chain(&node.structure) + .any(|child| *child == id) + .then_some(*parent) + })); + } + assert_eq!( + before.nodes.keys().collect::>(), + after.nodes.keys().collect::>() + ); + for (id, node) in &before.nodes { + let mut expected = serde_json::to_value(node).unwrap(); + let actual = serde_json::to_value(&after.nodes[id]).unwrap(); + if changed.contains(id) { + expected["modified"] = actual["modified"].clone(); + } + if *id == object { + match edit { + Edit::Position { x, y } => { + expected["layout"]["x"] = x.into(); + expected["layout"]["y"] = y.into(); + } + Edit::Width { points, user_set } => { + expected["layout"]["max_width"] = points.into(); + expected["layout"]["width_set_by_user"] = user_set.into(); + let fields = expected["extra"][0].as_array_mut().unwrap(); + fields.retain(|field| field["id"].as_u64() != Some(0x14001cdb)); + } + Edit::Collapsed(value) => { + expected["kind"]["collapse_state"] = u8::from(value).into() + } + } + } + let mut actual = actual; + // Property order is not semantic; every property and nested value still compares exactly. + expected["extra"][0] + .as_array_mut() + .unwrap() + .sort_by_key(|field| field["id"].as_u64().unwrap()); + actual["extra"][0] + .as_array_mut() + .unwrap() + .sort_by_key(|field| field["id"].as_u64().unwrap()); + assert_eq!(actual, expected, "{name}: {id}"); + } + for (space_id, old_space) in &index.spaces { + for revision in old_space.revisions.keys() { + let old = index.resolve(*space_id, *revision).unwrap(); + let retained = after_index.resolve(*space_id, *revision).unwrap(); + assert_eq!(old.roots, retained.roots); + for (id, value) in old.objects { + assert_eq!(value.data, retained.objects[&id].data); + } + } + if *space_id != sid { + assert_eq!(old_space.labels, after_index.spaces[space_id].labels); + } + } + let again = PreparedEdit::outline(prepared.as_bytes(), sid, object, edit).unwrap(); + assert_eq!(again.as_bytes(), prepared.as_bytes()); + } +} + +#[test] +fn invalid_geometry_and_non_outline_targets_are_rejected() { + let store = Store::parse(SOURCE).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + let document = Document::parse(&index).unwrap(); + for (_, sid, object, _) in cases(&document) { + for value in [f32::NAN, f32::INFINITY, f32::NEG_INFINITY] { + for edit in [ + Edit::Position { x: value, y: 0.0 }, + Edit::Position { x: 0.0, y: value }, + Edit::Width { + points: value, + user_set: true, + }, + ] { + assert!(PreparedEdit::outline(SOURCE, sid, object, edit).is_err()); + } + } + for points in [-1.0, 0.0, 35.999] { + assert!( + PreparedEdit::outline( + SOURCE, + sid, + object, + Edit::Width { + points, + user_set: false + } + ) + .is_err() + ); + } + let space = &document.spaces[&sid]; + let view = &space.revisions[&space.contexts[&ExGuid::default()]]; + for (id, node) in &view.nodes { + if !matches!(node.kind, Kind::Outline { .. }) { + assert!( + PreparedEdit::outline(SOURCE, sid, *id, Edit::Position { x: 72.0, y: 72.0 }) + .is_err() + ); + } + if matches!(node.kind, Kind::Title) { + let mut descendants = node.children.clone(); + while let Some(child) = descendants.pop() { + descendants.extend(&view.nodes[&child].children); + for edit in [ + Edit::Position { x: 72.0, y: 72.0 }, + Edit::Width { + points: 144.0, + user_set: true, + }, + Edit::Collapsed(true), + ] { + assert!(PreparedEdit::outline(SOURCE, sid, child, edit).is_err()); + } + } + } + if !matches!(node.kind, Kind::Paragraph { .. }) { + assert!(PreparedEdit::outline(SOURCE, sid, *id, Edit::Collapsed(true)).is_err()); + } + } + assert!( + PreparedEdit::outline(SOURCE, ExGuid::default(), object, Edit::Collapsed(true)) + .is_err() + ); + assert!( + PreparedEdit::outline(SOURCE, sid, ExGuid::default(), Edit::Collapsed(true)).is_err() + ); + } +} + +#[test] +fn resizing_a_native_reserved_width_preserves_content() { + let source = include_bytes!("../../../corpus/outline-edit/after/notebook/synthetic.one"); + let store = Store::parse(source).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + let document = Document::parse(&index).unwrap(); + let (_, sid, object, _) = cases(&document) + .into_iter() + .find(|(name, ..)| name == "Move outline") + .unwrap(); + let space = &document.spaces[&sid]; + let before = &space.revisions[&space.contexts[&ExGuid::default()]]; + assert!( + before.nodes[&object].extra[0] + .iter() + .any(|p| p.id == 0x14001cdb) + ); + let edit = PreparedEdit::outline( + source, + sid, + object, + Edit::Width { + points: 144.0, + user_set: true, + }, + ) + .unwrap(); + let after_store = Store::parse(edit.as_bytes()).unwrap(); + let after_index = RevisionIndex::parse(&after_store).unwrap(); + let after_document = Document::parse(&after_index).unwrap(); + let space = &after_document.spaces[&sid]; + let after = &space.revisions[&space.contexts[&ExGuid::default()]]; + assert!( + !after.nodes[&object].extra[0] + .iter() + .any(|p| p.id == 0x14001cdb) + ); + assert_eq!(after.nodes[&object].layout.max_width, Some(144.0)); + for (id, node) in &before.nodes { + assert_eq!(node.children, after.nodes[id].children); + assert_eq!(node.content, after.nodes[id].content); + if matches!(node.kind, Kind::RichText { .. }) { + assert_eq!( + serde_json::to_value(node).unwrap(), + serde_json::to_value(&after.nodes[id]).unwrap() + ); + } + } + if let Some(output) = std::env::var_os("ONESTORE_RESERVED_WIDTH_OUTPUT") { + let output = std::path::PathBuf::from(output); + assert!(output.is_absolute()); + std::fs::create_dir(&output).unwrap(); + std::fs::write(output.join("synthetic.one"), edit.as_bytes()).unwrap(); + } +} + +#[test] +fn outline_publication_interruptions_reopen_as_complete_old_or_new_layout() { + let source = onestore::create_section("layout.one", "Before 🦀 after", "Author").unwrap(); + let store = Store::parse(&source).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + let document = Document::parse(&index).unwrap(); + let (sid, page) = document.pages().unwrap()[0]; + let space = &document.spaces[&sid]; + let view = &space.revisions[&space.contexts[&ExGuid::default()]]; + let outline = *view.nodes[&page] + .children + .iter() + .find(|id| matches!(view.nodes[id].kind, Kind::Outline { .. })) + .unwrap(); + let paragraph = view.nodes[&outline].children[0]; + for (object, operation) in [ + (outline, Edit::Position { x: 216.0, y: 72.0 }), + ( + outline, + Edit::Width { + points: 144.0, + user_set: true, + }, + ), + (paragraph, Edit::Collapsed(true)), + ] { + let edit = PreparedEdit::outline(&source, sid, object, operation).unwrap(); + let before = current::current(&source); + let after = current::current(edit.as_bytes()); + for write_limit in [17, 4096] { + let disk = |fail_at| disk::Disk { + visible: source.clone(), + durable: source.clone(), + operation: 0, + fail_at, + write_limit, + random: 1927, + }; + let mut success = disk(None); + edit.commit(&mut success).unwrap(); + assert_eq!(success.durable, edit.as_bytes()); + for at in 1..=success.operation { + let mut interrupted = disk(Some(at)); + let failure = edit.commit(&mut interrupted).unwrap_err(); + let actual = current::current(&interrupted.durable); + assert!( + actual == before || actual == after, + "{operation:?} operation {at}" + ); + if failure.state == onestore::CommitState::NotCommitted { + assert_eq!(actual, before); + } + } + } + } +} + +#[test] +fn repeated_geometry_changes_and_expansion_match_an_independent_model() { + let original = onestore::create_section("layout.one", "Before 🦀 é\rafter", "Author").unwrap(); + let store = Store::parse(&original).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + let document = Document::parse(&index).unwrap(); + let (sid, page) = document.pages().unwrap()[0]; + let space = &document.spaces[&sid]; + let view = &space.revisions[&space.contexts[&ExGuid::default()]]; + let outline = *view.nodes[&page] + .children + .iter() + .find(|id| matches!(view.nodes[id].kind, Kind::Outline { .. })) + .unwrap(); + let paragraph = view.nodes[&outline].children[0]; + let text = view.nodes[¶graph].content[0]; + for seed in 1..=16_u64 { + let mut rng = seed; + let mut source = original.clone(); + let mut layout = serde_json::to_value(&view.nodes[&outline].layout).unwrap(); + let mut collapsed = None; + for step in 0..48 { + rng ^= rng << 13; + rng ^= rng >> 7; + rng ^= rng << 17; + let (object, edit) = match step % 3 { + 0 => { + let x = ((rng % 400) as f32 - 100.0) * 18.0; + let y = ((rng % 217) as f32 - 60.0) * 18.0; + layout["x"] = x.into(); + layout["y"] = y.into(); + (outline, Edit::Position { x, y }) + } + 1 => { + let points = (2 + rng % 86) as f32 * 18.0; + layout["max_width"] = points.into(); + layout["width_set_by_user"] = (rng & 1 != 0).into(); + ( + outline, + Edit::Width { + points, + user_set: rng & 1 != 0, + }, + ) + } + _ => { + collapsed = Some(u8::from(rng & 1 != 0)); + (paragraph, Edit::Collapsed(rng & 1 != 0)) + } + }; + source = PreparedEdit::outline(&source, sid, object, edit) + .unwrap() + .as_bytes() + .to_vec(); + let store = Store::parse(&source).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + index.validate_current().unwrap(); + let document = Document::parse(&index).unwrap(); + let space = &document.spaces[&sid]; + let current = &space.revisions[&space.contexts[&ExGuid::default()]]; + assert_eq!( + serde_json::to_value(¤t.nodes[&outline].layout).unwrap(), + layout + ); + let Kind::Paragraph { collapse_state, .. } = ¤t.nodes[¶graph].kind else { + panic!() + }; + assert_eq!(*collapse_state, collapsed); + assert_eq!( + current.nodes[&outline].children, + view.nodes[&outline].children + ); + assert_eq!( + serde_json::to_value(¤t.nodes[&text]).unwrap(), + serde_json::to_value(&view.nodes[&text]).unwrap() + ); + } + } +} + +#[test] +#[ignore = "exports public-API outline candidates for cold native validation"] +fn export_native_outline_candidates() { + let output = std::path::PathBuf::from(std::env::var_os("ONESTORE_OUTLINE_OUTPUT").unwrap()); + assert!(output.is_absolute()); + std::fs::create_dir(&output).unwrap(); + let store = Store::parse(SOURCE).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + let document = Document::parse(&index).unwrap(); + let mut bytes = SOURCE.to_vec(); + for (_, sid, object, edit) in cases(&document) { + bytes = PreparedEdit::outline(&bytes, sid, object, edit) + .unwrap() + .as_bytes() + .to_vec(); + } + std::fs::write(output.join("synthetic.one"), bytes).unwrap(); +} diff --git a/fuzz/fuzz_targets/paragraph.rs b/fuzz/fuzz_targets/paragraph.rs index a7600901c0d5118d31963e56b19ea365bced0b32..dbb663bf828dd4e32e13aee1b59fb24635a7db19 100644 --- a/fuzz/fuzz_targets/paragraph.rs +++ b/fuzz/fuzz_targets/paragraph.rs @@ -1,8 +1,8 @@ #![no_main] use libfuzzer_sys::fuzz_target; use onestore::{ - CommitState, ExGuid, Insertion, ParagraphJoin, ParagraphSplit, PreparedEdit, RevisionIndex, - Store, TextAttribute as A, + CommitState, ExGuid, Insertion, OutlineEdit, ParagraphJoin, ParagraphSplit, PreparedEdit, + RevisionIndex, Store, TextAttribute as A, document::{Document, Kind}, }; use std::sync::LazyLock; @@ -38,6 +38,11 @@ static SOURCE: LazyLock<(Vec, ExGuid, ExGuid)> = LazyLock::new(|| { fuzz_target!(|input: &[u8]| { let (source, sid, outline) = &*SOURCE; + if let Ok(operation) = serde_json::from_slice::(input) + && let Ok(edit) = PreparedEdit::outline(source, *sid, *outline, operation) + { + current::current(edit.as_bytes()); + } if let Ok(intent) = serde_json::from_slice::(input) && let Ok(edit) = PreparedEdit::split(source, *sid, &intent) { @@ -94,7 +99,41 @@ fuzz_target!(|input: &[u8]| { .collect(); let mut expected_text = Vec::new(); let mut expected_graph = Vec::new(); - let edit = if step[1] & 8 != 0 && !pairs.is_empty() { + let mut expected_layout = None; + let mut expected_collapse = None; + let edit = if step[1] & 16 != 0 { + let mut layout = serde_json::to_value(&view.nodes[outline].layout).unwrap(); + let (object, operation) = match (step[1] >> 5) % 3 { + 0 => { + let x = (f32::from(step[2]) - 64.0) * 18.0; + let y = f32::from(step[3]) * 18.0; + layout["x"] = x.into(); + layout["y"] = y.into(); + (*outline, OutlineEdit::Position { x, y }) + } + 1 => { + let points = (2.0 + f32::from(step[2])) * 18.0; + let user_set = step[3] & 1 != 0; + layout["max_width"] = points.into(); + layout["width_set_by_user"] = user_set.into(); + (*outline, OutlineEdit::Width { points, user_set }) + } + _ => { + let paragraph = paragraphs[usize::from(step[2]) % paragraphs.len()]; + let collapsed = step[3] & 1 != 0; + expected_collapse = Some((paragraph, collapsed)); + (paragraph, OutlineEdit::Collapsed(collapsed)) + } + }; + expected_layout = Some(layout); + for (id, node) in &view.nodes { + expected_graph.push((*id, node.children.clone(), node.content.clone())); + if matches!(node.kind, Kind::RichText { .. }) { + expected_text.push((*id, characters(view, *id))); + } + } + PreparedEdit::outline(source, *sid, object, operation).unwrap() + } else if step[1] & 8 != 0 && !pairs.is_empty() { let (parent, left, right) = pairs[usize::from(step[2]) % pairs.len()]; let a = view.nodes[&left].content[0]; let b = view.nodes[&right].content[0]; @@ -148,6 +187,18 @@ fuzz_target!(|input: &[u8]| { let after_document = Document::parse(&after_index).unwrap(); let space = &after_document.spaces[sid]; let after_view = &space.revisions[&space.contexts[&ExGuid::default()]]; + if let Some(expected) = expected_layout { + assert_eq!( + serde_json::to_value(&after_view.nodes[outline].layout).unwrap(), + expected + ); + } + if let Some((id, expected)) = expected_collapse { + let Kind::Paragraph { collapse_state, .. } = after_view.nodes[&id].kind else { + panic!() + }; + assert_eq!(collapse_state, Some(u8::from(expected))); + } for (id, expected) in expected_text { assert_eq!(characters(after_view, id), expected); } diff --git a/tools/test_outline_edit.py b/tools/test_outline_edit.py index 099a6dc346da3838c75b114adac285e4992d97a1..a356bbbfcb154765fffda6321e7686e050aa60e0 100644 --- a/tools/test_outline_edit.py +++ b/tools/test_outline_edit.py @@ -17,6 +17,75 @@ compare = runpy.run_path(str(ROOT / 'tools/verify-document.py'))['compare'] class OutlineEditTest(unittest.TestCase): + def cold_layout(self, fixture): + models = {} + with TemporaryDirectory() as temporary: + for phase, notebook in [('candidate', fixture / 'candidate'), ('cold', fixture / 'cold/notebook')]: + folder = Path(temporary) / phase + shutil.copytree(fixture / 'cold/read', folder / 'read') + compare(notebook, folder / 'read') + subprocess.run([EXPORTER, notebook / 'synthetic.one', folder / 'model'], check=True) + model = json.loads((folder / 'model/document.json').read_text()) + models[phase] = {r['nodes'][r['roots']['2']]['kind']['title']: (r, page) + for _, _, r, page in ordered_pages(model)} + captures = {page.get('name'): page for path in (fixture / 'cold/read').glob('page-*.xml') + for page in [ET.parse(path).getroot()]} + self.assertEqual(len(models['candidate']), 15) + self.assertEqual(models['candidate'].keys(), models['cold'].keys()) + for name, (old, page) in models['candidate'].items(): + new, saved_page = models['cold'][name] + self.assertEqual(page, saved_page) + for oid, node in walk(old, page): + actual = new['nodes'][oid] + for key in ('children', 'content', 'structure', 'child_level'): + self.assertEqual(actual[key], node[key], (name, oid, key)) + self.assertEqual(actual['kind'].get('collapse_state'), node['kind'].get('collapse_state')) + if node['kind']['type'] == 'RichText': + self.assertEqual(actual['kind'], node['kind']) + return models, captures + + def test_rust_layout_and_saved_expansion_survive_cold_native_reopen(self): + models, captures = self.cold_layout(FIXTURE / 'layout') + cases = json.loads((FIXTURE / 'cases.json').read_text(encoding='utf-8-sig')) + selected = [case for case in cases if any(key in case for key in ('position', 'size', 'collapse'))] + self.assertEqual(len(selected), 5) + for case in selected: + name = case['name'] + old, page = models['candidate'][name] + saved, _ = models['cold'][name] + oid = next(oid for oid in old['nodes'][page]['children'] if old['nodes'][oid]['kind']['type'] == 'Outline') + node = saved['nodes'][oid] + z = old['nodes'][page]['children'].index(oid) + native = next(outline for outline in captures[name].findall('one:Outline', ns) + if int(outline.find('one:Position', ns).get('z')) == z) + for key, value in case.get('position', {}).items(): + self.assertEqual(node['layout'][key], value) + if 'size' in case: + size = native.find('one:Size', ns) + self.assertEqual(node['layout']['max_width'], case['size']['width']) + self.assertEqual(size.get('isSetByUser') in ('true', '1'), case['size']['isSetByUser']) + if case['size']['isSetByUser']: + self.assertAlmostEqual(float(size.get('width')), case['size']['width'], places=3) + if 'collapse' in case: + target, = [p for p in native.findall('.//one:OE', ns) if p.find('one:T', ns) is not None + and ''.join(Text(p.find('one:T', ns).text or '').parts).startswith('Target ')] + self.assertEqual(target.get('collapsed') in ('true', '1'), case['collapse']) + + def test_rust_width_replaces_native_reserved_wrap_width(self): + models, captures = self.cold_layout(FIXTURE / 'reserved-width') + saved, page = models['cold']['Move outline'] + oid = next(oid for oid in saved['nodes'][page]['children'] if saved['nodes'][oid]['kind']['type'] == 'Outline') + node = saved['nodes'][oid] + self.assertEqual(node['layout']['max_width'], 144) + self.assertTrue(node['layout']['width_set_by_user']) + self.assertFalse(any(field['id'] == 0x14001cdb for field in node['extra'][0])) + z = saved['nodes'][page]['children'].index(oid) + native = next(outline for outline in captures['Move outline'].findall('one:Outline', ns) + if int(outline.find('one:Position', ns).get('z')) == z) + size = native.find('one:Size', ns) + self.assertEqual(size.get('isSetByUser'), 'true') + self.assertAlmostEqual(float(size.get('width')), 144, places=3) + def preserved_node(self, old, new): expected = dict(old) if old['modified'] != new['modified']: @@ -101,8 +170,7 @@ class OutlineEditTest(unittest.TestCase): self.assertEqual(geometry[key], value) if 'size' in case: self.assertEqual(geometry['max_width'], case['size']['width']) - fields = {field['id'] for field in new['nodes'][outline]['extra'][0]} - self.assertEqual(0x88001cbd in fields, case['size']['isSetByUser']) + self.assertEqual(geometry['width_set_by_user'], case['size']['isSetByUser']) if 'collapse' in case: self.assertEqual(bool(new['nodes'][target]['kind']['collapse_state']), case['collapse']) node, = [node for node in captures[phase][name].findall('one:Outline//one:OE', ns) -- 2.54.0