diff --git a/corpus/paragraph-edit/reconciliation/README.md b/corpus/paragraph-edit/reconciliation/README.md new file mode 100644 index 0000000000000000000000000000000000000000..66f2d1bb8e4dd97316f8c026464ff90f2e368457 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/README.md @@ -0,0 +1,37 @@ +# Native paragraph reconciliation controls + +`before` contains sixteen OneNote-authored pages and one unchanged source page. +`tools/native/paragraph-reconciliation.ps1` creates these cases and applies the +separate COM replacement controls retained in `remote`. Whole-page COM updates +replace rich-text identities, including unchanged text. Every local split/join +and dependent edit therefore remains a conflict without remote publication. + +`keyboard` begins from the same notebook and records actual native keystrokes, +screenshots, XML, and saved bytes. Prefix/boundary edits, children, bullets, tags, +formatting, sibling replacement, and empty-paragraph typing exercise independent +changes. Bullets alter ancestry: the first paragraph gains an outline group, +and a later bullet becomes a child of its preceding paragraph. Replacing a whole +selected sibling creates a new paragraph; the split/join targets retain identity. + +`reconciled` retains Rust output and a fresh OneNote cold-open. Six cases publish +automatically; eight publish after explicit review. Each includes a dependent +text edit, with SQLite reopen between local acknowledgements and publications. +The changed empty-left survivor and nonadjacent bulleted join retain conflicts. +Public tests check all 28 receipts, exact active graph/child levels, native +characters/styles, and the saved graph's identities. COM replacement controls +also retain all sixteen local branches across reopen without publishing. + +Regenerate keyboard controls with `tools/native_runner.py` on `before/notebook`, +using `--expected-pages 17 --inspect --collect-notebook`. Once inspection is +ready, run `tools/native_paragraph_reconciliation.py OUTPUT`; it records actions +and requests final capture. The runner removes its owned clone. The ignored +Rust test `paragraph::export_native_reconciliation` generates reconciled output +at a new absolute `ONESTORE_NATIVE_RECONCILIATION_OUTPUT` directory. Cold-open its +`candidate` with the same runner, without inspection. Verification lives in +`tools/test_paragraph_edit.py` and the offline crate's `tests/sync.rs`. + +The original COM pass stopped at its fifth case because its tag definition +followed page settings. The recorded continuation fixes the schema order and +applies only the remaining twelve cases. Scripts, commands, and both phase +hashes retain this provenance; the before-image was preserved throughout. +Identical captured files link to their canonical corpus copy. diff --git a/corpus/paragraph-edit/reconciliation/before/notebook/Open Notebook.onetoc2 b/corpus/paragraph-edit/reconciliation/before/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..caf6cd8dfb5dd42a5594ea49ff31560c9a6fea0b Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/before/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/paragraph-edit/reconciliation/before/notebook/synthetic.one b/corpus/paragraph-edit/reconciliation/before/notebook/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..0bd7ce42587425376a287f055c68110a32fd1147 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/before/notebook/synthetic.one differ diff --git a/corpus/paragraph-edit/reconciliation/before/read/environment.json b/corpus/paragraph-edit/reconciliation/before/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..a2ba5b139e91fa58403585eb573049f0aee59904 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-9095E701", + "cold": false, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/paragraph-edit/reconciliation/before/read/hierarchy.xml b/corpus/paragraph-edit/reconciliation/before/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..dea1607b9b6054f1f070215831ee1f9f617cb59f --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-000.xml b/corpus/paragraph-edit/reconciliation/before/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..5e819ef3003b03e35e97d6aa3d8788cb958b4566 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-000.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-001.xml b/corpus/paragraph-edit/reconciliation/before/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..9b0995d1c94483dd420e5dc694cf2005e11390cf --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-001.xml @@ -0,0 +1,3 @@ + +Right]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-002.xml b/corpus/paragraph-edit/reconciliation/before/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..d0454b76f58c57eba16b2ac2f055e116b3ef2b3f --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-002.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-003.xml b/corpus/paragraph-edit/reconciliation/before/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..3e209bfd20e9d469d59212f213a8d784b616d4d4 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-003.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-004.xml b/corpus/paragraph-edit/reconciliation/before/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..c98a95b72f2afa5010cdc9b1bb63f960fc175d65 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-004.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-005.xml b/corpus/paragraph-edit/reconciliation/before/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..091cf3e0238d4d124fcf66d8fd02cc0f1ced06c6 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-005.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-006.xml b/corpus/paragraph-edit/reconciliation/before/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..f2894e1fc41a58e593c4840caeb932be0abbd933 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-006.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-007.xml b/corpus/paragraph-edit/reconciliation/before/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..d2088474d3286cada212fab98732f9fa04bac96f --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-007.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-008.xml b/corpus/paragraph-edit/reconciliation/before/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..82c81d2dd07dffa35f77fe1d4764e93983b3f8c7 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-008.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-009.xml b/corpus/paragraph-edit/reconciliation/before/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..396bc4d356195778ed0ebb02fd4769f93677cd38 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-009.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-010.xml b/corpus/paragraph-edit/reconciliation/before/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..f9d31f5eb92946f7339ab4515b37fe424d6b8bd8 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-010.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-011.xml b/corpus/paragraph-edit/reconciliation/before/read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..4211655454b98ec2e7e78a9119fb62f29feb13e5 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-011.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-012.xml b/corpus/paragraph-edit/reconciliation/before/read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..c91727f672f10c2be25a91726480da4da466145b --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-012.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-013.xml b/corpus/paragraph-edit/reconciliation/before/read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..cf2e5fa90eebc053af209c4c46fbdc183fd5f9fa --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-013.xml @@ -0,0 +1,20 @@ + +Bold 🦀 italic é color 東京
+End
]]>
Fictitious: café, 東京, مرحبا]]>
diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-014.xml b/corpus/paragraph-edit/reconciliation/before/read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..1bcca85eac36511908652a3e5587e00f0960ec4a --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-014.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-015.xml b/corpus/paragraph-edit/reconciliation/before/read/page-015.xml new file mode 100644 index 0000000000000000000000000000000000000000..e3a8febd3975cbe1f21237e948a401aaa9133c2b --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-015.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/page-016.xml b/corpus/paragraph-edit/reconciliation/before/read/page-016.xml new file mode 100644 index 0000000000000000000000000000000000000000..420e7421ad930b250a497bea2c5751a487abf334 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/page-016.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/before/read/payloads.json b/corpus/paragraph-edit/reconciliation/before/read/payloads.json new file mode 120000 index 0000000000000000000000000000000000000000..3cf45dc1acb611d7f764e0340d73e87192f81407 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/before/read/payloads.json @@ -0,0 +1 @@ +../../../before/read/payloads.json \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/cases.json b/corpus/paragraph-edit/reconciliation/cases.json new file mode 100644 index 0000000000000000000000000000000000000000..c1fc8edd9bcc4026137439fb9ca07a8264b05639 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/cases.json @@ -0,0 +1,82 @@ +[ + { + "operation": "split", + "change": "prefix", + "name": "Split remote prefix" + }, + { + "operation": "split", + "change": "boundary", + "name": "Split remote boundary" + }, + { + "operation": "split", + "change": "child", + "name": "Split remote child" + }, + { + "operation": "split", + "change": "list", + "name": "Split remote list" + }, + { + "operation": "split", + "change": "tag", + "name": "Split remote tag" + }, + { + "operation": "split", + "change": "format", + "name": "Split remote format" + }, + { + "operation": "split", + "change": "sibling", + "name": "Split remote sibling" + }, + { + "operation": "join", + "change": "prefix", + "name": "Join remote prefix" + }, + { + "operation": "join", + "change": "boundary", + "name": "Join left boundary" + }, + { + "operation": "join", + "change": "right-boundary", + "name": "Join right boundary" + }, + { + "operation": "join", + "change": "child", + "name": "Join remote child" + }, + { + "operation": "join", + "change": "list", + "name": "Join remote list" + }, + { + "operation": "join", + "change": "tag", + "name": "Join remote tag" + }, + { + "operation": "join", + "change": "format", + "name": "Join remote format" + }, + { + "operation": "join", + "change": "sibling", + "name": "Join remote sibling" + }, + { + "operation": "join", + "change": "adoption", + "name": "Join empty adoption" + } +] diff --git a/corpus/paragraph-edit/reconciliation/commands.jsonl b/corpus/paragraph-edit/reconciliation/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..c765e35203b05ff7b47d532fd820c6d3ed4b25db --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/commands.jsonl @@ -0,0 +1,9 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\author.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-9095E701", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-9095E701 -ExpectedPages 17 -UseCurrentCache -KeepOpen", "exit": 0, "stdout": "Read 1 sections and 17 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\remote-paragraphs.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-9095E701 -Remote", "exit": 1, "stdout": "", "stderr": "C:\\one-tests\\remote-paragraphs.ps1 : Exception calling \"UpdatePageContent\" \r\nwith \"4\" argument(s): \"Exception from HRESULT: 0x80042001\"\r\n + CategoryInfo : NotSpecified: (:) [remote-paragraphs.ps1], Metho \r\n dInvocationException\r\n + FullyQualifiedErrorId : COMException,remote-paragraphs.ps1\r\n \r\n", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\remote-remaining.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-9095E701 -Remote", "exit": 0, "stdout": "Updating: Split remote tag\r\nApplied: Split remote tag\r\nUpdating: Split remote format\r\nApplied: Split remote format\r\nUpdating: Split remote sibling\r\nApplied: Split remote sibling\r\nUpdating: Join remote prefix\r\nApplied: Join remote prefix\r\nUpdating: Join left boundary\r\nApplied: Join left boundary\r\nUpdating: Join right boundary\r\nApplied: Join right boundary\r\nUpdating: Join remote child\r\nApplied: Join remote child\r\nUpdating: Join remote list\r\nApplied: Join remote list\r\nUpdating: Join remote tag\r\nApplied: Join remote tag\r\nUpdating: Join remote format\r\nApplied: Join remote format\r\nUpdating: Join remote sibling\r\nApplied: Join remote sibling\r\nUpdating: Join empty adoption\r\nApplied: Join empty adoption\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Rename-Item C:\\one-tests\\runs\\capture\\read before-read\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-9095E701 -UseCurrentCache -ExpectedPages -1", "exit": 0, "stdout": "Read 1 sections and 17 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/environment.json b/corpus/paragraph-edit/reconciliation/keyboard/before-read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..ec50e97d0556a6542bdc449aaac4beaf6480c8d1 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-9E5BF58B", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/hierarchy.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..808381e23ba8cbc53f30b37bfa0341dcdad7c608 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-000.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..bf7b8b30b28d4d40e88a494e67993a5c26b9aa54 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-000.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-001.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..1714a322c2eefd02fb76e1bc979eccf9854e5b5e --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-001.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-002.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..63f7dfee059db8e1d9d17df972b64599b568db05 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-002.xml @@ -0,0 +1,3 @@ + +Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-003.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..c19dea5cd069ba2bc925090db7a71d15c07c898a --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-003.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-004.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..44da7709e34e34a6d90b2a9d7cfe068cf66fb5b5 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-004.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-005.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..f11b5f6ca8c941f3da8031a7fbfce4e6faad4feb --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-005.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-006.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..785bb4f4b19981fd48bc02ca4bb604b8ec5b5971 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-006.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-007.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ff6c0118c8a147bb8e023aaa9b0fa5544a7bcc9 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-007.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-008.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..0634f3ae3b027ea11ad895aed7f033f1ace67869 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-008.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-009.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..86401caeefb1ff6f2156df7607321a873df09979 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-009.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-010.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..281f0fc050bd88bd705980c371e7bde592343744 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-010.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-011.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..a0f5faf2b5e67e46083931ec3b0d207dd189156b --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-011.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-012.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..bd03ad783c5068905602383f8a5a296f427d2fb7 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-012.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-013.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..9d27858c41fd796eff0e13e327ecbc5a76a5de2a --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-013.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-014.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e75784766110628c3848f7c213bde4f5ea75bf7 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-014.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-015.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-015.xml new file mode 100644 index 0000000000000000000000000000000000000000..fd8fe79dc73e66d6f49d5d6e1ea249f0251aeb34 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-015.xml @@ -0,0 +1,20 @@ + +Bold 🦀 italic é color 東京
+End
]]>
Fictitious: café, 東京, مرحبا]]>
diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-016.xml b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-016.xml new file mode 100644 index 0000000000000000000000000000000000000000..95c2f2c4a8168f4676e94c924ec043e2c7ec11ac --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/page-016.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/before-read/payloads.json b/corpus/paragraph-edit/reconciliation/keyboard/before-read/payloads.json new file mode 120000 index 0000000000000000000000000000000000000000..3cf45dc1acb611d7f764e0340d73e87192f81407 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/before-read/payloads.json @@ -0,0 +1 @@ +../../../before/read/payloads.json \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/commands.jsonl b/corpus/paragraph-edit/reconciliation/keyboard/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..fd04864244b9fed72b9a82b2e420b1bfce0b4615 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/commands.jsonl @@ -0,0 +1,6 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-9E5BF58B -ExpectedPages 17 -KeepOpen", "exit": 0, "stdout": "Read 1 sections and 17 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Rename-Item C:\\one-tests\\runs\\capture\\read before-read\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-9E5BF58B -UseCurrentCache -ExpectedPages -1", "exit": 0, "stdout": "Read 1 sections and 17 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-empty-adoption.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-empty-adoption.ahk new file mode 100644 index 0000000000000000000000000000000000000000..952b13d3fd35261e422ac85e69511f0463bbc7a4 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-empty-adoption.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{339CBA14-5F09-4E74-98D2-DAC2C4AF85DA}{1}{B0}", "{753F2A26-21FA-49A5-A7E3-3D97DFE56B0F}{40}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Left}X" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-empty-adoption.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-empty-adoption.json new file mode 100644 index 0000000000000000000000000000000000000000..ecf6ab42df682e3e6d448858290b3747d8beb17c --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-empty-adoption.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Join empty adoption - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-empty-adoption.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-empty-adoption.png new file mode 100644 index 0000000000000000000000000000000000000000..d70628354ce632013f0abd59c2be48ea2c6e08c2 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-empty-adoption.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-left-boundary.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-left-boundary.ahk new file mode 100644 index 0000000000000000000000000000000000000000..7aa38e62012770e7cad2a06bca4ba7f453048222 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-left-boundary.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{C7C8C394-529E-47CA-A13B-7931CC047FB6}{1}{B0}", "{A5D6D966-6004-458B-92AA-51C8DD659D3A}{40}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Right}X" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-left-boundary.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-left-boundary.json new file mode 100644 index 0000000000000000000000000000000000000000..70b32f42a826feb7397a2b29a419de789b8445cf --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-left-boundary.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Join left boundary - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-left-boundary.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-left-boundary.png new file mode 100644 index 0000000000000000000000000000000000000000..0061ba5ef8cb7e064d1a88b40df29dd75e3c1a5f Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-left-boundary.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-child.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-child.ahk new file mode 100644 index 0000000000000000000000000000000000000000..99cbc6d0c5d9382d512d71698c0aee0068463658 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-child.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{AD28524E-CC50-40D0-84FA-157F9867EC05}{1}{B0}", "{E971E60D-4048-4A2C-9151-0CE852F4405D}{46}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Right}{Enter}{Tab}Native child" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-child.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-child.json new file mode 100644 index 0000000000000000000000000000000000000000..0e7acec2fc8e2e4832e2c58689fb8327cf66b07e --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-child.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Join remote child - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-child.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-child.png new file mode 100644 index 0000000000000000000000000000000000000000..41f358fadfe146526c8c5a3f4e5d5d5fe62124cc Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-child.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-format.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-format.ahk new file mode 100644 index 0000000000000000000000000000000000000000..40a9f7997ee7fae5360904700409bb6f818512e5 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-format.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{CF3EFEEF-026C-4156-B3B5-5D9FD0637BB0}{1}{B0}", "{C9681C2A-35ED-4F34-85EB-C6297F12C13F}{46}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "^i" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-format.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-format.json new file mode 100644 index 0000000000000000000000000000000000000000..bc5d5b3890d6473f956ab04494bf3afe72fcad2d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-format.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Join remote format - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-format.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-format.png new file mode 100644 index 0000000000000000000000000000000000000000..24e088b87ca10e388076a229845c5fff2bbfd5c6 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-format.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-list.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-list.ahk new file mode 100644 index 0000000000000000000000000000000000000000..7686c7bace1e07b5467e518c43c355d48cfde258 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-list.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{70252131-654A-4CB2-9015-3264EF828208}{1}{B0}", "{24C6ABE1-25B8-4183-90D0-07A1BFD645EF}{46}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Left}^." +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-list.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-list.json new file mode 100644 index 0000000000000000000000000000000000000000..f321adc53b804c55d4b61bf21d247b4a3787e38e --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-list.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Join remote list - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-list.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-list.png new file mode 100644 index 0000000000000000000000000000000000000000..d2bb110f48463299fce4cbee4039848035c220f2 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-list.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-prefix.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-prefix.ahk new file mode 100644 index 0000000000000000000000000000000000000000..f4c750c81ac7e368dd709d3c7d57cd78a15b85fc --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-prefix.ahk @@ -0,0 +1,25 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{DEA76FCD-5853-477C-AD4A-F165915338BB}{1}{B0}", "{62483E36-C372-4F75-90BF-DE6D1F7A5FC1}{40}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Left}X" +Sleep 300 +app.NavigateTo("{DEA76FCD-5853-477C-AD4A-F165915338BB}{1}{B0}", "{62483E36-C372-4F75-90BF-DE6D1F7A5FC1}{46}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Right}Y" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-prefix.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-prefix.json new file mode 100644 index 0000000000000000000000000000000000000000..2427316a487d1601e67641fb36d88590c9927223 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-prefix.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Join remote prefix - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-prefix.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-prefix.png new file mode 100644 index 0000000000000000000000000000000000000000..2778d739d07991a1b9c42d492564ca5fdb7f6b82 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-prefix.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-sibling.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-sibling.ahk new file mode 100644 index 0000000000000000000000000000000000000000..2198d2df7852d8f6ecde054d3476e336bb9d6bab --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-sibling.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{3E68D1A6-BF4B-413B-ACE3-56435E4546F5}{1}{B0}", "{3750DABC-69EB-4A22-82ED-2972300956DE}{51}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "Native sibling" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-sibling.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-sibling.json new file mode 100644 index 0000000000000000000000000000000000000000..03dac1c8180bcfbcb753bfeeb2825938b8b58257 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-sibling.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Join remote sibling - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-sibling.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-sibling.png new file mode 100644 index 0000000000000000000000000000000000000000..f7f8cf46343ea0a3d5ed15c5d9d22e1695ca34a6 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-sibling.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-tag.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-tag.ahk new file mode 100644 index 0000000000000000000000000000000000000000..9578ae8ae9af6a57fc5f21c66468d2296249a1e0 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-tag.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{49638AD3-7021-4A1C-AAA3-B08AB5F5506D}{1}{B0}", "{D86013FB-B193-4A3B-BF7A-753A51E01437}{46}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Left}^1" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-tag.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-tag.json new file mode 100644 index 0000000000000000000000000000000000000000..7f3e8b40186521e9992e2cca24f7d2acdbbffece --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-tag.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Join remote tag - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-tag.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-tag.png new file mode 100644 index 0000000000000000000000000000000000000000..f01b0131a1c497972638468e7a0c999dac3ff464 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-remote-tag.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-right-boundary.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-right-boundary.ahk new file mode 100644 index 0000000000000000000000000000000000000000..492c369ac1f450835d8c1dce3eb33b1a8cd6a783 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-right-boundary.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{6098C8BD-5256-42BE-A5A7-561BF30DE077}{1}{B0}", "{0355EDE0-60F1-4C03-BF26-8EB483A0F5AA}{46}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Left}X" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-right-boundary.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-right-boundary.json new file mode 100644 index 0000000000000000000000000000000000000000..fd2eb7acc479a71c84b79c2662be49534f28bc74 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-right-boundary.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Join right boundary - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-right-boundary.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-right-boundary.png new file mode 100644 index 0000000000000000000000000000000000000000..6ac724939b56453008f029b61a65fa677bb5edae Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/join-right-boundary.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-boundary.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-boundary.ahk new file mode 100644 index 0000000000000000000000000000000000000000..9b8fec16d0f58c0851233907872c998f799aa61e --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-boundary.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{4E20F67A-9223-4BB5-9191-7EC10CE43F1F}{1}{B0}", "{3224CEC3-F663-4F74-8CBE-540DDC982B1E}{40}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Left}{Right 2}X" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-boundary.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-boundary.json new file mode 100644 index 0000000000000000000000000000000000000000..93f62ef7ba9db2af2f44660c7ac577007e4414ec --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-boundary.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Split remote boundary - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-boundary.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-boundary.png new file mode 100644 index 0000000000000000000000000000000000000000..92e84b8dda2e79d94478e727ea16ec0c56d7b22b Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-boundary.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-child.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-child.ahk new file mode 100644 index 0000000000000000000000000000000000000000..27b163b98270070b5ad3a0c7e12a30e25355f29d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-child.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{AA94EAE9-FD63-4922-86A1-458933A73EA4}{1}{B0}", "{92829D34-66A4-48FE-AC75-907125308AE5}{40}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Right}{Enter}{Tab}Native child" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-child.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-child.json new file mode 100644 index 0000000000000000000000000000000000000000..bcc084b8978e3e13c7cce3e92d048b95a3ac8f95 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-child.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Split remote child - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-child.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-child.png new file mode 100644 index 0000000000000000000000000000000000000000..aa79c64fd6a61504778de730ddecf92a29aca2f8 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-child.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-format.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-format.ahk new file mode 100644 index 0000000000000000000000000000000000000000..cdd54492e2e0dfed7470b87b8387d8e0a445d13b --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-format.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{57F7D738-2BD4-42F6-B4AF-DB0B2FC7574E}{1}{B0}", "{12E5B354-A883-4DEB-984F-1461EE79A1D5}{40}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "^i" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-format.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-format.json new file mode 100644 index 0000000000000000000000000000000000000000..483bfdc4151988a5a6752e30df772669f79c31cf --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-format.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Split remote format - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-format.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-format.png new file mode 100644 index 0000000000000000000000000000000000000000..84342d3615920400383f6e7093e0aae8b7edf23e Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-format.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-list.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-list.ahk new file mode 100644 index 0000000000000000000000000000000000000000..3bb8e6d61e570afc4c9ba8e47def810c5c7a93e9 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-list.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{F848F52D-F95C-4D45-B54A-E6E7875961C3}{1}{B0}", "{748CAF50-7793-4033-9CE8-1E8CF040DEBF}{40}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Left}^." +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-list.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-list.json new file mode 100644 index 0000000000000000000000000000000000000000..c4020169963efb3d26aca606e105882e201ba531 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-list.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Split remote list - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-list.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-list.png new file mode 100644 index 0000000000000000000000000000000000000000..9b784cf0d557d655ded2e7acaf013e379c7659e2 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-list.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-prefix.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-prefix.ahk new file mode 100644 index 0000000000000000000000000000000000000000..4a47646099cd512508c7ad5e83a89f039c60867e --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-prefix.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{2491D9D8-BFA7-46D8-A855-D07263E6470E}{1}{B0}", "{460B2629-58B0-40B0-8590-702A35A91D80}{40}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Left}X" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-prefix.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-prefix.json new file mode 100644 index 0000000000000000000000000000000000000000..ca9485dc851e38c515344c4473bd8bd7fd2a8073 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-prefix.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Split remote prefix - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-prefix.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-prefix.png new file mode 100644 index 0000000000000000000000000000000000000000..0204978cd12d0bb4b8166d1ff765dff64bfe30fb Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-prefix.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-sibling.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-sibling.ahk new file mode 100644 index 0000000000000000000000000000000000000000..b8f92ab23be07941534744220b14e64d15602a57 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-sibling.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{A35EA4E1-8740-466B-BBC1-D410A7075FB0}{1}{B0}", "{7FF116ED-B5D3-4F42-B7EC-C3CE00FDC9B0}{46}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "Native sibling" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-sibling.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-sibling.json new file mode 100644 index 0000000000000000000000000000000000000000..798b9aec4480d5c47d8cde873ff40e65ff78bb14 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-sibling.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Split remote sibling - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-sibling.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-sibling.png new file mode 100644 index 0000000000000000000000000000000000000000..67fb9bcd296fea94ee9a9ba63472b711e5c5d017 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-sibling.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-tag.ahk b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-tag.ahk new file mode 100644 index 0000000000000000000000000000000000000000..5b17e5d8801dff64f63535a4199565ca4196dc7d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-tag.ahk @@ -0,0 +1,14 @@ +#Requires AutoHotkey v2.0 +OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1))) +app := ComObject("OneNote.Application") +app.NavigateTo("{2245C86F-7CED-4CCD-A2B5-64835D267233}{1}{B0}", "{FF6F426F-6458-4D21-8CA2-C8232DA59D33}{40}{B0}", false) +hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10) +if !hwnd + throw Error("OneNote window did not appear") +WinMaximize(hwnd) +WinActivate(hwnd) +if !WinWaitActive(hwnd,, 10) + throw Error("OneNote did not become active") +Sleep 300 +Send "{Left}^1" +Sleep 300 diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-tag.json b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-tag.json new file mode 100644 index 0000000000000000000000000000000000000000..9c9c0ff33bb97d1537c5d0657ace90a607f47a37 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-tag.json @@ -0,0 +1,13 @@ +{ + "exit": 0, + "stdout": "", + "stderr": "", + "w": 800, + "h": 600, + "error": null, + "win": { + "title": "Split remote tag - Microsoft OneNote", + "class": "Framework::CFrame", + "dialog": false + } +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-tag.png b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-tag.png new file mode 100644 index 0000000000000000000000000000000000000000..7e81427bba061f0279451a4f14b96588f01c78f6 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/keyboard/split-remote-tag.png differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/notebook/Open Notebook.onetoc2 b/corpus/paragraph-edit/reconciliation/keyboard/notebook/Open Notebook.onetoc2 new file mode 120000 index 0000000000000000000000000000000000000000..a6c7d197861f52dda5ecaf4da2ab7e471f409518 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/notebook/Open Notebook.onetoc2 @@ -0,0 +1 @@ +../../before/notebook/Open Notebook.onetoc2 \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/notebook/synthetic.one b/corpus/paragraph-edit/reconciliation/keyboard/notebook/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..d6e676ae156c22e19ef2bddf12564db6de4a7787 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/keyboard/notebook/synthetic.one differ diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/environment.json b/corpus/paragraph-edit/reconciliation/keyboard/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..c82c7b8b6cdc98c6ae3a69c54d2a990ac668973f --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-9E5BF58B", + "cold": false, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/hierarchy.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..419e92d8a14692128ebc7f48cf3b20e52d11931d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-000.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..d9a1f82daa2b5e7b2ed3fa4335172e9dbad09a7b --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-000.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-001.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..8f8d40512bec0dd9c467aa5a5c0f74fffe3bb133 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-001.xml @@ -0,0 +1,3 @@ + +Xab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-002.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..43ad77528a96ab071122a78a5418187269ac9a4d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-002.xml @@ -0,0 +1,3 @@ + +Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-003.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..34cd615a152bbe14c7cfaaa933fa34f533ce1b3f --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-003.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-004.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..893b75022527482fbcf3499187d4e042b09e6b5e --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-004.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-005.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..4f01b688aa176e5c3a188c63f66241684b641d41 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-005.xml @@ -0,0 +1,3 @@ + +abX🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-006.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..324ca5e9fb53c82ce7f3219854d430e7d5abd587 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-006.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-007.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..51f5fe1209e28cad1e8abd8c6e58db8c58de2534 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-007.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>XRight]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-008.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..9098763fe61c6b672676d8a0598eaa6555602740 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-008.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-009.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..dd981c0dc44d3a625bd8598441a3ad7d7d10d1d7 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-009.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-010.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..83cbece05782059718ed4ae5db93fdb90478589c --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-010.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Native child]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-011.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..6410c5700135cd7d69369642581fe57c46866c26 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-011.xml @@ -0,0 +1,5 @@ + +ab🦀cd]]>Right]]>Native child]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-012.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..01c8bad008914d47f41c7b02c8c3b88e6f898afe --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-012.xml @@ -0,0 +1,4 @@ + +ab🦀cdX]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-013.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..6bd6fa9d17a5baa409ef05318f89de90729848de --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-013.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-014.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..772d113b0ab2df27a5d8a5f5caf94ccefc7bf8c4 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-014.xml @@ -0,0 +1,4 @@ + +Xab🦀cd]]>RightY]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-015.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-015.xml new file mode 100644 index 0000000000000000000000000000000000000000..23c9b8a06544516a5beeef3db356a4678e1a7f5e --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-015.xml @@ -0,0 +1,20 @@ + +Bold 🦀 italic é color 東京
+End
]]>
Fictitious: café, 東京, مرحبا]]>
diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/page-016.xml b/corpus/paragraph-edit/reconciliation/keyboard/read/page-016.xml new file mode 100644 index 0000000000000000000000000000000000000000..e7a190f3bb55733af77e41212a839ca17e573112 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/page-016.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/keyboard/read/payloads.json b/corpus/paragraph-edit/reconciliation/keyboard/read/payloads.json new file mode 120000 index 0000000000000000000000000000000000000000..3cf45dc1acb611d7f764e0340d73e87192f81407 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/read/payloads.json @@ -0,0 +1 @@ +../../../before/read/payloads.json \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/keyboard/run.json b/corpus/paragraph-edit/reconciliation/keyboard/run.json new file mode 100644 index 0000000000000000000000000000000000000000..0c95f16db00ca937d70cd26052e8ac06f656c1a5 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/Users/clo/dev/one/corpus/paragraph-edit/reconciliation/before/notebook", + "expected_pages": 17, + "author": null, + "author_timeout_seconds": 600, + "inspect": true, + "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/paragraph-edit/reconciliation/keyboard/scripts/cold.ps1 b/corpus/paragraph-edit/reconciliation/keyboard/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/scripts/cold.ps1 @@ -0,0 +1,27 @@ +param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '') +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' } +$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote' +if ($CloneHost) { + if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) { + throw 'The disposable clone hostname does not match this machine.' + } + New-Item "$key\Options\Paths" -Force | Out-Null + New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null +} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or + -not (Test-Path 'C:\one-tests\profile-original-cache')) { + throw 'Park the personal OneNote profile before resetting the test cache.' +} +$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0' +$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root)) +if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' } +New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null +if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked } +if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse } +New-Item "$key\OpenNotebooks" | Out-Null +New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null diff --git a/corpus/paragraph-edit/reconciliation/keyboard/scripts/read.ps1 b/corpus/paragraph-edit/reconciliation/keyboard/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/scripts/read.ps1 @@ -0,0 +1,142 @@ +param( + [Parameter(Mandatory=$true)][string]$Root, + [int]$ExpectedPages = -1, + [switch]$UseCurrentCache, + [switch]$Pdf, + [switch]$KeepOpen, + [string]$CloneHost = '' +) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$root = [IO.Path]::GetFullPath($Root).TrimEnd('\') +if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') { + throw 'Choose a run directly below C:\one-tests\runs.' +} +$notebook = Join-Path $root 'notebook' +$output = Join-Path $root 'read' +if (Test-Path $output) { throw 'Choose a new read destination.' } +if ($UseCurrentCache) { + if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') { + throw 'Park the personal OneNote profile before reading test notebooks.' + } +} else { + & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost +} +New-Item -ItemType Directory -Path $output | Out-Null +$app = New-Object -ComObject OneNote.Application +$notebookId = '' +$failure = $null +try { + $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0) + $process = Get-Process ONENOTE + @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion; + powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } | + ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8 + $sections = @() + foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) { + $id = '' + $app.OpenHierarchy($file.FullName, '', [ref]$id, 0) + $sections += $id + } + $deadline = [DateTime]::UtcNow.AddSeconds(300) + $previous = '' + $lastChange = '' + $stableSince = [DateTime]::UtcNow + $settled = $false + do { + $pages = @{} + foreach ($section in $sections) { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$xml = $hierarchy + foreach ($node in $xml.SelectNodes('//*[@path]')) { + if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'OneNote opened a section outside the copied notebook.' + } + } + foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) { + $id = $node.GetAttribute('ID') + $content = '' + $app.GetPageContent($id, [ref]$content, 1, 1) + $pages[$id] = $content + } + } + $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] })) + if ($signature -ne $previous) { + $lastChange = $previous + $previous = $signature + $stableSince = [DateTime]::UtcNow + } + if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or + ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and + ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) { + [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8) + $index = 0 + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + $index++ + } + $hierarchy = '' + $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1) + [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8) + throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled." + } + $index = 0 + $payloads = @() + foreach ($id in @($pages.Keys | Sort-Object)) { + [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8) + if ($Pdf) { + $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index) + $app.NavigateTo($id, '', $false) + $app.Publish($id, $pdfPath, 3, '') + if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' } + } + [xml]$page = $pages[$id] + foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) { + $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache')) + $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant() + [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes) + $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID'); + kind = $file.LocalName; name = $file.GetAttribute('preferredName'); + sha256 = $hash; bytes = $bytes.Length } + } + $index++ + } + [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8) + $all = '' + $app.GetHierarchy($notebookId, 4, [ref]$all, 1) + [xml]$finalTree = $all + $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique) + if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) { + throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.' + } + [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8) + Write-Output "Read $($sections.Count) sections and $($pages.Count) pages." +} catch { + $failure = $_ + [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + throw +} finally { + try { + try { + if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) } + if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) { + $app.CloseNotebook($notebookId, $false) + } + } catch { + if ($null -eq $failure) { throw } + [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8) + } + } finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + } + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + if (-not $UseCurrentCache -and -not $CloneHost) { + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10 + } +} diff --git a/corpus/paragraph-edit/reconciliation/keyboard/source.json b/corpus/paragraph-edit/reconciliation/keyboard/source.json new file mode 100644 index 0000000000000000000000000000000000000000..e58756a6eb74645ea0cbc4787009065b7d62a892 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/source.json @@ -0,0 +1,14 @@ +[ + { + "path": "Open Notebook.onetoc2", + "bytes": 4800, + "sha256": "1122dbd6fe3ee18a8cdf6c1e65521faa69119bafb220828fc86e7c858d7e3e76", + "mtime_ns": 1788887226300088396 + }, + { + "path": "synthetic.one", + "bytes": 100944, + "sha256": "c40709e26e9e5f177956747cb4b862f8a9f2c1c0e155b77dd54abb148ae9bba5", + "mtime_ns": 1788887226300365479 + } +] diff --git a/corpus/paragraph-edit/reconciliation/keyboard/teardown.json b/corpus/paragraph-edit/reconciliation/keyboard/teardown.json new file mode 120000 index 0000000000000000000000000000000000000000..b0d2ee26322df655cbbf9e42f6c30b72a4d110a5 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/keyboard/teardown.json @@ -0,0 +1 @@ +../../joined/teardown.json \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/reconciled/candidate/synthetic.one b/corpus/paragraph-edit/reconciliation/reconciled/candidate/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..1d8e772b17c02f0800c4007232b3e463f018afd2 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/reconciled/candidate/synthetic.one differ diff --git a/corpus/paragraph-edit/reconciliation/reconciled/manifest.json b/corpus/paragraph-edit/reconciliation/reconciled/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..8b9e4249a69e21b98eb28554ee01660413e1874c --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/manifest.json @@ -0,0 +1,323 @@ +[ + { + "case": "Split remote prefix", + "dependent_receipt": "{CE7388B9-8702-4628-B5FD-1CB0A86C7579},1", + "intent": { + "author": "Offline author", + "created": 1473355695, + "guid": [ + 72, + 3, + 21, + 225, + 173, + 175, + 163, + 66, + 181, + 182, + 27, + 215, + 235, + 175, + 30, + 101 + ], + "offset": 2, + "text": "{C4C5964A-00F6-06E5-1947-EF9DD9BFF93E},44" + }, + "outcome": "automatic", + "receipt": "{32C8046A-B530-44D9-932E-964D583CE2DC},1", + "space": "{A65F69BB-E7E1-008D-3482-4FC58FF0A3B0},1" + }, + { + "case": "Split remote boundary", + "dependent_receipt": "{BA2BDF8F-DCC0-4065-90F1-6983A1F37E15},1", + "intent": { + "author": "Offline author", + "created": 1473355696, + "guid": [ + 121, + 163, + 49, + 221, + 144, + 2, + 69, + 72, + 145, + 115, + 17, + 231, + 77, + 231, + 13, + 167 + ], + "offset": 2, + "text": "{B0EA7EA0-AE25-0921-1069-CBBA308ECFA0},44" + }, + "outcome": "reviewed", + "receipt": "{EE6FDF11-A1B9-402D-B1BE-F7EE9004909F},1", + "space": "{CCEE4619-CA65-0DE0-0D46-E176E0F2DBA1},1" + }, + { + "case": "Split remote child", + "dependent_receipt": "{FFEEB215-51E2-44B6-8D3B-475400347A22},1", + "intent": { + "author": "Offline author", + "created": 1473355696, + "guid": [ + 229, + 160, + 224, + 139, + 80, + 49, + 248, + 79, + 147, + 199, + 22, + 222, + 227, + 116, + 32, + 195 + ], + "offset": 2, + "text": "{104C2D57-3EE2-0EAB-30A2-0FC6C9266E5B},44" + }, + "outcome": "reviewed", + "receipt": "{B3E8433E-8363-4424-8B20-C0F3A9712D81},1", + "space": "{285A5A8A-A525-0F77-1A76-DA3EDFB1DA1A},1" + }, + { + "case": "Split remote list", + "dependent_receipt": "{A50CB64F-C580-43E9-B1DF-522FB18B6B51},1", + "intent": { + "author": "Offline author", + "created": 1473355697, + "guid": [ + 6, + 118, + 122, + 220, + 71, + 210, + 164, + 79, + 154, + 8, + 22, + 195, + 142, + 16, + 93, + 166 + ], + "offset": 2, + "text": "{F6421F33-2FD5-0666-003F-813B1C563A01},44" + }, + "outcome": "reviewed", + "receipt": "{967507AF-A4FC-4593-85DA-DB4BDB215CB8},1", + "space": "{7A86454E-A11A-0B10-299D-79506B4F857D},1" + }, + { + "case": "Split remote tag", + "dependent_receipt": "{8C68C1BF-FA7C-414C-B4C8-6D6330816B67},1", + "intent": { + "author": "Offline author", + "created": 1473355698, + "guid": [ + 190, + 238, + 93, + 84, + 186, + 28, + 195, + 65, + 140, + 108, + 184, + 101, + 128, + 188, + 55, + 19 + ], + "offset": 2, + "text": "{7DA1F20C-3C1E-0B74-1075-5794C1B3798D},44" + }, + "outcome": "reviewed", + "receipt": "{ABF29E0E-5267-416D-BCDC-C6A5E7378D30},1", + "space": "{A08B780C-24AB-0A98-3E62-FB34B130968D},1" + }, + { + "case": "Split remote format", + "dependent_receipt": "{D9948EA1-D7AA-450F-949C-1489C5B37D92},1", + "intent": { + "author": "Offline author", + "created": 1473355698, + "guid": [ + 56, + 178, + 113, + 83, + 197, + 69, + 46, + 64, + 181, + 97, + 8, + 109, + 138, + 17, + 10, + 110 + ], + "offset": 2, + "text": "{902B0337-F0C5-0BBE-0498-8BD6026F456B},44" + }, + "outcome": "automatic", + "receipt": "{C93BEE05-161E-45D1-90A7-9EBCB1889577},1", + "space": "{D539675B-7392-04A3-2878-44BCC3D1B3F0},1" + }, + { + "case": "Split remote sibling", + "dependent_receipt": "{971EC3CC-2FD5-4A40-A9DF-A7E250057BF6},1", + "intent": { + "author": "Offline author", + "created": 1473355699, + "guid": [ + 29, + 215, + 155, + 66, + 220, + 243, + 26, + 76, + 178, + 203, + 57, + 141, + 56, + 243, + 174, + 46 + ], + "offset": 2, + "text": "{FD3FA68E-ED95-0917-2B3B-5C79ECEB2D0E},44" + }, + "outcome": "automatic", + "receipt": "{CF2A16BE-1BC9-4A42-BA60-EA637480552C},1", + "space": "{21901482-DF06-003E-2716-4BA74B11BB0E},1" + }, + { + "case": "Join remote prefix", + "dependent_receipt": "{2D17C528-B546-40FA-8485-16C9B0DABF6E},1", + "intent": { + "author": "Offline author", + "left": "{E0868E55-9B34-0920-0C68-41DAF36CBB7F},44", + "right": "{E0868E55-9B34-0920-0C68-41DAF36CBB7F},50" + }, + "outcome": "automatic", + "receipt": "{F63692D3-3D09-43A6-890D-10C65A159B16},1", + "space": "{5C69DFAE-0015-0129-319D-6ED27D45DC05},1" + }, + { + "case": "Join left boundary", + "dependent_receipt": "{0CA7FB85-F492-47BD-919C-6A919CFB409E},1", + "intent": { + "author": "Offline author", + "left": "{27186905-3842-03DE-0E7D-CE7F31737984},44", + "right": "{27186905-3842-03DE-0E7D-CE7F31737984},50" + }, + "outcome": "reviewed", + "receipt": "{166E0BE9-230F-43E9-8555-C6776B5D6183},1", + "space": "{450673F7-0AD8-019F-3DEC-E68620129B08},1" + }, + { + "case": "Join right boundary", + "dependent_receipt": "{F89D5093-F20C-4391-9F38-6C716922731D},1", + "intent": { + "author": "Offline author", + "left": "{819B5D83-38B7-0A56-23F1-11036FB61114},44", + "right": "{819B5D83-38B7-0A56-23F1-11036FB61114},50" + }, + "outcome": "reviewed", + "receipt": "{084D104B-CB74-492A-8EAF-0D9E8E6F6099},1", + "space": "{E25678DE-0A10-04EB-3970-C9AC1F1B04C9},1" + }, + { + "case": "Join remote child", + "dependent_receipt": "{2196E1EA-49A6-4A1C-B0FE-3CCBCD1EA993},1", + "intent": { + "author": "Offline author", + "left": "{6BBF566E-180E-0C79-0D86-935FBEE2A4E3},44", + "right": "{6BBF566E-180E-0C79-0D86-935FBEE2A4E3},50" + }, + "outcome": "reviewed", + "receipt": "{69B85C08-6FD0-4756-B20A-39A342BA516C},1", + "space": "{2FE6E22D-9416-0685-182D-8AC8747108BB},1" + }, + { + "case": "Join remote list", + "intent": { + "author": "Offline author", + "left": "{A6081B82-7DFE-07D6-0C07-981653C0A151},44", + "right": "{A6081B82-7DFE-07D6-0C07-981653C0A151},50" + }, + "outcome": "retained_conflict", + "space": "{F2EB9152-3D0C-0AE7-0CC2-ADD3039466B6},1" + }, + { + "case": "Join remote tag", + "dependent_receipt": "{F4EB3C75-AB8C-4E7C-9A64-69593946321E},1", + "intent": { + "author": "Offline author", + "left": "{5AAEA398-E9D5-0C6E-23AD-EA8DBDF6F089},44", + "right": "{5AAEA398-E9D5-0C6E-23AD-EA8DBDF6F089},50" + }, + "outcome": "reviewed", + "receipt": "{5AC635E3-AC61-41EF-9424-737AD0EAAF32},1", + "space": "{CBAD3AB0-2867-0C49-3674-2F3D59E3B4D3},1" + }, + { + "case": "Join remote format", + "dependent_receipt": "{649CC682-7CCB-4A9E-9C26-06DDF3A7F49E},1", + "intent": { + "author": "Offline author", + "left": "{4BA6AC49-6DAB-0961-193C-599E93042581},44", + "right": "{4BA6AC49-6DAB-0961-193C-599E93042581},50" + }, + "outcome": "automatic", + "receipt": "{F63BD836-C10E-4928-890D-9BCB13C1C3F5},1", + "space": "{4DF04E8C-5A2A-0703-2F62-C2283C759F0E},1" + }, + { + "case": "Join remote sibling", + "dependent_receipt": "{2A4C6024-4FF9-46A9-83A1-34F1A7EF62F2},1", + "intent": { + "author": "Offline author", + "left": "{B59E6ADF-31AD-0C77-1E3A-B6C5DC1FB260},44", + "right": "{B59E6ADF-31AD-0C77-1E3A-B6C5DC1FB260},50" + }, + "outcome": "automatic", + "receipt": "{B29D40A5-BAE2-48BA-9028-25A1B14CF27F},1", + "space": "{BCA661C5-E70D-076E-3034-C9F4B253A24B},1" + }, + { + "case": "Join empty adoption", + "intent": { + "author": "Offline author", + "left": "{F7F19A45-79BC-0FF0-3B34-A22033F38FB1},45", + "right": "{F7F19A45-79BC-0FF0-3B34-A22033F38FB1},50" + }, + "outcome": "retained_conflict", + "space": "{B1520A77-074F-0821-0405-457528B96164},1" + } +] \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/commands.jsonl b/corpus/paragraph-edit/reconciliation/reconciled/native/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..cb3c2a111b21a7326b68fd579f1793e987266689 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/commands.jsonl @@ -0,0 +1,3 @@ +{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null} +{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-C4BC54FD -ExpectedPages 17", "exit": 0, "stdout": "Read 1 sections and 17 pages.\r\n", "stderr": "", "error": null} +{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null} diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/notebook/Open Notebook.onetoc2 b/corpus/paragraph-edit/reconciliation/reconciled/native/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..b9bab8c52537429d44220695235ee851fb06b25f Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/reconciled/native/notebook/Open Notebook.onetoc2 differ diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/notebook/synthetic.one b/corpus/paragraph-edit/reconciliation/reconciled/native/notebook/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..936b9ab9cb382a5f778585b059c36bb42ec3cfd7 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/reconciled/native/notebook/synthetic.one differ diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/environment.json b/corpus/paragraph-edit/reconciliation/reconciled/native/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..65aa2c11c1ebdbd6f42f5804c7aab2e333b85de8 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-C4BC54FD", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/hierarchy.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..0441bcc4c362b34c6f9558ee8700e0455d3b0dbf --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-000.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..81c1ddb53e5bf54933e0d631bcd218afca494a83 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-000.xml @@ -0,0 +1,4 @@ + +Xab]]>🦀Cd]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-001.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..1e3c0a44d06f38f8164cd0599202c8bc0e71ae26 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-001.xml @@ -0,0 +1,4 @@ + +ab]]>🦀Cd]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-002.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..d3fc936e7fe651db0077215d8b151acaec9f3a81 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-002.xml @@ -0,0 +1,3 @@ + +Right]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-003.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..74ac54b851bf4c5a248faac016ae80a3491f38d8 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-003.xml @@ -0,0 +1,3 @@ + +ab🦀CdRight]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-004.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..7f704143d0cd08864436d46fc2d9c435b3b7224c --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-004.xml @@ -0,0 +1,3 @@ + +ab🦀CdXRight]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-005.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..73e4802abc70716f755ab5abcda28d93156d84b6 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-005.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-006.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..8c186c2049b406f4d2988b54dc6c4ab768fa1a63 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-006.xml @@ -0,0 +1,4 @@ + +abX]]>🦀Cd]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-007.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..6caf646c16101926c31bf4e183e22b1a71fe0bc8 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-007.xml @@ -0,0 +1,3 @@ + +ab🦀CdRight]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-008.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..a64bd030159d49e5a39d1dea87b50737558f004d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-008.xml @@ -0,0 +1,4 @@ + +ab]]>🦀Cd]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-009.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..574e842905eee4665974e53774334610e01e604d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-009.xml @@ -0,0 +1,4 @@ + +ab]]>🦀Cd]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-010.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..53ce13775c9a4597cacd837f842cdc5c766c9f57 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-010.xml @@ -0,0 +1,4 @@ + +ab🦀CdRight]]>Native child]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-011.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..5f9da940793a81e5edd9793998588904f3761844 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-011.xml @@ -0,0 +1,5 @@ + +ab]]>🦀Cd]]>Native child]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-012.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..e0f5b22e79144bbc918089e91c4c232a4304ca4a --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-012.xml @@ -0,0 +1,20 @@ + +Bold 🦀 italic é color 東京
+End
]]>
Fictitious: café, 東京, مرحبا]]>
diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-013.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..2674fc5835ded06fdb7c449ffa12c29ea2bad9d2 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-013.xml @@ -0,0 +1,4 @@ + +ab]]>🦀Cd]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-014.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..ea2d860a04647d8391d6e08fcb720119ceeeeb76 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-014.xml @@ -0,0 +1,3 @@ + +ab🦀CdXRight]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-015.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-015.xml new file mode 100644 index 0000000000000000000000000000000000000000..95b0b9ab9926bf25580ce122c42b43d21e5dbe21 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-015.xml @@ -0,0 +1,4 @@ + +ab🦀CdRight]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-016.xml b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-016.xml new file mode 100644 index 0000000000000000000000000000000000000000..fba65e6542efe81eaa6b811b94f4d245b44bdf4c --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/page-016.xml @@ -0,0 +1,3 @@ + +Xab🦀CdRightY]]> diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/read/payloads.json b/corpus/paragraph-edit/reconciliation/reconciled/native/read/payloads.json new file mode 120000 index 0000000000000000000000000000000000000000..787b4bae85038cda922f8befac6c8ed361fa8035 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/read/payloads.json @@ -0,0 +1 @@ +../../../../before/read/payloads.json \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/run.json b/corpus/paragraph-edit/reconciliation/reconciled/native/run.json new file mode 100644 index 0000000000000000000000000000000000000000..546fce9d6b573ef588180ddb0b1e6da6b0b249c6 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/Users/clo/dev/one/evidence/m10/paragraph-native-reconciled-01/candidate", + "expected_pages": 17, + "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/paragraph-edit/reconciliation/reconciled/native/scripts/cold.ps1 b/corpus/paragraph-edit/reconciliation/reconciled/native/scripts/cold.ps1 new file mode 120000 index 0000000000000000000000000000000000000000..26b7b0452f69923a3f8cb748d6b5206dbee28c45 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/scripts/cold.ps1 @@ -0,0 +1 @@ +../../../keyboard/scripts/cold.ps1 \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/scripts/read.ps1 b/corpus/paragraph-edit/reconciliation/reconciled/native/scripts/read.ps1 new file mode 120000 index 0000000000000000000000000000000000000000..112acdbaf069e052b224eff502f91d8a6b8b626e --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/scripts/read.ps1 @@ -0,0 +1 @@ +../../../keyboard/scripts/read.ps1 \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/source.json b/corpus/paragraph-edit/reconciliation/reconciled/native/source.json new file mode 100644 index 0000000000000000000000000000000000000000..7840b52fea33cd3cbab2c8bfb2072069366e8215 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/source.json @@ -0,0 +1,8 @@ +[ + { + "path": "synthetic.one", + "bytes": 171880, + "sha256": "1d35503a9b47fcd2f1e776e77f200a4d7390c6e1d3a63974f4e2b2cea7959692", + "mtime_ns": 1788888504006534380 + } +] diff --git a/corpus/paragraph-edit/reconciliation/reconciled/native/teardown.json b/corpus/paragraph-edit/reconciliation/reconciled/native/teardown.json new file mode 120000 index 0000000000000000000000000000000000000000..47a1192a30ea7da90676d631bb9a2687d829b43e --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/reconciled/native/teardown.json @@ -0,0 +1 @@ +../../../joined/teardown.json \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-remaining-script.json b/corpus/paragraph-edit/reconciliation/remote-remaining-script.json new file mode 100644 index 0000000000000000000000000000000000000000..4df2d62d423d2a267df09aa87e10ef250a32727b --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-remaining-script.json @@ -0,0 +1,5 @@ +{ + "sha256": "a7e23f927eaa9b7205aca31a37ac3eea3f27766c3661ac631cd07eb2d65f4ef4", + "source": "tools/native/paragraph-reconciliation.ps1", + "change": "Resume only cases 4 through 15 after observed first four applied updates; TagDef moved before PageSettings per published XSD" +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-script.json b/corpus/paragraph-edit/reconciliation/remote-script.json new file mode 100644 index 0000000000000000000000000000000000000000..b74a04ca57829688a890f7454a1ca83b4262b623 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-script.json @@ -0,0 +1,5 @@ +{ + "sha256": "c9da4ad1ca8af8203f1ceed49d34f6bd37cfb0b383082e4c808f22c34b5424b9", + "source": "tools/native/paragraph-reconciliation.ps1", + "switch": "Remote" +} \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Join empty adoption.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Join empty adoption.xml new file mode 100644 index 0000000000000000000000000000000000000000..6e9b989ba2bea5d78848e235446f5a1d816ac570 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Join empty adoption.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + X + + + Right]]> + + + + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Join left boundary.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Join left boundary.xml new file mode 100644 index 0000000000000000000000000000000000000000..649b08b1dbea08c72caf0ff48748c7f9d70c39ea --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Join left boundary.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + <span +style='font-weight:bold'>ab&#129408;cd</span>X + + + Right]]> + + + + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Join remote child.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote child.xml new file mode 100644 index 0000000000000000000000000000000000000000..7d103b9d1f228f5ed2acf5f5da485734a81a3895 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote child.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + ab🦀cd]]> + + + Right]]> + + + Native child + + + + + + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Join remote format.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote format.xml new file mode 100644 index 0000000000000000000000000000000000000000..a7577dc5529eca0e09c26e9ee0fc8cfc785e5e3c --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote format.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + ab🦀cd]]> + + + <i>Right</i> + + + + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Join remote list.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote list.xml new file mode 100644 index 0000000000000000000000000000000000000000..e393bde54011f484dc827a1849cf47b95bd9031f --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote list.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + ab🦀cd]]> + + + + + + Right]]> + + + + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Join remote prefix.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote prefix.xml new file mode 100644 index 0000000000000000000000000000000000000000..52875cc8a7e087674e0ddf2e3e7a18dfd4884e07 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote prefix.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + X<span +style='font-weight:bold'>ab&#129408;cd</span> + + + <span +style='font-weight:bold'>Right</span>Y + + + + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Join remote sibling.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote sibling.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d928152d16a316a4fe0f7c74d931a63a78d1219 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote sibling.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + ab🦀cd]]> + + + Right]]> + + + Native sibling + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Join remote tag.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote tag.xml new file mode 100644 index 0000000000000000000000000000000000000000..227960ad01d80afc5b30b948a747a28213e07005 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Join remote tag.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + ab🦀cd]]> + + + + Right]]> + + + + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Join right boundary.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Join right boundary.xml new file mode 100644 index 0000000000000000000000000000000000000000..047877a4097d7ee7fac81b1ab952b9fb12b157fc --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Join right boundary.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + ab🦀cd]]> + + + X<span +style='font-weight:bold'>Right</span> + + + + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Split remote format.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Split remote format.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e968891ebfd260b0b443a9db10f083699efe535 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Split remote format.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + <i>ab🦀cd</i> + + + + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Split remote sibling.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Split remote sibling.xml new file mode 100644 index 0000000000000000000000000000000000000000..ea38f26d72f1371d5d46f52d35f41ba2424bccbf --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Split remote sibling.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + ab🦀cd]]> + + + Native sibling + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote-updates/Split remote tag.xml b/corpus/paragraph-edit/reconciliation/remote-updates/Split remote tag.xml new file mode 100644 index 0000000000000000000000000000000000000000..97c71db5ab80678dcda683481491c56bd590f28d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote-updates/Split remote tag.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + ab🦀cd]]> + + + + + + + \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote/notebook/Open Notebook.onetoc2 b/corpus/paragraph-edit/reconciliation/remote/notebook/Open Notebook.onetoc2 new file mode 120000 index 0000000000000000000000000000000000000000..a6c7d197861f52dda5ecaf4da2ab7e471f409518 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/notebook/Open Notebook.onetoc2 @@ -0,0 +1 @@ +../../before/notebook/Open Notebook.onetoc2 \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote/notebook/synthetic.one b/corpus/paragraph-edit/reconciliation/remote/notebook/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..317425aa5b0367d84b785d972cc4a4bcf286ecc4 Binary files /dev/null and b/corpus/paragraph-edit/reconciliation/remote/notebook/synthetic.one differ diff --git a/corpus/paragraph-edit/reconciliation/remote/read/environment.json b/corpus/paragraph-edit/reconciliation/remote/read/environment.json new file mode 120000 index 0000000000000000000000000000000000000000..032ba3b41dd4114f7b416f0781d9c5fb61796d7f --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/environment.json @@ -0,0 +1 @@ +../../before/read/environment.json \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/remote/read/hierarchy.xml b/corpus/paragraph-edit/reconciliation/remote/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..0efc0fd8af4ecb859ebc80e4c3ad2d10231ff47d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-000.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..48b6406f1a0124f1c3a0e537b1ba087b433f683f --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-000.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-001.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..c1876c96a6dc66136dd0908386d1a9d25b48a4a9 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-001.xml @@ -0,0 +1,4 @@ + +ab🦀cdX]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-002.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..78025286ae6e0798de72860799f72e78b2301a6a --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-002.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>RightY]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-003.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..190d65e02977855084eb3375dd41ba7dd2250d77 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-003.xml @@ -0,0 +1,20 @@ + +Bold 🦀 italic é color 東京
+End
]]>
Fictitious: café, 東京, مرحبا]]>
diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-004.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..6313d0ac357e8394824dd785fabcc9e759246b2d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-004.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-005.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..f5f83c486fec6dae9898b422d7211de61dc777fa --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-005.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-006.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..7d7d75d926c6854fbaf261b76cdcbec4a67a0fbb --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-006.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-007.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..9f3c8510f80e5cf239032fbd00f60a2e6f6ec025 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-007.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-008.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..a8162ce14ca9ae4e5a2538fa9480af7701304cd7 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-008.xml @@ -0,0 +1,3 @@ + +abX🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-009.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..ada9dbe3ec9126928bd5a151719c61b4ab678e41 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-009.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-010.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..8eea3550dfa7046e7d4460d30c243a0d1919364d --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-010.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-011.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..dd80b12e9c3458b94ae87426c15b98872c84a310 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-011.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-012.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..5a58d4f7d6a459b9e14c20b30ebea7eeb78056b2 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-012.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-013.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..e06525cfacb955dc729d15c6bcec45ac3cd87291 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-013.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-014.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..aa6494b99e07b4576b677ed40d0b9aff44cf4129 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-014.xml @@ -0,0 +1,3 @@ + +ab🦀cd]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-015.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-015.xml new file mode 100644 index 0000000000000000000000000000000000000000..3b084c66185892c8120066dd399341a089d29022 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-015.xml @@ -0,0 +1,4 @@ + +ab🦀cd]]>Right]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/page-016.xml b/corpus/paragraph-edit/reconciliation/remote/read/page-016.xml new file mode 100644 index 0000000000000000000000000000000000000000..8bab569f32010cc2aef793831fade3caed64fc8c --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/page-016.xml @@ -0,0 +1,3 @@ + +Right]]> diff --git a/corpus/paragraph-edit/reconciliation/remote/read/payloads.json b/corpus/paragraph-edit/reconciliation/remote/read/payloads.json new file mode 120000 index 0000000000000000000000000000000000000000..3cf45dc1acb611d7f764e0340d73e87192f81407 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/remote/read/payloads.json @@ -0,0 +1 @@ +../../../before/read/payloads.json \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/run.json b/corpus/paragraph-edit/reconciliation/run.json new file mode 100644 index 0000000000000000000000000000000000000000..712a6a5028a94f2693f4b3215433a520f2d4c439 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/run.json @@ -0,0 +1,19 @@ +{ + "notebook": "/Users/clo/dev/one/corpus/formatted-insertion/native-paragraph/candidate", + "expected_pages": 17, + "author": "tools/native/paragraph-reconciliation.ps1", + "author_timeout_seconds": 600, + "inspect": true, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "author.ps1": "72afcfc5d33a43a2c03744b3378be461e869ba4e81fad6af8e73de17d99c2b5e", + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/paragraph-edit/reconciliation/scripts/author.ps1 b/corpus/paragraph-edit/reconciliation/scripts/author.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..3404b6e657a91af38ae38baaed70ac43ed5d30a6 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/scripts/author.ps1 @@ -0,0 +1,122 @@ +param([Parameter(Mandatory=$true)][string]$Root, [Parameter(Mandatory=$true)][string]$CloneHost, [switch]$Remote) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +if (-not $Remote) { & "$PSScriptRoot\cold-current.ps1" -Root $Root -CloneHost $CloneHost } +$app = New-Object -ComObject OneNote.Application +$notebook = '' +$ns = 'http://schemas.microsoft.com/office/onenote/2010/onenote' +try { + $app.OpenHierarchy((Join-Path $Root 'notebook'), '', [ref]$notebook, 0) + $section = '' + $app.OpenHierarchy('synthetic.one', $notebook, [ref]$section, 0) + if (-not $Remote) { + $cases = @( + @{ name = 'Split remote prefix'; operation = 'split'; change = 'prefix' }, + @{ name = 'Split remote boundary'; operation = 'split'; change = 'boundary' }, + @{ name = 'Split remote child'; operation = 'split'; change = 'child' }, + @{ name = 'Split remote list'; operation = 'split'; change = 'list' }, + @{ name = 'Split remote tag'; operation = 'split'; change = 'tag' }, + @{ name = 'Split remote format'; operation = 'split'; change = 'format' }, + @{ name = 'Split remote sibling'; operation = 'split'; change = 'sibling' }, + @{ name = 'Join remote prefix'; operation = 'join'; change = 'prefix' }, + @{ name = 'Join left boundary'; operation = 'join'; change = 'boundary' }, + @{ name = 'Join right boundary'; operation = 'join'; change = 'right-boundary' }, + @{ name = 'Join remote child'; operation = 'join'; change = 'child' }, + @{ name = 'Join remote list'; operation = 'join'; change = 'list' }, + @{ name = 'Join remote tag'; operation = 'join'; change = 'tag' }, + @{ name = 'Join remote format'; operation = 'join'; change = 'format' }, + @{ name = 'Join remote sibling'; operation = 'join'; change = 'sibling' }, + @{ name = 'Join empty adoption'; operation = 'join'; change = 'adoption' } + ) + foreach ($case in $cases) { + $page = '' + $app.CreateNewPage($section, [ref]$page, 0) + $left = if ($case.change -eq 'adoption') { '' } else { 'ab' + [char]::ConvertFromUtf32(0x1F980) + 'cd' } + $body = '' + $left + ']]>' + if ($case.operation -eq 'join') { $body += 'Right]]>' } + $body += 'Preserved sibling' + $xml = '' + $case.name + '' + $body + '' + $app.UpdatePageContent($xml, [DateTime]::MinValue, 1, $true) + } + $cases | ConvertTo-Json -Depth 6 | Set-Content (Join-Path $Root 'cases.json') -Encoding UTF8 + } else { + $cases = Get-Content (Join-Path $Root 'cases.json') -Raw | ConvertFrom-Json + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$tree = $hierarchy + $manager = New-Object Xml.XmlNamespaceManager($tree.NameTable) + $manager.AddNamespace('one', $ns) + foreach ($case in $cases) { + $page = @($tree.SelectNodes('//one:Page', $manager) | Where-Object { $_.GetAttribute('name') -eq $case.name }) + if ($page.Count -ne 1) { throw ('Expected one native control page: ' + $case.name) } + $content = '' + $app.GetPageContent($page[0].GetAttribute('ID'), [ref]$content, 0, 1) + [xml]$xml = $content + $manager = New-Object Xml.XmlNamespaceManager($xml.NameTable) + $manager.AddNamespace('one', $ns) + $outline = $xml.SelectSingleNode('/one:Page/one:Outline/one:OEChildren', $manager) + $paragraphs = @($outline.SelectNodes('one:OE', $manager)) + $left = $paragraphs[0] + $target = if ($case.operation -eq 'join') { $paragraphs[1] } else { $left } + switch ($case.change) { + 'prefix' { + $text = $left.SelectSingleNode('one:T', $manager) + $text.InnerText = 'X' + $text.InnerText + if ($case.operation -eq 'join') { + $text = $target.SelectSingleNode('one:T', $manager) + $text.InnerText += 'Y' + } + } + 'boundary' { + $text = $left.SelectSingleNode('one:T', $manager) + if ($case.operation -eq 'split') { + if (-not $text.InnerText.Contains('ab')) { throw 'The split boundary control lost its text' } + $text.InnerText = $text.InnerText.Replace('ab', 'abX') + } else { $text.InnerText += 'X' } + } + 'right-boundary' { + $text = $target.SelectSingleNode('one:T', $manager) + $text.InnerText = 'X' + $text.InnerText + } + 'child' { + $children = $xml.CreateElement('one', 'OEChildren', $ns) + $child = $xml.CreateElement('one', 'OE', $ns) + $text = $xml.CreateElement('one', 'T', $ns) + $text.InnerText = 'Native child' + [void]$child.AppendChild($text) + [void]$children.AppendChild($child) + [void]$target.AppendChild($children) + } + 'list' { + $list = $xml.CreateElement('one', 'List', $ns) + $bullet = $xml.CreateElement('one', 'Bullet', $ns) + $bullet.SetAttribute('bullet', '3') + $bullet.SetAttribute('fontSize', '11') + [void]$list.AppendChild($bullet) + [void]$target.PrependChild($list) + } + 'tag' { + $tag = $xml.CreateElement('one', 'Tag', $ns) + foreach ($pair in @{ index='0'; completed='false'; disabled='false'; creationDate='2020-01-02T03:04:05.000Z' }.GetEnumerator()) { $tag.SetAttribute($pair.Key, $pair.Value) } + [void]$target.PrependChild($tag) + } + 'format' { + $text = $target.SelectSingleNode('one:T', $manager) + $plain = if ($case.operation -eq 'join') { 'Right' } else { 'ab' + [char]::ConvertFromUtf32(0x1F980) + 'cd' } + $text.InnerText = '' + $plain + '' + } + 'sibling' { $paragraphs[-1].SelectSingleNode('one:T', $manager).InnerText = 'Native sibling' } + 'adoption' { $left.SelectSingleNode('one:T', $manager).InnerText = 'X' } + default { throw ('Unknown native control: ' + $case.change) } + } + $app.UpdatePageContent($xml.OuterXml, [DateTime]::MinValue, 1, $true) + } + } + $app.SyncHierarchy($notebook) +} finally { + if ($notebook) { $app.CloseNotebook($notebook, $false) } + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() +} diff --git a/corpus/paragraph-edit/reconciliation/scripts/cold.ps1 b/corpus/paragraph-edit/reconciliation/scripts/cold.ps1 new file mode 120000 index 0000000000000000000000000000000000000000..7692cdad6c6ff5292511de8850bf236e8cb3dab7 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/scripts/cold.ps1 @@ -0,0 +1 @@ +../keyboard/scripts/cold.ps1 \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/scripts/probe.ps1 b/corpus/paragraph-edit/reconciliation/scripts/probe.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..441f5ff2c9cbd1e1d35abc94f2d4a13ad0982ca0 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/scripts/probe.ps1 @@ -0,0 +1,24 @@ +$app = New-Object -ComObject OneNote.Application +$notebook = '' +$app.OpenHierarchy('C:\one-tests\runs\capture\notebook', '', [ref]$notebook, 0) +$section = '' +$app.OpenHierarchy('synthetic.one', $notebook, [ref]$section, 0) +$hierarchy = '' +$deadline = [DateTime]::UtcNow.AddSeconds(30) +do { + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$tree = $hierarchy + $pages = @($tree.SelectNodes('//*[local-name()="Page"]')) + if ($pages.Count -eq 17) { break } + Start-Sleep -Milliseconds 200 +} while ([DateTime]::UtcNow -lt $deadline) +Write-Output ('pages=' + $pages.Count) +Write-Output $hierarchy +foreach ($page in $tree.SelectNodes('//*[local-name()="Page"]')) { + $content = '' + $app.GetPageContent($page.GetAttribute('ID'), [ref]$content, 0, 1) + [xml]$xml = $content + $texts = @($xml.SelectNodes('//*[local-name()="Outline"]//*[local-name()="T"]') | ForEach-Object { $_.InnerText }) + @{ name=$page.GetAttribute('name'); texts=$texts; tags=@($xml.SelectNodes('//*[local-name()="Tag"]')).Count; lists=@($xml.SelectNodes('//*[local-name()="List"]')).Count } | ConvertTo-Json -Compress +} +$app.CloseNotebook($notebook, $false) diff --git a/corpus/paragraph-edit/reconciliation/scripts/read.ps1 b/corpus/paragraph-edit/reconciliation/scripts/read.ps1 new file mode 120000 index 0000000000000000000000000000000000000000..65e900c42b74f25f049c62b00e7c1042301f07cc --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/scripts/read.ps1 @@ -0,0 +1 @@ +../keyboard/scripts/read.ps1 \ No newline at end of file diff --git a/corpus/paragraph-edit/reconciliation/scripts/remote-remaining.ps1 b/corpus/paragraph-edit/reconciliation/scripts/remote-remaining.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..1c1629d7e7ff570e48670852e2b62410836387bb --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/scripts/remote-remaining.ps1 @@ -0,0 +1,138 @@ +param([Parameter(Mandatory=$true)][string]$Root, [Parameter(Mandatory=$true)][string]$CloneHost, [switch]$Remote) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +if (-not $Remote) { & "$PSScriptRoot\cold-current.ps1" -Root $Root -CloneHost $CloneHost } +$app = New-Object -ComObject OneNote.Application +$notebook = '' +$ns = 'http://schemas.microsoft.com/office/onenote/2010/onenote' +$tagDefinition = '' +try { + $app.OpenHierarchy((Join-Path $Root 'notebook'), '', [ref]$notebook, 0) + $section = '' + $app.OpenHierarchy('synthetic.one', $notebook, [ref]$section, 0) + if (-not $Remote) { + $cases = @( + @{ name = 'Split remote prefix'; operation = 'split'; change = 'prefix' }, + @{ name = 'Split remote boundary'; operation = 'split'; change = 'boundary' }, + @{ name = 'Split remote child'; operation = 'split'; change = 'child' }, + @{ name = 'Split remote list'; operation = 'split'; change = 'list' }, + @{ name = 'Split remote tag'; operation = 'split'; change = 'tag' }, + @{ name = 'Split remote format'; operation = 'split'; change = 'format' }, + @{ name = 'Split remote sibling'; operation = 'split'; change = 'sibling' }, + @{ name = 'Join remote prefix'; operation = 'join'; change = 'prefix' }, + @{ name = 'Join left boundary'; operation = 'join'; change = 'boundary' }, + @{ name = 'Join right boundary'; operation = 'join'; change = 'right-boundary' }, + @{ name = 'Join remote child'; operation = 'join'; change = 'child' }, + @{ name = 'Join remote list'; operation = 'join'; change = 'list' }, + @{ name = 'Join remote tag'; operation = 'join'; change = 'tag' }, + @{ name = 'Join remote format'; operation = 'join'; change = 'format' }, + @{ name = 'Join remote sibling'; operation = 'join'; change = 'sibling' }, + @{ name = 'Join empty adoption'; operation = 'join'; change = 'adoption' } + ) + foreach ($case in $cases) { + $page = '' + $app.CreateNewPage($section, [ref]$page, 0) + $left = if ($case.change -eq 'adoption') { '' } else { 'ab' + [char]::ConvertFromUtf32(0x1F980) + 'cd' } + $body = '' + $left + ']]>' + if ($case.operation -eq 'join') { $body += 'Right]]>' } + $body += 'Preserved sibling' + $xml = '' + $tagDefinition + '' + $case.name + '' + $body + '' + $app.UpdatePageContent($xml, [DateTime]::MinValue, 1, $true) + } + $cases | ConvertTo-Json -Depth 6 | Set-Content (Join-Path $Root 'cases.json') -Encoding UTF8 + } else { + $cases = Get-Content (Join-Path $Root 'cases.json') -Raw | ConvertFrom-Json + $hierarchy = '' + $deadline = [DateTime]::UtcNow.AddSeconds(30) + do { + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$tree = $hierarchy + $manager = New-Object Xml.XmlNamespaceManager($tree.NameTable) + $manager.AddNamespace('one', $ns) + if (@($tree.SelectNodes('//one:Page', $manager)).Count -eq $cases.Count + 1) { break } + Start-Sleep -Milliseconds 200 + } while ([DateTime]::UtcNow -lt $deadline) + $updates = Join-Path $Root 'remote-updates' + [void](New-Item -ItemType Directory -Path $updates -Force) + foreach ($case in @($cases)[4..15]) { + $page = @($tree.SelectNodes('//one:Page', $manager) | Where-Object { $_.GetAttribute('name') -eq $case.name }) + if ($page.Count -ne 1) { throw ('Expected one native control page: ' + $case.name) } + $content = '' + $app.GetPageContent($page[0].GetAttribute('ID'), [ref]$content, 0, 1) + [xml]$xml = $content + $manager = New-Object Xml.XmlNamespaceManager($xml.NameTable) + $manager.AddNamespace('one', $ns) + $outline = $xml.SelectSingleNode('/one:Page/one:Outline/one:OEChildren', $manager) + $paragraphs = @($outline.SelectNodes('one:OE', $manager)) + $left = $paragraphs[0] + $target = if ($case.operation -eq 'join') { $paragraphs[1] } else { $left } + switch ($case.change) { + 'prefix' { + $text = $left.SelectSingleNode('one:T', $manager) + $text.InnerText = 'X' + $text.InnerText + if ($case.operation -eq 'join') { + $text = $target.SelectSingleNode('one:T', $manager) + $text.InnerText += 'Y' + } + } + 'boundary' { + $text = $left.SelectSingleNode('one:T', $manager) + if ($case.operation -eq 'split') { + if (-not $text.InnerText.Contains('ab')) { throw 'The split boundary control lost its text' } + $text.InnerText = $text.InnerText.Replace('ab', 'abX') + } else { $text.InnerText += 'X' } + } + 'right-boundary' { + $text = $target.SelectSingleNode('one:T', $manager) + $text.InnerText = 'X' + $text.InnerText + } + 'child' { + $children = $xml.CreateElement('one', 'OEChildren', $ns) + $child = $xml.CreateElement('one', 'OE', $ns) + $text = $xml.CreateElement('one', 'T', $ns) + $text.InnerText = 'Native child' + [void]$child.AppendChild($text) + [void]$children.AppendChild($child) + [void]$target.AppendChild($children) + } + 'list' { + $list = $xml.CreateElement('one', 'List', $ns) + $bullet = $xml.CreateElement('one', 'Bullet', $ns) + $bullet.SetAttribute('bullet', '3') + $bullet.SetAttribute('fontSize', '11') + [void]$list.AppendChild($bullet) + [void]$target.PrependChild($list) + } + 'tag' { + if (-not $xml.SelectSingleNode('/one:Page/one:TagDef[@index="0"]', $manager)) { + $definition = $xml.CreateDocumentFragment() + $definition.InnerXml = $tagDefinition + [void]$xml.DocumentElement.PrependChild($definition) + } + $tag = $xml.CreateElement('one', 'Tag', $ns) + foreach ($pair in @{ index='0'; completed='false'; disabled='false'; creationDate='2020-01-02T03:04:05.000Z' }.GetEnumerator()) { $tag.SetAttribute($pair.Key, $pair.Value) } + [void]$target.PrependChild($tag) + } + 'format' { + $text = $target.SelectSingleNode('one:T', $manager) + $plain = if ($case.operation -eq 'join') { 'Right' } else { 'ab' + [char]::ConvertFromUtf32(0x1F980) + 'cd' } + $text.InnerText = '' + $plain + '' + } + 'sibling' { $paragraphs[-1].SelectSingleNode('one:T', $manager).InnerText = 'Native sibling' } + 'adoption' { $left.SelectSingleNode('one:T', $manager).InnerText = 'X' } + default { throw ('Unknown native control: ' + $case.change) } + } + $xml.Save((Join-Path $updates ($case.name + '.xml'))) + Write-Output ('Updating: ' + $case.name) + $app.UpdatePageContent($xml.OuterXml, [DateTime]::MinValue, 1, $true) + Write-Output ('Applied: ' + $case.name) + } + } + $app.SyncHierarchy($notebook) +} finally { + if ($notebook) { $app.CloseNotebook($notebook, $false) } + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() +} diff --git a/corpus/paragraph-edit/reconciliation/scripts/remote.ps1 b/corpus/paragraph-edit/reconciliation/scripts/remote.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..ba1f06b8a9b6aa0e1b2230125fbff9c2625c69e9 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/scripts/remote.ps1 @@ -0,0 +1,128 @@ +param([Parameter(Mandatory=$true)][string]$Root, [Parameter(Mandatory=$true)][string]$CloneHost, [switch]$Remote) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +if (-not $Remote) { & "$PSScriptRoot\cold-current.ps1" -Root $Root -CloneHost $CloneHost } +$app = New-Object -ComObject OneNote.Application +$notebook = '' +$ns = 'http://schemas.microsoft.com/office/onenote/2010/onenote' +$tagDefinition = '' +try { + $app.OpenHierarchy((Join-Path $Root 'notebook'), '', [ref]$notebook, 0) + $section = '' + $app.OpenHierarchy('synthetic.one', $notebook, [ref]$section, 0) + if (-not $Remote) { + $cases = @( + @{ name = 'Split remote prefix'; operation = 'split'; change = 'prefix' }, + @{ name = 'Split remote boundary'; operation = 'split'; change = 'boundary' }, + @{ name = 'Split remote child'; operation = 'split'; change = 'child' }, + @{ name = 'Split remote list'; operation = 'split'; change = 'list' }, + @{ name = 'Split remote tag'; operation = 'split'; change = 'tag' }, + @{ name = 'Split remote format'; operation = 'split'; change = 'format' }, + @{ name = 'Split remote sibling'; operation = 'split'; change = 'sibling' }, + @{ name = 'Join remote prefix'; operation = 'join'; change = 'prefix' }, + @{ name = 'Join left boundary'; operation = 'join'; change = 'boundary' }, + @{ name = 'Join right boundary'; operation = 'join'; change = 'right-boundary' }, + @{ name = 'Join remote child'; operation = 'join'; change = 'child' }, + @{ name = 'Join remote list'; operation = 'join'; change = 'list' }, + @{ name = 'Join remote tag'; operation = 'join'; change = 'tag' }, + @{ name = 'Join remote format'; operation = 'join'; change = 'format' }, + @{ name = 'Join remote sibling'; operation = 'join'; change = 'sibling' }, + @{ name = 'Join empty adoption'; operation = 'join'; change = 'adoption' } + ) + foreach ($case in $cases) { + $page = '' + $app.CreateNewPage($section, [ref]$page, 0) + $left = if ($case.change -eq 'adoption') { '' } else { 'ab' + [char]::ConvertFromUtf32(0x1F980) + 'cd' } + $body = '' + $left + ']]>' + if ($case.operation -eq 'join') { $body += 'Right]]>' } + $body += 'Preserved sibling' + $xml = '' + $tagDefinition + '' + $case.name + '' + $body + '' + $app.UpdatePageContent($xml, [DateTime]::MinValue, 1, $true) + } + $cases | ConvertTo-Json -Depth 6 | Set-Content (Join-Path $Root 'cases.json') -Encoding UTF8 + } else { + $cases = Get-Content (Join-Path $Root 'cases.json') -Raw | ConvertFrom-Json + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$tree = $hierarchy + $manager = New-Object Xml.XmlNamespaceManager($tree.NameTable) + $manager.AddNamespace('one', $ns) + foreach ($case in $cases) { + $page = @($tree.SelectNodes('//one:Page', $manager) | Where-Object { $_.GetAttribute('name') -eq $case.name }) + if ($page.Count -ne 1) { throw ('Expected one native control page: ' + $case.name) } + $content = '' + $app.GetPageContent($page[0].GetAttribute('ID'), [ref]$content, 0, 1) + [xml]$xml = $content + $manager = New-Object Xml.XmlNamespaceManager($xml.NameTable) + $manager.AddNamespace('one', $ns) + $outline = $xml.SelectSingleNode('/one:Page/one:Outline/one:OEChildren', $manager) + $paragraphs = @($outline.SelectNodes('one:OE', $manager)) + $left = $paragraphs[0] + $target = if ($case.operation -eq 'join') { $paragraphs[1] } else { $left } + switch ($case.change) { + 'prefix' { + $text = $left.SelectSingleNode('one:T', $manager) + $text.InnerText = 'X' + $text.InnerText + if ($case.operation -eq 'join') { + $text = $target.SelectSingleNode('one:T', $manager) + $text.InnerText += 'Y' + } + } + 'boundary' { + $text = $left.SelectSingleNode('one:T', $manager) + if ($case.operation -eq 'split') { + if (-not $text.InnerText.Contains('ab')) { throw 'The split boundary control lost its text' } + $text.InnerText = $text.InnerText.Replace('ab', 'abX') + } else { $text.InnerText += 'X' } + } + 'right-boundary' { + $text = $target.SelectSingleNode('one:T', $manager) + $text.InnerText = 'X' + $text.InnerText + } + 'child' { + $children = $xml.CreateElement('one', 'OEChildren', $ns) + $child = $xml.CreateElement('one', 'OE', $ns) + $text = $xml.CreateElement('one', 'T', $ns) + $text.InnerText = 'Native child' + [void]$child.AppendChild($text) + [void]$children.AppendChild($child) + [void]$target.AppendChild($children) + } + 'list' { + $list = $xml.CreateElement('one', 'List', $ns) + $bullet = $xml.CreateElement('one', 'Bullet', $ns) + $bullet.SetAttribute('bullet', '3') + $bullet.SetAttribute('fontSize', '11') + [void]$list.AppendChild($bullet) + [void]$target.PrependChild($list) + } + 'tag' { + if (-not $xml.SelectSingleNode('/one:Page/one:TagDef[@index="0"]', $manager)) { + $definition = $xml.CreateDocumentFragment() + $definition.InnerXml = $tagDefinition + [void]$xml.DocumentElement.InsertBefore($definition, $xml.SelectSingleNode('/one:Page/one:Title', $manager)) + } + $tag = $xml.CreateElement('one', 'Tag', $ns) + foreach ($pair in @{ index='0'; completed='false'; disabled='false'; creationDate='2020-01-02T03:04:05.000Z' }.GetEnumerator()) { $tag.SetAttribute($pair.Key, $pair.Value) } + [void]$target.PrependChild($tag) + } + 'format' { + $text = $target.SelectSingleNode('one:T', $manager) + $plain = if ($case.operation -eq 'join') { 'Right' } else { 'ab' + [char]::ConvertFromUtf32(0x1F980) + 'cd' } + $text.InnerText = '' + $plain + '' + } + 'sibling' { $paragraphs[-1].SelectSingleNode('one:T', $manager).InnerText = 'Native sibling' } + 'adoption' { $left.SelectSingleNode('one:T', $manager).InnerText = 'X' } + default { throw ('Unknown native control: ' + $case.change) } + } + $app.UpdatePageContent($xml.OuterXml, [DateTime]::MinValue, 1, $true) + } + } + $app.SyncHierarchy($notebook) +} finally { + if ($notebook) { $app.CloseNotebook($notebook, $false) } + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() +} diff --git a/corpus/paragraph-edit/reconciliation/teardown.json b/corpus/paragraph-edit/reconciliation/teardown.json new file mode 120000 index 0000000000000000000000000000000000000000..8b4fa29c76b0c84be8e3815d693a242cc55fbf90 --- /dev/null +++ b/corpus/paragraph-edit/reconciliation/teardown.json @@ -0,0 +1 @@ +../joined/teardown.json \ No newline at end of file diff --git a/crates/onestore-offline/tests/sync.rs b/crates/onestore-offline/tests/sync.rs index 9062a51cdfdae824e39ac4c086ce85f85cf9a24f..72f5f91088e951a2b0fe71ac7b683cbe3619d936 100644 --- a/crates/onestore-offline/tests/sync.rs +++ b/crates/onestore-offline/tests/sync.rs @@ -26,6 +26,234 @@ mod paragraph { (source, sid, left, parent) } + fn native_reconciliation(keyboard: bool) -> (Vec, Vec) { + let source = include_bytes!( + "../../../corpus/paragraph-edit/reconciliation/before/notebook/synthetic.one" + ); + let native: &[u8] = if keyboard { + include_bytes!( + "../../../corpus/paragraph-edit/reconciliation/keyboard/notebook/synthetic.one" + ) + } else { + include_bytes!( + "../../../corpus/paragraph-edit/reconciliation/remote/notebook/synthetic.one" + ) + }; + let store = Store::parse(source).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + let document = Document::parse(&index).unwrap(); + let mut server = Server::new(native); + let mut recorded = Vec::new(); + let mut counts = [0; 3]; + 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 { + continue; + }; + if !name.starts_with("Split ") && !name.starts_with("Join ") { + continue; + } + let outline = view.nodes[&page] + .children + .iter() + .find(|id| matches!(view.nodes[id].kind, Kind::Outline { .. })) + .unwrap(); + let children = &view.nodes[outline].children; + let left = view.nodes[&children[0]].content[0]; + let split = name.starts_with("Split "); + let adoption = name == "Join empty adoption"; + let directory = tempfile::tempdir().unwrap(); + let path = directory.path().join("native-reconciliation.sqlite"); + let mut cache = Replica::create(&path, source).unwrap(); + let (id, target, intent) = if split { + let intent = ParagraphSplit::new(left, 2, "Offline author").unwrap(); + ( + cache.split(source, sid, &intent).unwrap().unwrap(), + intent.text_object(), + serde_json::to_value(intent).unwrap(), + ) + } else { + let right = view.nodes[&children[1]].content[0]; + let intent = ParagraphJoin::new(left, right, "Offline author").unwrap(); + ( + cache.join(source, sid, &intent).unwrap().unwrap(), + if adoption { right } else { left }, + serde_json::to_value(intent).unwrap(), + ) + }; + drop(cache); + cache = Replica::open(&path).unwrap(); + let at = if split { + 2 + } else if adoption { + 1 + } else { + 4 + }; + let dependent = cache + .edit_text( + &cache.snapshot().unwrap(), + sid, + target, + at..at + 1, + if adoption { "I" } else { "C" }, + ) + .unwrap() + .unwrap(); + let local = cache.snapshot().unwrap(); + let pending = cache.pending().unwrap(); + drop(cache); + cache = Replica::open(&path).unwrap(); + assert_eq!(cache.snapshot().unwrap(), local); + assert_eq!(cache.pending().unwrap(), pending); + let previous = server.publications; + let remote = server.visible.clone(); + let (actual, status) = cache.sync_once(&mut server).unwrap().unwrap(); + assert_eq!(actual, id); + assert_eq!(cache.snapshot().unwrap(), local); + if !keyboard { + counts[2] += 1; + assert_eq!( + status, + EditStatus::Conflict(ConflictKind::TargetUnavailable), + "{name}" + ); + assert_eq!(server.publications, previous); + assert_eq!(server.visible, remote); + drop(cache); + cache = Replica::open(&path).unwrap(); + assert_eq!(cache.status(id).unwrap(), Some(status)); + assert_eq!(cache.snapshot().unwrap(), local); + assert_eq!(cache.pending().unwrap(), pending); + continue; + } + let automatic = ["prefix", "format", "sibling"] + .iter() + .any(|suffix| name.ends_with(suffix)); + if automatic { + counts[0] += 1; + assert!( + matches!(status, EditStatus::Published { .. }), + "{name}: {status:?}" + ); + } else { + let expected = if name.ends_with("boundary") || adoption { + ConflictKind::TextChanged + } else { + ConflictKind::StructureChanged + }; + assert_eq!(status, EditStatus::Conflict(expected), "{name}"); + assert_eq!(server.publications, previous); + assert_eq!(server.visible, remote); + assert_eq!(cache.pending().unwrap(), pending); + drop(cache); + cache = Replica::open(&path).unwrap(); + assert_eq!(cache.status(id).unwrap(), Some(status)); + assert_eq!(cache.snapshot().unwrap(), local); + assert_eq!(cache.pending().unwrap(), pending); + if adoption || name == "Join remote list" { + counts[2] += 1; + assert!(cache.rebase_join_conflict(id, &local, &remote).is_err()); + assert_eq!(cache.pending().unwrap(), pending); + assert_eq!(cache.snapshot().unwrap(), local); + assert_eq!(cache.status(id).unwrap(), Some(status)); + recorded.push(serde_json::json!({"case": name, "space": sid, "intent": intent, "outcome": "retained_conflict"})); + continue; + } + counts[1] += 1; + if split { + let offset = if name.ends_with("boundary") { 3 } else { 2 }; + cache + .rebase_conflict(id, &local, &remote, offset..offset) + .unwrap(); + let onestore_offline::Operation::Split(edit) = + &cache.pending().unwrap()[0].operation + else { + panic!() + }; + assert_eq!( + edit.intent, + serde_json::from_value::(intent.clone()) + .unwrap() + .reposition(offset) + ); + } else { + cache.rebase_join_conflict(id, &local, &remote).unwrap(); + } + drop(cache); + cache = Replica::open(&path).unwrap(); + let (actual, status) = cache.sync_once(&mut server).unwrap().unwrap(); + assert_eq!(actual, id); + assert!( + matches!(status, EditStatus::Published { .. }), + "{name}: {status:?}" + ); + } + drop(cache); + cache = Replica::open(&path).unwrap(); + let first_receipt = cache.status(id).unwrap().unwrap(); + let (actual, status) = cache.sync_once(&mut server).unwrap().unwrap(); + assert_eq!(actual, dependent); + assert!( + matches!(status, EditStatus::Published { .. }), + "{name} dependent: {status:?}" + ); + assert_eq!(server.publications, previous + 2); + drop(cache); + cache = Replica::open(&path).unwrap(); + assert_eq!(cache.status(id).unwrap(), Some(first_receipt)); + assert_eq!(cache.status(dependent).unwrap(), Some(status)); + assert!(cache.pending().unwrap().is_empty()); + assert_eq!(cache.snapshot().unwrap(), server.durable); + let EditStatus::Published { revision } = first_receipt else { + panic!() + }; + let EditStatus::Published { + revision: dependent_revision, + } = status + else { + panic!() + }; + recorded.push(serde_json::json!({"case": name, "space": sid, "intent": intent, + "outcome": if automatic { "automatic" } else { "reviewed" }, "receipt": revision, "dependent_receipt": dependent_revision})); + } + assert_eq!(counts, if keyboard { [6, 8, 2] } else { [0, 0, 16] }); + assert_eq!(server.publications, if keyboard { 28 } else { 0 }); + (server.durable, recorded) + } + + #[test] + fn native_com_replacement_preserves_every_local_paragraph_branch() { + native_reconciliation(false); + } + + #[test] + fn native_changes_commute_or_retain_reviewable_paragraph_dependencies() { + native_reconciliation(true); + } + + #[test] + #[ignore = "exports native-controlled reconciliation for cold OneNote validation"] + fn export_native_reconciliation() { + let output = std::path::PathBuf::from( + std::env::var_os("ONESTORE_NATIVE_RECONCILIATION_OUTPUT").unwrap(), + ); + assert!(output.is_absolute()); + std::fs::create_dir(&output).unwrap(); + let (bytes, cases) = native_reconciliation(true); + std::fs::create_dir(output.join("candidate")).unwrap(); + std::fs::write(output.join("candidate/synthetic.one"), bytes).unwrap(); + std::fs::write( + output.join("manifest.json"), + serde_json::to_vec_pretty(&cases).unwrap(), + ) + .unwrap(); + } + #[test] fn native_splits_retain_independent_local_identities_and_changed_boundaries() { let source = include_bytes!("../../../corpus/paragraph-edit/before/notebook/synthetic.one"); diff --git a/tools/native/paragraph-reconciliation.ps1 b/tools/native/paragraph-reconciliation.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..f6053c4d4652024a212e43037601a5acfbf745a6 --- /dev/null +++ b/tools/native/paragraph-reconciliation.ps1 @@ -0,0 +1,137 @@ +param([Parameter(Mandatory=$true)][string]$Root, [Parameter(Mandatory=$true)][string]$CloneHost, [switch]$Remote) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +if (-not $Remote) { & "$PSScriptRoot\cold-current.ps1" -Root $Root -CloneHost $CloneHost } +$app = New-Object -ComObject OneNote.Application +$notebook = '' +$ns = 'http://schemas.microsoft.com/office/onenote/2010/onenote' +try { + $app.OpenHierarchy((Join-Path $Root 'notebook'), '', [ref]$notebook, 0) + $section = '' + $app.OpenHierarchy('synthetic.one', $notebook, [ref]$section, 0) + if (-not $Remote) { + $cases = @( + @{ name = 'Split remote prefix'; operation = 'split'; change = 'prefix' }, + @{ name = 'Split remote boundary'; operation = 'split'; change = 'boundary' }, + @{ name = 'Split remote child'; operation = 'split'; change = 'child' }, + @{ name = 'Split remote list'; operation = 'split'; change = 'list' }, + @{ name = 'Split remote tag'; operation = 'split'; change = 'tag' }, + @{ name = 'Split remote format'; operation = 'split'; change = 'format' }, + @{ name = 'Split remote sibling'; operation = 'split'; change = 'sibling' }, + @{ name = 'Join remote prefix'; operation = 'join'; change = 'prefix' }, + @{ name = 'Join left boundary'; operation = 'join'; change = 'boundary' }, + @{ name = 'Join right boundary'; operation = 'join'; change = 'right-boundary' }, + @{ name = 'Join remote child'; operation = 'join'; change = 'child' }, + @{ name = 'Join remote list'; operation = 'join'; change = 'list' }, + @{ name = 'Join remote tag'; operation = 'join'; change = 'tag' }, + @{ name = 'Join remote format'; operation = 'join'; change = 'format' }, + @{ name = 'Join remote sibling'; operation = 'join'; change = 'sibling' }, + @{ name = 'Join empty adoption'; operation = 'join'; change = 'adoption' } + ) + foreach ($case in $cases) { + $page = '' + $app.CreateNewPage($section, [ref]$page, 0) + $left = if ($case.change -eq 'adoption') { '' } else { 'ab' + [char]::ConvertFromUtf32(0x1F980) + 'cd' } + $body = '' + $left + ']]>' + if ($case.operation -eq 'join') { $body += 'Right]]>' } + $body += 'Preserved sibling' + $xml = '' + $case.name + '' + $body + '' + $app.UpdatePageContent($xml, [DateTime]::MinValue, 1, $true) + } + $cases | ConvertTo-Json -Depth 6 | Set-Content (Join-Path $Root 'cases.json') -Encoding UTF8 + } else { + $cases = Get-Content (Join-Path $Root 'cases.json') -Raw | ConvertFrom-Json + $hierarchy = '' + $deadline = [DateTime]::UtcNow.AddSeconds(30) + do { + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$tree = $hierarchy + $manager = New-Object Xml.XmlNamespaceManager($tree.NameTable) + $manager.AddNamespace('one', $ns) + if (@($tree.SelectNodes('//one:Page', $manager)).Count -eq $cases.Count + 1) { break } + Start-Sleep -Milliseconds 200 + } while ([DateTime]::UtcNow -lt $deadline) + $updates = Join-Path $Root 'remote-updates' + [void](New-Item -ItemType Directory -Path $updates -Force) + foreach ($case in $cases) { + $page = @($tree.SelectNodes('//one:Page', $manager) | Where-Object { $_.GetAttribute('name') -eq $case.name }) + if ($page.Count -ne 1) { throw ('Expected one native control page: ' + $case.name) } + $content = '' + $app.GetPageContent($page[0].GetAttribute('ID'), [ref]$content, 0, 1) + [xml]$xml = $content + $manager = New-Object Xml.XmlNamespaceManager($xml.NameTable) + $manager.AddNamespace('one', $ns) + $outline = $xml.SelectSingleNode('/one:Page/one:Outline/one:OEChildren', $manager) + $paragraphs = @($outline.SelectNodes('one:OE', $manager)) + $left = $paragraphs[0] + $target = if ($case.operation -eq 'join') { $paragraphs[1] } else { $left } + switch ($case.change) { + 'prefix' { + $text = $left.SelectSingleNode('one:T', $manager) + $text.InnerText = 'X' + $text.InnerText + if ($case.operation -eq 'join') { + $text = $target.SelectSingleNode('one:T', $manager) + $text.InnerText += 'Y' + } + } + 'boundary' { + $text = $left.SelectSingleNode('one:T', $manager) + if ($case.operation -eq 'split') { + if (-not $text.InnerText.Contains('ab')) { throw 'The split boundary control lost its text' } + $text.InnerText = $text.InnerText.Replace('ab', 'abX') + } else { $text.InnerText += 'X' } + } + 'right-boundary' { + $text = $target.SelectSingleNode('one:T', $manager) + $text.InnerText = 'X' + $text.InnerText + } + 'child' { + $children = $xml.CreateElement('one', 'OEChildren', $ns) + $child = $xml.CreateElement('one', 'OE', $ns) + $text = $xml.CreateElement('one', 'T', $ns) + $text.InnerText = 'Native child' + [void]$child.AppendChild($text) + [void]$children.AppendChild($child) + [void]$target.AppendChild($children) + } + 'list' { + $list = $xml.CreateElement('one', 'List', $ns) + $bullet = $xml.CreateElement('one', 'Bullet', $ns) + $bullet.SetAttribute('bullet', '3') + $bullet.SetAttribute('fontSize', '11') + [void]$list.AppendChild($bullet) + [void]$target.PrependChild($list) + } + 'tag' { + if (-not $xml.SelectSingleNode('/one:Page/one:TagDef[@index="0"]', $manager)) { + $definition = $xml.CreateDocumentFragment() + $definition.InnerXml = '' + [void]$xml.DocumentElement.PrependChild($definition) + } + $tag = $xml.CreateElement('one', 'Tag', $ns) + foreach ($pair in @{ index='0'; completed='false'; disabled='false'; creationDate='2020-01-02T03:04:05.000Z' }.GetEnumerator()) { $tag.SetAttribute($pair.Key, $pair.Value) } + [void]$target.PrependChild($tag) + } + 'format' { + $text = $target.SelectSingleNode('one:T', $manager) + $plain = if ($case.operation -eq 'join') { 'Right' } else { 'ab' + [char]::ConvertFromUtf32(0x1F980) + 'cd' } + $text.InnerText = '' + $plain + '' + } + 'sibling' { $paragraphs[-1].SelectSingleNode('one:T', $manager).InnerText = 'Native sibling' } + 'adoption' { $left.SelectSingleNode('one:T', $manager).InnerText = 'X' } + default { throw ('Unknown native control: ' + $case.change) } + } + $xml.Save((Join-Path $updates ($case.name + '.xml'))) + Write-Output ('Updating: ' + $case.name) + $app.UpdatePageContent($xml.OuterXml, [DateTime]::MinValue, 1, $true) + Write-Output ('Applied: ' + $case.name) + } + } + $app.SyncHierarchy($notebook) +} finally { + if ($notebook) { $app.CloseNotebook($notebook, $false) } + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() +} diff --git a/tools/native_paragraph_reconciliation.py b/tools/native_paragraph_reconciliation.py new file mode 100644 index 0000000000000000000000000000000000000000..6b2569661f8e4b2316e4bdbe0a1ddd8714b4ba90 --- /dev/null +++ b/tools/native_paragraph_reconciliation.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Apply keyboard controls during a native paragraph-fixture inspection.""" +import argparse +import base64 +import json +from pathlib import Path +import re +import xml.etree.ElementTree as ET + +from native_runner import windows +from native_xml import ns + + +def apply(output): + target = json.loads((output / 'machine.json').read_text())['name'] + pages = {page.get('name'): page for path in (output / 'read').glob('page-*.xml') + for page in [ET.parse(path).getroot()]} + cases = json.loads((Path(__file__).resolve().parent.parent / + 'corpus/paragraph-edit/reconciliation/cases.json').read_text(encoding='utf-8-sig')) + scripts = output / 'keyboard' + scripts.mkdir() + for case in cases: + page = pages[case['name']] + paragraphs = page.findall('one:Outline/one:OEChildren/one:OE', ns) + join = case['operation'] == 'join' + change = case['change'] + at = 1 if join and change in ('child', 'list', 'tag', 'format', 'right-boundary') else 0 + keys = { + 'prefix': '{Left}X', + 'boundary': '{Right}X' if join else '{Left}{Right 2}X', + 'right-boundary': '{Left}X', + 'child': '{Right}{Enter}{Tab}Native child', + 'list': '{Left}^.', + 'tag': '{Left}^1', + 'format': '^i', + 'sibling': 'Native sibling', + 'adoption': '{Left}X', + }[change] + if change == 'sibling': + at = len(paragraphs) - 1 + steps = [(paragraphs[at].get('objectID'), keys)] + if join and change == 'prefix': + steps.append((paragraphs[1].get('objectID'), '{Right}Y')) + script = ('#Requires AutoHotkey v2.0\n' + 'OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1)))\n' + 'app := ComObject("OneNote.Application")\n') + for oid, keys in steps: + for identifier in (page.get('ID'), oid): + if not re.fullmatch(r'\{[0-9A-Fa-f-]+\}\{[0-9]+\}\{[0-9A-Fa-f]+\}', identifier): + raise ValueError('Invalid native fixture identity') + script += (f'app.NavigateTo("{page.get("ID")}", "{oid}", false)\n' + 'hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10)\n' + 'if !hwnd\n throw Error("OneNote window did not appear")\n' + 'WinMaximize(hwnd)\nWinActivate(hwnd)\n' + 'if !WinWaitActive(hwnd,, 10)\n throw Error("OneNote did not become active")\n' + f'Sleep 300\nSend "{keys}"\nSleep 300\n') + stem = scripts / case['name'].lower().replace(' ', '-') + stem.with_suffix('.ahk').write_text(script) + result = windows.do_exec(script, target=target, shot_delay_ms=500) + stem.with_suffix('.json').write_text(json.dumps({k: v for k, v in result.items() if k != 'png_b64'}, indent=2)) + if result.get('png_b64'): + stem.with_suffix('.png').write_bytes(base64.b64decode(result['png_b64'])) + if result.get('error') or result.get('exit') != 0 or not result.get('png_b64'): + raise RuntimeError(windows.text_result(result)) + print(case['name'], flush=True) + (output / 'finish').touch() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('output', type=Path) + apply(parser.parse_args().output) diff --git a/tools/test_paragraph_edit.py b/tools/test_paragraph_edit.py index 62bfe9cd08b5214d27602dd37f5b6e0f5a2cf497..a2530729f3cfd50aed366d457775afc2511e60d0 100644 --- a/tools/test_paragraph_edit.py +++ b/tools/test_paragraph_edit.py @@ -10,6 +10,7 @@ import xml.etree.ElementTree as ET from document_model import EXPORTER, ordered_pages, walk from native_format import compare_formats, native_characters from native_xml import ns +from offline_document_history import identity ROOT = Path(__file__).resolve().parent.parent FIXTURE = ROOT / 'corpus/paragraph-edit' @@ -17,6 +18,156 @@ compare = runpy.run_path(str(ROOT / 'tools/verify-document.py'))['compare'] class ParagraphEditTest(unittest.TestCase): + def test_reconciled_native_edits_keep_remote_content_and_exact_graphs(self): + fixture = FIXTURE / 'reconciliation' + result = fixture / 'reconciled' + self.assert_cold_graph(result) + manifest = json.loads((result / 'manifest.json').read_text()) + self.assertEqual(len(manifest), 16) + self.assertEqual({case['case'] for case in manifest if case['outcome'] == 'retained_conflict'}, + {'Join remote list', 'Join empty adoption'}) + receipts = [case[key] for case in manifest for key in ('receipt', 'dependent_receipt') if key in case] + self.assertEqual(len(set(receipts)), 28) + models, captures = {}, {} + with TemporaryDirectory() as temporary: + for phase, notebook, read in [('remote', fixture / 'keyboard/notebook', fixture / 'keyboard/read'), + ('reconciled', result / 'candidate', result / 'native/read')]: + folder = Path(temporary) / phase + subprocess.run([EXPORTER, notebook / 'synthetic.one', folder], check=True) + model = json.loads((folder / 'document.json').read_text()) + models[phase] = {r['nodes'][r['roots']['2']]['kind']['title']: (r, page) + for _, _, r, page in ordered_pages(model)} + captures[phase] = {page.get('name'): native_characters(page, page.findall('one:Outline', ns)) + for path in read.glob('page-*.xml') for page in [ET.parse(path).getroot()]} + for case in manifest: + name, intent = case['case'], case['intent'] + old, page = models['remote'][name] + new, new_page = models['reconciled'][name] + self.assertEqual(new_page, page) + outline, = [oid for oid in old['nodes'][page]['children'] if old['nodes'][oid]['kind']['type'] == 'Outline'] + graph = {oid: [list(node['children']), list(node['content']), node['child_level']] + for oid, node in walk(old, outline)} + characters = [list(paragraph) for paragraph in captures['remote'][name]] + if case['outcome'] != 'retained_conflict': + if name.startswith('Split '): + text = intent['text'] + paragraph, = [oid for oid, (_, content, _) in graph.items() if content == [text]] + parent, = [oid for oid, (children, _, _) in graph.items() if paragraph in children] + offset = 3 if name.endswith(('prefix', 'boundary')) else 2 + characters[:1] = [characters[0][:offset], characters[0][offset:]] + characters[1] = [('C' if char == 'c' else char, style) for char, style in characters[1]] + right, right_text = identity(intent, 1), identity(intent, 2) + self.assertNotIn(right, graph) + self.assertNotIn(right_text, graph) + graph[parent][0].insert(graph[parent][0].index(paragraph) + 1, right) + graph[right] = [graph[paragraph][0], [right_text], graph[paragraph][2]] + graph[right_text] = [[], [], None] + graph[paragraph][0] = [] + self.assertEqual(new['nodes'][right_text]['tags'], []) + else: + left, right = intent['left'], intent['right'] + a, = [oid for oid, (_, content, _) in graph.items() if content == [left]] + b, = [oid for oid, (_, content, _) in graph.items() if content == [right]] + parent, = [oid for oid, (children, _, _) in graph.items() if a in children] + graph[parent][0].remove(b) + graph[a][0] += graph[b][0] + del graph[b], graph[right] + characters[:2] = [characters[0] + characters[1]] + characters[0] = [('C' if char == 'c' else char, style) for char, style in characters[0]] + self.assertEqual(new['nodes'][left]['tags'], old['nodes'][left]['tags']) + with self.subTest(case=name): + self.assertEqual({oid: [node['children'], node['content'], node['child_level']] + for oid, node in walk(new, outline)}, graph) + for expected, actual in zip(characters, captures['reconciled'][name], strict=True): + for (a, before), (b, after) in zip(expected, actual, strict=True): + self.assertEqual(a, b) + for key in before.keys() | after.keys(): + default = 'automatic' if key in ('color', 'highlight') else False + self.assertEqual(before.get(key, default), after.get(key, default)) + + def test_native_reconciliation_controls_preserve_the_intended_edit_scope(self): + fixture = FIXTURE / 'reconciliation' + cases = json.loads((fixture / 'cases.json').read_text(encoding='utf-8-sig')) + self.assertEqual(len(cases), 16) + models, captures = {}, {} + with TemporaryDirectory() as temporary: + for phase in ('before', 'remote', 'keyboard'): + folder = Path(temporary) / phase + shutil.copytree(fixture / phase / 'read', folder / 'read') + compare(fixture / phase / 'notebook', folder / 'read') + subprocess.run([EXPORTER, fixture / phase / '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[phase] = {page.get('name'): native_characters(page, page.findall('one:Outline', ns)) + for path in (folder / 'read').glob('page-*.xml') for page in [ET.parse(path).getroot()]} + self.assertEqual(len(models[phase]), 17) + for case in cases: + name, change = case['name'], case['change'] + join = case['operation'] == 'join' + old, page = models['before'][name] + outline, = [oid for oid in old['nodes'][page]['children'] if old['nodes'][oid]['kind']['type'] == 'Outline'] + paragraphs = old['nodes'][outline]['children'] + target = paragraphs[1 if join and change in ('child', 'list', 'tag', 'format', 'right-boundary') else 0] + expected = ['' if change == 'adoption' else 'ab🦀cd'] + (['Right'] if join else []) + ['Preserved sibling'] + self.assertEqual([old['nodes'][old['nodes'][oid]['content'][0]]['kind']['text'] for oid in paragraphs], expected) + if change == 'prefix': + expected[0] = 'X' + expected[0] + if join: expected[1] += 'Y' + elif change == 'boundary': + expected[0] = expected[0] + 'X' if join else 'abX🦀cd' + elif change == 'right-boundary': expected[1] = 'XRight' + elif change == 'sibling': expected[-1] = 'Native sibling' + elif change == 'adoption': expected[0] = 'X' + for phase in ('remote', 'keyboard'): + with self.subTest(case=name, phase=phase): + current, current_page = models[phase][name] + if change == 'format': + for char, style in captures['before'][name][int(join)]: + self.assertTrue(style['bold']) + self.assertFalse(style.get('italic', False)) + for char, style in captures[phase][name][int(join)]: + self.assertTrue(style['italic']) + self.assertEqual(style.get('bold', False), phase == 'keyboard') + self.assertEqual(current_page, page) + active = [oid for oid, node in walk(current, outline) if node['kind']['type'] == 'Paragraph'] + expected_ids = list(paragraphs) + if phase == 'keyboard' and change == 'sibling': + self.assertNotEqual(active[-1], paragraphs[-1]) + expected_ids[-1] = active[-1] + if change == 'child': + child, = current['nodes'][target]['children'] + expected_ids.insert(expected_ids.index(target) + 1, child) + self.assertEqual(active, expected_ids) + actual_texts = [current['nodes'][current['nodes'][oid]['content'][0]]['kind']['text'] for oid in active] + expected_texts = list(expected) + if change == 'child': expected_texts.insert(2 if join else 1, 'Native child') + self.assertEqual(actual_texts, expected_texts) + top = list(paragraphs) + if phase == 'keyboard' and change == 'sibling': top[-1] = active[-1] + if phase == 'keyboard' and change == 'list': + if join: + top.remove(target) + self.assertEqual(current['nodes'][paragraphs[0]]['children'], [target]) + else: + group = current['nodes'][outline]['children'][0] + self.assertEqual(current['nodes'][group]['kind']['type'], 'OutlineGroup') + self.assertEqual(current['nodes'][group]['children'], [target]) + self.assertEqual(current['nodes'][group]['content'], []) + top[0] = group + self.assertEqual(current['nodes'][outline]['children'], top) + for oid in active: + node = current['nodes'][oid] + text, = node['content'] + if oid in paragraphs: + if phase == 'keyboard': self.assertEqual(node['content'], old['nodes'][oid]['content']) + else: self.assertNotEqual(node['content'], old['nodes'][oid]['content']) + child_count = int(oid == target and change == 'child') + if phase == 'keyboard' and join and change == 'list' and oid == paragraphs[0]: child_count = 1 + self.assertEqual(len(node['children']), child_count) + self.assertEqual(len(node['kind']['lists']), int(oid == target and change == 'list')) + self.assertEqual(len(current['nodes'][text]['tags']), int(oid == target and change == 'tag')) + def assert_cold_graph(self, fixture): with TemporaryDirectory() as temporary: models = []