From 8f943380df58facba8f67538e833f1e7f86a515a Mon Sep 17 00:00:00 2001 From: clover caruso Date: Thu, 10 Sep 2026 23:05:38 -0700 Subject: [PATCH] test: reopen page-model edits in OneNote and edit them natively Export a candidate notebook with eight compound PreparedEdit::page publications on the outline-edit fixture (reorder with Unicode replacement and bold, subtree move with a new nested child and italic/color/size, deletion with an appended paragraph and a new outline, mid-paragraph split, collapse with outline move and fixed width, outline reorder, outline deletion with underline/highlight/font, join with strike/subscript), capture it through a fresh OneNote 2010 cache, replace one Rust-written paragraph natively, and reopen that result cold. tools/test_page_model.py compares every page against the Rust model of each notebook, requires every page space to keep its active revision across the cold reopen, and checks each case against the manifest. Native results: 15/15 pages, 14 associated tags and 10,132 format comparisons match after the cold reopen; OneNote only adds its per-series navigation metadata copies to the section root, as for the untouched fixture. The native edit saves on top of the Rust output, and its cold reopen is byte-identical. Three owned clones removed. Acceptance: evidence/m10/PAGE-MODEL.md. Assisted-by: claude-fable-5.1 --- corpus/page-model/README.md | 32 + corpus/page-model/candidate/manifest.json | 1505 +++++++++++++++++ .../candidate/notebook/Open Notebook.onetoc2 | Bin 0 -> 4800 bytes .../candidate/notebook/synthetic.one | Bin 0 -> 119720 bytes corpus/page-model/cold/commands.jsonl | 3 + .../page-model/cold/format-differences.json | 1 + .../page-model/cold/geometry-differences.json | 1 + corpus/page-model/cold/machine.json | 1 + .../cold/notebook/Open Notebook.onetoc2 | Bin 0 -> 4800 bytes corpus/page-model/cold/notebook/synthetic.one | Bin 0 -> 123872 bytes corpus/page-model/cold/pdf-format-checks.json | 1 + corpus/page-model/cold/read/environment.json | 7 + corpus/page-model/cold/read/hierarchy.xml | 2 + corpus/page-model/cold/read/page-000.xml | 5 + corpus/page-model/cold/read/page-001.xml | 25 + corpus/page-model/cold/read/page-002.xml | 5 + corpus/page-model/cold/read/page-003.xml | 5 + corpus/page-model/cold/read/page-004.xml | 4 + corpus/page-model/cold/read/page-005.xml | 5 + corpus/page-model/cold/read/page-006.xml | 5 + corpus/page-model/cold/read/page-007.xml | 5 + corpus/page-model/cold/read/page-008.xml | 5 + corpus/page-model/cold/read/page-009.xml | 8 + corpus/page-model/cold/read/page-010.xml | 5 + corpus/page-model/cold/read/page-011.xml | 5 + corpus/page-model/cold/read/page-012.xml | 6 + corpus/page-model/cold/read/page-013.xml | 4 + corpus/page-model/cold/read/page-014.xml | 7 + corpus/page-model/cold/read/payloads.json | 3 + corpus/page-model/cold/run.json | 18 + corpus/page-model/cold/scripts/cold.ps1 | 27 + corpus/page-model/cold/scripts/read.ps1 | 142 ++ corpus/page-model/cold/source.json | 14 + corpus/page-model/cold/table-autofit.json | 1 + corpus/page-model/cold/teardown.json | 1 + .../page-model/followup-cold/commands.jsonl | 3 + .../followup-cold/format-differences.json | 1 + .../followup-cold/geometry-differences.json | 1 + corpus/page-model/followup-cold/machine.json | 1 + .../notebook/Open Notebook.onetoc2 | Bin 0 -> 4800 bytes .../followup-cold/notebook/synthetic.one | Bin 0 -> 127664 bytes .../followup-cold/pdf-format-checks.json | 1 + .../followup-cold/read/environment.json | 7 + .../followup-cold/read/hierarchy.xml | 2 + .../followup-cold/read/page-000.xml | 5 + .../followup-cold/read/page-001.xml | 5 + .../followup-cold/read/page-002.xml | 25 + .../followup-cold/read/page-003.xml | 4 + .../followup-cold/read/page-004.xml | 5 + .../followup-cold/read/page-005.xml | 5 + .../followup-cold/read/page-006.xml | 5 + .../followup-cold/read/page-007.xml | 5 + .../followup-cold/read/page-008.xml | 5 + .../followup-cold/read/page-009.xml | 4 + .../followup-cold/read/page-010.xml | 6 + .../followup-cold/read/page-011.xml | 5 + .../followup-cold/read/page-012.xml | 8 + .../followup-cold/read/page-013.xml | 5 + .../followup-cold/read/page-014.xml | 5 + .../followup-cold/read/payloads.json | 3 + corpus/page-model/followup-cold/run.json | 18 + .../page-model/followup-cold/scripts/cold.ps1 | 27 + .../page-model/followup-cold/scripts/read.ps1 | 142 ++ corpus/page-model/followup-cold/source.json | 14 + .../followup-cold/table-autofit.json | 1 + corpus/page-model/followup-cold/teardown.json | 1 + corpus/page-model/followup/before.xml | 7 + corpus/page-model/followup/commands.jsonl | 4 + corpus/page-model/followup/machine.json | 1 + corpus/page-model/followup/native-text.txt | 1 + .../followup/notebook/Open Notebook.onetoc2 | Bin 0 -> 4800 bytes .../followup/notebook/synthetic.one | Bin 0 -> 127664 bytes .../page-model/followup/read/environment.json | 7 + corpus/page-model/followup/read/hierarchy.xml | 2 + corpus/page-model/followup/read/page-000.xml | 5 + corpus/page-model/followup/read/page-001.xml | 25 + corpus/page-model/followup/read/page-002.xml | 5 + corpus/page-model/followup/read/page-003.xml | 5 + corpus/page-model/followup/read/page-004.xml | 4 + corpus/page-model/followup/read/page-005.xml | 5 + corpus/page-model/followup/read/page-006.xml | 5 + corpus/page-model/followup/read/page-007.xml | 5 + corpus/page-model/followup/read/page-008.xml | 5 + corpus/page-model/followup/read/page-009.xml | 5 + corpus/page-model/followup/read/page-010.xml | 8 + corpus/page-model/followup/read/page-011.xml | 5 + corpus/page-model/followup/read/page-012.xml | 6 + corpus/page-model/followup/read/page-013.xml | 4 + corpus/page-model/followup/read/page-014.xml | 5 + corpus/page-model/followup/read/payloads.json | 3 + corpus/page-model/followup/run.json | 19 + corpus/page-model/followup/scripts/author.ps1 | 43 + corpus/page-model/followup/scripts/cold.ps1 | 27 + corpus/page-model/followup/scripts/read.ps1 | 142 ++ corpus/page-model/followup/source.json | 14 + corpus/page-model/followup/teardown.json | 1 + corpus/page-model/provenance.json | 37 + crates/onestore/tests/page_writer.rs | 358 ++++ tools/native/page-model-followup.ps1 | 43 + tools/test_page_model.py | 133 ++ 100 files changed, 3116 insertions(+) create mode 100644 corpus/page-model/README.md create mode 100644 corpus/page-model/candidate/manifest.json create mode 100644 corpus/page-model/candidate/notebook/Open Notebook.onetoc2 create mode 100644 corpus/page-model/candidate/notebook/synthetic.one create mode 100644 corpus/page-model/cold/commands.jsonl create mode 100644 corpus/page-model/cold/format-differences.json create mode 100644 corpus/page-model/cold/geometry-differences.json create mode 100644 corpus/page-model/cold/machine.json create mode 100644 corpus/page-model/cold/notebook/Open Notebook.onetoc2 create mode 100644 corpus/page-model/cold/notebook/synthetic.one create mode 100644 corpus/page-model/cold/pdf-format-checks.json create mode 100644 corpus/page-model/cold/read/environment.json create mode 100644 corpus/page-model/cold/read/hierarchy.xml create mode 100644 corpus/page-model/cold/read/page-000.xml create mode 100644 corpus/page-model/cold/read/page-001.xml create mode 100644 corpus/page-model/cold/read/page-002.xml create mode 100644 corpus/page-model/cold/read/page-003.xml create mode 100644 corpus/page-model/cold/read/page-004.xml create mode 100644 corpus/page-model/cold/read/page-005.xml create mode 100644 corpus/page-model/cold/read/page-006.xml create mode 100644 corpus/page-model/cold/read/page-007.xml create mode 100644 corpus/page-model/cold/read/page-008.xml create mode 100644 corpus/page-model/cold/read/page-009.xml create mode 100644 corpus/page-model/cold/read/page-010.xml create mode 100644 corpus/page-model/cold/read/page-011.xml create mode 100644 corpus/page-model/cold/read/page-012.xml create mode 100644 corpus/page-model/cold/read/page-013.xml create mode 100644 corpus/page-model/cold/read/page-014.xml create mode 100644 corpus/page-model/cold/read/payloads.json create mode 100644 corpus/page-model/cold/run.json create mode 100644 corpus/page-model/cold/scripts/cold.ps1 create mode 100644 corpus/page-model/cold/scripts/read.ps1 create mode 100644 corpus/page-model/cold/source.json create mode 100644 corpus/page-model/cold/table-autofit.json create mode 100644 corpus/page-model/cold/teardown.json create mode 100644 corpus/page-model/followup-cold/commands.jsonl create mode 100644 corpus/page-model/followup-cold/format-differences.json create mode 100644 corpus/page-model/followup-cold/geometry-differences.json create mode 100644 corpus/page-model/followup-cold/machine.json create mode 100644 corpus/page-model/followup-cold/notebook/Open Notebook.onetoc2 create mode 100644 corpus/page-model/followup-cold/notebook/synthetic.one create mode 100644 corpus/page-model/followup-cold/pdf-format-checks.json create mode 100644 corpus/page-model/followup-cold/read/environment.json create mode 100644 corpus/page-model/followup-cold/read/hierarchy.xml create mode 100644 corpus/page-model/followup-cold/read/page-000.xml create mode 100644 corpus/page-model/followup-cold/read/page-001.xml create mode 100644 corpus/page-model/followup-cold/read/page-002.xml create mode 100644 corpus/page-model/followup-cold/read/page-003.xml create mode 100644 corpus/page-model/followup-cold/read/page-004.xml create mode 100644 corpus/page-model/followup-cold/read/page-005.xml create mode 100644 corpus/page-model/followup-cold/read/page-006.xml create mode 100644 corpus/page-model/followup-cold/read/page-007.xml create mode 100644 corpus/page-model/followup-cold/read/page-008.xml create mode 100644 corpus/page-model/followup-cold/read/page-009.xml create mode 100644 corpus/page-model/followup-cold/read/page-010.xml create mode 100644 corpus/page-model/followup-cold/read/page-011.xml create mode 100644 corpus/page-model/followup-cold/read/page-012.xml create mode 100644 corpus/page-model/followup-cold/read/page-013.xml create mode 100644 corpus/page-model/followup-cold/read/page-014.xml create mode 100644 corpus/page-model/followup-cold/read/payloads.json create mode 100644 corpus/page-model/followup-cold/run.json create mode 100644 corpus/page-model/followup-cold/scripts/cold.ps1 create mode 100644 corpus/page-model/followup-cold/scripts/read.ps1 create mode 100644 corpus/page-model/followup-cold/source.json create mode 100644 corpus/page-model/followup-cold/table-autofit.json create mode 100644 corpus/page-model/followup-cold/teardown.json create mode 100644 corpus/page-model/followup/before.xml create mode 100644 corpus/page-model/followup/commands.jsonl create mode 100644 corpus/page-model/followup/machine.json create mode 100644 corpus/page-model/followup/native-text.txt create mode 100644 corpus/page-model/followup/notebook/Open Notebook.onetoc2 create mode 100644 corpus/page-model/followup/notebook/synthetic.one create mode 100644 corpus/page-model/followup/read/environment.json create mode 100644 corpus/page-model/followup/read/hierarchy.xml create mode 100644 corpus/page-model/followup/read/page-000.xml create mode 100644 corpus/page-model/followup/read/page-001.xml create mode 100644 corpus/page-model/followup/read/page-002.xml create mode 100644 corpus/page-model/followup/read/page-003.xml create mode 100644 corpus/page-model/followup/read/page-004.xml create mode 100644 corpus/page-model/followup/read/page-005.xml create mode 100644 corpus/page-model/followup/read/page-006.xml create mode 100644 corpus/page-model/followup/read/page-007.xml create mode 100644 corpus/page-model/followup/read/page-008.xml create mode 100644 corpus/page-model/followup/read/page-009.xml create mode 100644 corpus/page-model/followup/read/page-010.xml create mode 100644 corpus/page-model/followup/read/page-011.xml create mode 100644 corpus/page-model/followup/read/page-012.xml create mode 100644 corpus/page-model/followup/read/page-013.xml create mode 100644 corpus/page-model/followup/read/page-014.xml create mode 100644 corpus/page-model/followup/read/payloads.json create mode 100644 corpus/page-model/followup/run.json create mode 100644 corpus/page-model/followup/scripts/author.ps1 create mode 100644 corpus/page-model/followup/scripts/cold.ps1 create mode 100644 corpus/page-model/followup/scripts/read.ps1 create mode 100644 corpus/page-model/followup/source.json create mode 100644 corpus/page-model/followup/teardown.json create mode 100644 corpus/page-model/provenance.json create mode 100644 tools/native/page-model-followup.ps1 create mode 100644 tools/test_page_model.py diff --git a/corpus/page-model/README.md b/corpus/page-model/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c1307cf93d91157ea6b88a82ede89a3b253f182d --- /dev/null +++ b/corpus/page-model/README.md @@ -0,0 +1,32 @@ +# Page-model edits through a cold native reopen + +`candidate` is `corpus/outline-edit/before` after eight compound `PreparedEdit::page` +publications, one per edited page, each combining several kinds of change in a single +transaction: paragraph reorder and Unicode replacement with a bold range; a subtree +move with a new nested child and an italic/colored/resized range; a subtree deletion +with an appended paragraph and a new two-paragraph outline; a mid-paragraph split; a +collapse with an outline move and fixed width; an outline reorder with text appended +in both; an outline deletion with underline/highlight/font changes; and a paragraph +join with strike/subscript. `candidate/manifest.json` records each case, the page's +position in the section and the model the writer read back. + +`cold` is an independent OneNote 2010 capture of the candidate through a fresh +application cache, with the notebook retained after the native open. `followup` +opens `cold/notebook` in another fresh clone and replaces the Rust-written Unicode +paragraph on "Move leaf down" natively (`tools/native/page-model-followup.ps1`); +`followup-cold` reopens that result cold. + +`PYTHONPATH=tools python3 -m unittest test_page_model -v` compares every page's +native XML with the Rust model of each notebook (text order, resolved formatting, +associated tags), requires the cold reopen to leave every page space's active +revision unchanged (OneNote only adds its per-series navigation metadata copies to +the section root on open, as it does for the untouched `outline-edit` fixture whose +first-page copy was already stale), and checks each case's expected outline positions, paragraph order, +nesting and collapse state in the candidate, the cold notebook and the follow-up. + +To regenerate: `ONESTORE_PAGE_MODEL_OUTPUT=/absolute/new cargo test -p onestore +--test page_writer export_native_page_model_candidates -- --ignored`, then +`tools/native_runner.py /absolute/new/candidate/notebook /absolute/new/cold +--expected-pages 15 --collect-notebook`, then the same runner on `cold/notebook` +with `--author tools/native/page-model-followup.ps1` into `followup`, and a final +cold capture of `followup/notebook` into `followup-cold`. Each runner removes its clone. diff --git a/corpus/page-model/candidate/manifest.json b/corpus/page-model/candidate/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..1c8744c160c47abf5fdbbf6b18f2bc39f57d6526 --- /dev/null +++ b/corpus/page-model/candidate/manifest.json @@ -0,0 +1,1505 @@ +{ + "author": "Rust page writer", + "cases": [ + { + "description": "Anchor moved last and replaced with Unicode text, bold range on Trailing sibling", + "expected": { + "outlines": [ + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": true, + "color": 4278190080, + "end": 12, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 57, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 67, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Target 🦀 é ﷟HYPERLINK \"https://example.invalid/outline\"Link label" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": true, + "color": 4278190080, + "end": 4, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 16, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Trailing sibling" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 17, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Rust 🦀 é 東京 שלום" + } + ], + "width_set_by_user": null, + "x": 72.0, + "y": 108.0 + }, + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Other outline" + } + ], + "width_set_by_user": null, + "x": 480.0, + "y": 108.0 + } + ], + "title": "Move leaf down" + }, + "index": 1, + "space": "{B7267338-BF83-0893-27A7-37F606DD20C8},1", + "title": "Move leaf down" + }, + { + "description": "Target subtree moved last with a new nested child, italic blue 14 pt range on Anchor", + "expected": { + "outlines": [ + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 16711680, + "end": 6, + "font": "Calibri", + "font_size": 14.0, + "highlight": 4278190080, + "italic": true, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Anchor" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 16, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Trailing sibling" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": true, + "color": 4278190080, + "end": 12, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 57, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 67, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Target 🦀 é ﷟HYPERLINK \"https://example.invalid/outline\"Link label" + }, + { + "collapsed": false, + "parent": 2, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 5, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": true, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Child" + }, + { + "collapsed": false, + "parent": 3, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 10, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Grandchild" + }, + { + "collapsed": false, + "parent": 2, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 14, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Nested by Rust" + } + ], + "width_set_by_user": null, + "x": 72.0, + "y": 108.0 + }, + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Other outline" + } + ], + "width_set_by_user": null, + "x": 480.0, + "y": 108.0 + } + ], + "title": "Move subtree down" + }, + "index": 2, + "space": "{9B80D7CA-18B4-02B0-1E85-6E8AA0DAD827},1", + "title": "Move subtree down" + }, + { + "description": "Anchor deleted, paragraph appended, new outline with two paragraphs at (300, 400)", + "expected": { + "outlines": [ + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": true, + "color": 4278190080, + "end": 12, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 57, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 67, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Target 🦀 é ﷟HYPERLINK \"https://example.invalid/outline\"Link label" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 16, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Trailing sibling" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 16, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Appended by Rust" + } + ], + "width_set_by_user": null, + "x": 72.0, + "y": 108.0 + }, + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Other outline" + } + ], + "width_set_by_user": null, + "x": 480.0, + "y": 108.0 + }, + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 16, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Rust outline one" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 16, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Rust outline two" + } + ], + "width_set_by_user": null, + "x": 300.0, + "y": 400.0 + } + ], + "title": "Delete leaf" + }, + "index": 8, + "space": "{363FE055-44E1-0B27-14A8-46278FD681FF},1", + "title": "Delete leaf" + }, + { + "description": "Anchor split in the middle", + "expected": { + "outlines": [ + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 3, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Anc" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 3, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "hor" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": true, + "color": 4278190080, + "end": 12, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 57, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 67, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Target 🦀 é ﷟HYPERLINK \"https://example.invalid/outline\"Link label" + }, + { + "collapsed": false, + "parent": 2, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 5, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": true, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Child" + }, + { + "collapsed": false, + "parent": 3, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 10, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Grandchild" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 16, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Trailing sibling" + } + ], + "width_set_by_user": null, + "x": 72.0, + "y": 108.0 + }, + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Other outline" + } + ], + "width_set_by_user": null, + "x": 480.0, + "y": 108.0 + } + ], + "title": "Delete subtree" + }, + "index": 9, + "space": "{8BBAD88F-D248-0959-00B3-2438A7065330},1", + "title": "Delete subtree" + }, + { + "description": "Target collapsed, outline moved to (90, 250.5) with a fixed 300 pt width", + "expected": { + "outlines": [ + { + "max_width": 300.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 6, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Anchor" + }, + { + "collapsed": true, + "parent": null, + "spans": [ + { + "bold": true, + "color": 4278190080, + "end": 12, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 57, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 67, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Target 🦀 é ﷟HYPERLINK \"https://example.invalid/outline\"Link label" + }, + { + "collapsed": false, + "parent": 1, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 5, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": true, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Child" + }, + { + "collapsed": false, + "parent": 2, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 10, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Grandchild" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 16, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Trailing sibling" + } + ], + "width_set_by_user": true, + "x": 90.0, + "y": 250.5 + }, + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Other outline" + } + ], + "width_set_by_user": null, + "x": 480.0, + "y": 108.0 + } + ], + "title": "Collapse subtree" + }, + "index": 6, + "space": "{FF88B513-029C-00E2-0082-9E3DCE1D7796},1", + "title": "Collapse subtree" + }, + { + "description": "first body outline moved after the second, first paragraph of each extended", + "expected": { + "outlines": [ + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 20, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Other outline (Rust)" + } + ], + "width_set_by_user": null, + "x": 480.0, + "y": 108.0 + }, + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Anchor (Rust)" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": true, + "color": 4278190080, + "end": 12, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 57, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 67, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Target 🦀 é ﷟HYPERLINK \"https://example.invalid/outline\"Link label" + }, + { + "collapsed": false, + "parent": 1, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 5, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": true, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Child" + }, + { + "collapsed": false, + "parent": 2, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 10, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Grandchild" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 16, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Trailing sibling" + } + ], + "width_set_by_user": null, + "x": 72.0, + "y": 108.0 + } + ], + "title": "Move outline" + }, + "index": 12, + "space": "{16207F40-69C9-0CA1-09B5-DC5712DB2BBE},1", + "title": "Move outline" + }, + { + "description": "second body outline deleted, underline, highlight and Consolas on a range of Anchor", + "expected": { + "outlines": [ + { + "max_width": 468.0, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 1, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 5, + "font": "Consolas", + "font_size": 11.0, + "highlight": 65535, + "italic": false, + "strike": false, + "subscript": false, + "underline": true + }, + { + "bold": false, + "color": 4278190080, + "end": 6, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Anchor" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": true, + "color": 4278190080, + "end": 12, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 13, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 57, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": false, + "color": 4278190080, + "end": 67, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Target 🦀 é ﷟HYPERLINK \"https://example.invalid/outline\"Link label" + }, + { + "collapsed": false, + "parent": 1, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 5, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": true, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Child" + }, + { + "collapsed": false, + "parent": 2, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 10, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Grandchild" + }, + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": false, + "color": 4278190080, + "end": 16, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Trailing sibling" + } + ], + "width_set_by_user": null, + "x": 72.0, + "y": 108.0 + } + ], + "title": "Delete outline" + }, + "index": 11, + "space": "{80E80543-87A1-0C3A-0816-22B190BDFC87},1", + "title": "Delete outline" + }, + { + "description": "the two paragraphs joined, strike and subscript on the first three units", + "expected": { + "outlines": [ + { + "max_width": 127.5136947631836, + "paragraphs": [ + { + "collapsed": false, + "parent": null, + "spans": [ + { + "bold": true, + "color": null, + "end": 3, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": null, + "strike": true, + "subscript": true, + "underline": true + }, + { + "bold": true, + "color": null, + "end": 4, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": null, + "strike": null, + "subscript": null, + "underline": true + }, + { + "bold": null, + "color": null, + "end": 5, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": null, + "strike": null, + "subscript": null, + "underline": null + }, + { + "bold": null, + "color": null, + "end": 7, + "font": "Arial", + "font_size": 13.5, + "highlight": null, + "italic": null, + "strike": null, + "subscript": null, + "underline": null + }, + { + "bold": null, + "color": null, + "end": 8, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": null, + "strike": null, + "subscript": null, + "underline": null + }, + { + "bold": null, + "color": null, + "end": 14, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": true, + "strike": true, + "subscript": null, + "underline": null + }, + { + "bold": null, + "color": null, + "end": 15, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": null, + "strike": null, + "subscript": null, + "underline": null + }, + { + "bold": null, + "color": null, + "end": 17, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": null, + "strike": null, + "subscript": false, + "underline": null + }, + { + "bold": null, + "color": null, + "end": 18, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": null, + "strike": null, + "subscript": null, + "underline": null + }, + { + "bold": null, + "color": 3678732, + "end": 23, + "font": "Calibri", + "font_size": 11.0, + "highlight": 65535, + "italic": null, + "strike": null, + "subscript": null, + "underline": null + }, + { + "bold": null, + "color": null, + "end": 24, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": null, + "strike": null, + "subscript": null, + "underline": null + }, + { + "bold": null, + "color": null, + "end": 26, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": null, + "strike": null, + "subscript": true, + "underline": null + }, + { + "bold": null, + "color": null, + "end": 27, + "font": "Calibri", + "font_size": 11.0, + "highlight": null, + "italic": null, + "strike": null, + "subscript": null, + "underline": null + }, + { + "bold": false, + "color": 4278190080, + "end": 30, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": null, + "subscript": null, + "underline": null + }, + { + "bold": true, + "color": 7949855, + "end": 48, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": true, + "color": 7949855, + "end": 50, + "font": "SimSun", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": true, + "color": 7949855, + "end": 52, + "font": "Calibri", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + }, + { + "bold": true, + "color": 7949855, + "end": 57, + "font": "Arial", + "font_size": 11.0, + "highlight": 4278190080, + "italic": false, + "strike": false, + "subscript": false, + "underline": false + } + ], + "text": "Bold 🦀 italic é color 東京\rEndFictitious: café, 東京, مرحبا" + } + ], + "width_set_by_user": false, + "x": 36.0, + "y": 14.40000057220459 + } + ], + "title": "Bold 🦀 italic é color 東京" + }, + "index": 0, + "space": "{64183EF4-4E19-0CBE-3D3B-88FF17D58B1C},1", + "title": "Bold 🦀 italic é color 東京" + } + ], + "source": "corpus/outline-edit/before/notebook/synthetic.one", + "transactions_added": 8 +} \ No newline at end of file diff --git a/corpus/page-model/candidate/notebook/Open Notebook.onetoc2 b/corpus/page-model/candidate/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..5814b0f6d1941721eba9f84289aa7d970c3f3e23 GIT binary patch literal 4800 zcmZ3e|KIuM`!b(-j|5(YE0x8k*3bLU5_!w1)hgFw_X_4i3~0dq?koZ6iC;aJUJ#%7 z_Qbjy(m;7+3{(Ce2taIBm;jW9iK7Xla6xK704&G>m0|(XAPfRP8lnQC=711H7)DlR zud0o@ZSB3`NTrJKguJEPP>HPkCnxNbzWXoD^;+`pLjFgXdTjI-&4v8P7@L|=vC$A1 z>LGCC%lEGvtHPEDKs~~d!!WghQH5nqwMgIH2>%wthR?>O#&(QAX_kbB25jO(JqSkK zKN~$`k>?d|+J+kpkR}An6wk4X@=-p7q&T>pAV}=N<1>+n9pNN^C%3-G!gK?e8)|c7K@UlQW$!WJpwWj1lC6yG&I1}$pDS~FTl_MmLZxrzz0>z!oUElKY$_) zP|*e!hAFZPGCO4$M6!YOJ|GRMO=d1Rp~GUJ?=!_>Tjz7B#6=)y%K&jPLnT8VLkU9$ zLn@HWWJqSvW5@@JqyptY9sp8608|ZjH50=(83q-QnIQdJ=G_C!GB6;=4@d?S2aE3t zikELpcihV`-9>TPp+t~4ws?6E`xaLmw4L^OUo*wfXPe2^rS)|uzp4TQ4`d_AC|G=4 zGS%wIT`um_w@SXieAD)mAUQ_^hTbcTEL=b~D=2PGGIGPh99P`bXfpf)#RpLLC>RZa P(Gb8H0?5T0to#80*j_}$ literal 0 HcmV?d00001 diff --git a/corpus/page-model/candidate/notebook/synthetic.one b/corpus/page-model/candidate/notebook/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..825678cbeddf443be391fa6dfadfab946270690a GIT binary patch literal 119720 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 P(Gb8H0?5T0to#80*j_}$ literal 0 HcmV?d00001 diff --git a/corpus/page-model/cold/notebook/synthetic.one b/corpus/page-model/cold/notebook/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..b89cecf3c6a19fc7a582e417142f48b0a0e9bee5 GIT binary patch literal 123872 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 MCxvI>8Z8g_4}L95D*ylh literal 0 HcmV?d00001 diff --git a/corpus/page-model/cold/pdf-format-checks.json b/corpus/page-model/cold/pdf-format-checks.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/corpus/page-model/cold/pdf-format-checks.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/corpus/page-model/cold/read/environment.json b/corpus/page-model/cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..97ef6379034194d40a5e909d2ae0459d9f5e0ba4 --- /dev/null +++ b/corpus/page-model/cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-A298124B", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-model/cold/read/hierarchy.xml b/corpus/page-model/cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..fd224f1883d975b4ad607981b9f37c861607f77f --- /dev/null +++ b/corpus/page-model/cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-model/cold/read/page-000.xml b/corpus/page-model/cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..cdd8d5a5300c396039a7b9d950b44edb40721ae6 --- /dev/null +++ b/corpus/page-model/cold/read/page-000.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-001.xml b/corpus/page-model/cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..7fae1848bc9bc3fafb1c1a3a1f726b05b02fe717 --- /dev/null +++ b/corpus/page-model/cold/read/page-001.xml @@ -0,0 +1,25 @@ + +Bold 🦀 italic é color 東京
+End
Fictitious: café, 東京, مرحبا]]>
diff --git a/corpus/page-model/cold/read/page-002.xml b/corpus/page-model/cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..912f188fc0db194126cd0c4d65b2d0551ba48639 --- /dev/null +++ b/corpus/page-model/cold/read/page-002.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-003.xml b/corpus/page-model/cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..a93fe21237a05a2554304704e2b36b764d3d6835 --- /dev/null +++ b/corpus/page-model/cold/read/page-003.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-004.xml b/corpus/page-model/cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..6714ad0c7a2999b248fc433c632ae5a75d9bf0cd --- /dev/null +++ b/corpus/page-model/cold/read/page-004.xml @@ -0,0 +1,4 @@ + +Target 🦀 é Link label]]> diff --git a/corpus/page-model/cold/read/page-005.xml b/corpus/page-model/cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..0bdb2812db741f8c1ae79ea92ee659dd34394748 --- /dev/null +++ b/corpus/page-model/cold/read/page-005.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-006.xml b/corpus/page-model/cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..78bd080854f4d01bb8f75f8410fa662b25570a9a --- /dev/null +++ b/corpus/page-model/cold/read/page-006.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-007.xml b/corpus/page-model/cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..7311086900e4065b4c6667d1c885530f2d21f605 --- /dev/null +++ b/corpus/page-model/cold/read/page-007.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-008.xml b/corpus/page-model/cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..c8c5fc98bd379a36e75692477086c6ce031d0658 --- /dev/null +++ b/corpus/page-model/cold/read/page-008.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-009.xml b/corpus/page-model/cold/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..e45763cebeb296bd8ad5ea9ef67d259a6353b3bb --- /dev/null +++ b/corpus/page-model/cold/read/page-009.xml @@ -0,0 +1,8 @@ + +Anchor]]>Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-010.xml b/corpus/page-model/cold/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..68204199b681e1994a9229b62f91f7cb25759bcb --- /dev/null +++ b/corpus/page-model/cold/read/page-010.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-011.xml b/corpus/page-model/cold/read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..f06ecb9b24864e22dba90e1bb2d8c82a064cd28d --- /dev/null +++ b/corpus/page-model/cold/read/page-011.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-012.xml b/corpus/page-model/cold/read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..f48f4db295b0b9f2a27e6a225a49e9f7fcaad1d0 --- /dev/null +++ b/corpus/page-model/cold/read/page-012.xml @@ -0,0 +1,6 @@ + +Anchor]]>Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/cold/read/page-013.xml b/corpus/page-model/cold/read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..929e4aa8822587464ee2d155d29dce707946ca65 --- /dev/null +++ b/corpus/page-model/cold/read/page-013.xml @@ -0,0 +1,4 @@ + +Target 🦀 é Link label]]> diff --git a/corpus/page-model/cold/read/page-014.xml b/corpus/page-model/cold/read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..b35b364f4fce294fcbdbceb0e3061f31240ae709 --- /dev/null +++ b/corpus/page-model/cold/read/page-014.xml @@ -0,0 +1,7 @@ + +Target 🦀 é Link label]]>Trailing sibling]]>Rust 🦀 é 東京 שלום]]> diff --git a/corpus/page-model/cold/read/payloads.json b/corpus/page-model/cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-model/cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-model/cold/run.json b/corpus/page-model/cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..1a3ac72580c55a5fcef640b5cc2644c939e87a84 --- /dev/null +++ b/corpus/page-model/cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/tmp/page-model/candidate/notebook", + "expected_pages": 15, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-model/cold/scripts/cold.ps1 b/corpus/page-model/cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-model/cold/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/page-model/cold/scripts/read.ps1 b/corpus/page-model/cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-model/cold/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/page-model/cold/source.json b/corpus/page-model/cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..f0ca3ba96036b4221b8c96e54c2a5c3dbb9fa253 --- /dev/null +++ b/corpus/page-model/cold/source.json @@ -0,0 +1,14 @@ +[ + { + "path": "Open Notebook.onetoc2", + "bytes": 4800, + "sha256": "341894b32b0433a1e8b647431f71e372d344c74e0f87699e45c9235964082551", + "mtime_ns": 1788890614579474155 + }, + { + "path": "synthetic.one", + "bytes": 119720, + "sha256": "a5ca37027575ea012fce7fd4131ffb7c184b65bc32836a3f33556ee5162cdbc3", + "mtime_ns": 1789107784789511093 + } +] diff --git a/corpus/page-model/cold/table-autofit.json b/corpus/page-model/cold/table-autofit.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/corpus/page-model/cold/table-autofit.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/corpus/page-model/cold/teardown.json b/corpus/page-model/cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-model/cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-model/followup-cold/commands.jsonl b/corpus/page-model/followup-cold/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..db68e272ae7b372eef26403f745860d8c3f26268 --- /dev/null +++ b/corpus/page-model/followup-cold/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-3CAF6D8E -ExpectedPages 15", "exit": 0, "stdout": "Read 1 sections and 15 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/page-model/followup-cold/format-differences.json b/corpus/page-model/followup-cold/format-differences.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/corpus/page-model/followup-cold/format-differences.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/corpus/page-model/followup-cold/geometry-differences.json b/corpus/page-model/followup-cold/geometry-differences.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/corpus/page-model/followup-cold/geometry-differences.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/corpus/page-model/followup-cold/machine.json b/corpus/page-model/followup-cold/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..7d7aed8f1e66d397e38bde8a4f94fbeb8c746158 --- /dev/null +++ b/corpus/page-model/followup-cold/machine.json @@ -0,0 +1 @@ +{"name": "m6-3caf6d8e", "hostname": "ONE-M6-3CAF6D8E"} diff --git a/corpus/page-model/followup-cold/notebook/Open Notebook.onetoc2 b/corpus/page-model/followup-cold/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..5814b0f6d1941721eba9f84289aa7d970c3f3e23 GIT binary patch literal 4800 zcmZ3e|KIuM`!b(-j|5(YE0x8k*3bLU5_!w1)hgFw_X_4i3~0dq?koZ6iC;aJUJ#%7 z_Qbjy(m;7+3{(Ce2taIBm;jW9iK7Xla6xK704&G>m0|(XAPfRP8lnQC=711H7)DlR zud0o@ZSB3`NTrJKguJEPP>HPkCnxNbzWXoD^;+`pLjFgXdTjI-&4v8P7@L|=vC$A1 z>LGCC%lEGvtHPEDKs~~d!!WghQH5nqwMgIH2>%wthR?>O#&(QAX_kbB25jO(JqSkK zKN~$`k>?d|+J+kpkR}An6wk4X@=-p7q&T>pAV}=N<1>+n9pNN^C%3-G!gK?e8)|c7K@UlQW$!WJpwWj1lC6yG&I1}$pDS~FTl_MmLZxrzz0>z!oUElKY$_) zP|*e!hAFZPGCO4$M6!YOJ|GRMO=d1Rp~GUJ?=!_>Tjz7B#6=)y%K&jPLnT8VLkU9$ zLn@HWWJqSvW5@@JqyptY9sp8608|ZjH50=(83q-QnIQdJ=G_C!GB6;=4@d?S2aE3t zikELpcihV`-9>TPp+t~4ws?6E`xaLmw4L^OUo*wfXPe2^rS)|uzp4TQ4`d_AC|G=4 zGS%wIT`um_w@SXieAD)mAUQ_^hTbcTEL=b~D=2PGGIGPh99P`bXfpf)#RpLLC>RZa P(Gb8H0?5T0to#80*j_}$ literal 0 HcmV?d00001 diff --git a/corpus/page-model/followup-cold/notebook/synthetic.one b/corpus/page-model/followup-cold/notebook/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..866983b63f7a2c0a91045600e6e0090d2e38eff2 GIT binary patch literal 127664 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 b24*a`bS#+Il*`-etpwgm;J1)KSN;FLdd~7r literal 0 HcmV?d00001 diff --git a/corpus/page-model/followup-cold/pdf-format-checks.json b/corpus/page-model/followup-cold/pdf-format-checks.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/corpus/page-model/followup-cold/pdf-format-checks.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/corpus/page-model/followup-cold/read/environment.json b/corpus/page-model/followup-cold/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..43b556f1b4cf42bfd37d85816130c48ee5db9b05 --- /dev/null +++ b/corpus/page-model/followup-cold/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-3CAF6D8E", + "cold": true, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-model/followup-cold/read/hierarchy.xml b/corpus/page-model/followup-cold/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..061a800637b9a23f0ec2f31c7d370113e508d36a --- /dev/null +++ b/corpus/page-model/followup-cold/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-model/followup-cold/read/page-000.xml b/corpus/page-model/followup-cold/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..9a01dd16894e7ebeaf1e43f1c03559facc2c08f3 --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-000.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/page-001.xml b/corpus/page-model/followup-cold/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..d7874313dae613a9b923edf885038180e0dd2018 --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-001.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/page-002.xml b/corpus/page-model/followup-cold/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..2cd0a70dd1e44fcc029e030a69e229a2ebb6de1b --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-002.xml @@ -0,0 +1,25 @@ + +Bold 🦀 italic é color 東京
+End
Fictitious: café, 東京, مرحبا]]>
diff --git a/corpus/page-model/followup-cold/read/page-003.xml b/corpus/page-model/followup-cold/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..44d97aca0dc3069c10a2ae4d1f1679449dd5a952 --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-003.xml @@ -0,0 +1,4 @@ + +Target 🦀 é Link label]]> diff --git a/corpus/page-model/followup-cold/read/page-004.xml b/corpus/page-model/followup-cold/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..6fd3b3e9da17a0f4b51308599ba48cc260741b40 --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-004.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/page-005.xml b/corpus/page-model/followup-cold/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..ac5281a2286f41e2ff1bc86dfede8de821f1ccae --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-005.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/page-006.xml b/corpus/page-model/followup-cold/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..9a881e4f7e211e1c4c835760ecd5c7b047fb52c6 --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-006.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/page-007.xml b/corpus/page-model/followup-cold/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..82eff189219270eef4304b6d3d546b55d15dd3a1 --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-007.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/page-008.xml b/corpus/page-model/followup-cold/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..bfb0e7521f427bac718632ace1bbb218169ad615 --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-008.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Trailing sibling]]> diff --git a/corpus/page-model/followup-cold/read/page-009.xml b/corpus/page-model/followup-cold/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..279410c4bba45b5f2fbbb328c3e7467814c650aa --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-009.xml @@ -0,0 +1,4 @@ + +Target 🦀 é Link label]]> diff --git a/corpus/page-model/followup-cold/read/page-010.xml b/corpus/page-model/followup-cold/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..db64a92f227db5e95bd5f1efcd7e55415d93ac7e --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-010.xml @@ -0,0 +1,6 @@ + +Anchor]]>Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/page-011.xml b/corpus/page-model/followup-cold/read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..be44336100e59aec4bbac0c6bf2896c23c1f2b27 --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-011.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/page-012.xml b/corpus/page-model/followup-cold/read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..8d470632f07479305862ace8681927a05b0564ca --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-012.xml @@ -0,0 +1,8 @@ + +Anchor]]>Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/page-013.xml b/corpus/page-model/followup-cold/read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..7d8611d8ad913e301bdc617ddf11b317941e4193 --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-013.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/page-014.xml b/corpus/page-model/followup-cold/read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..8f8180a6978889becd11f4a2cbe80fdb04905021 --- /dev/null +++ b/corpus/page-model/followup-cold/read/page-014.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup-cold/read/payloads.json b/corpus/page-model/followup-cold/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-model/followup-cold/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-model/followup-cold/run.json b/corpus/page-model/followup-cold/run.json new file mode 100644 index 0000000000000000000000000000000000000000..a3f67751d55bbc3fd4854e88663a723ff232bba6 --- /dev/null +++ b/corpus/page-model/followup-cold/run.json @@ -0,0 +1,18 @@ +{ + "notebook": "/private/tmp/page-model/followup/notebook", + "expected_pages": 15, + "author": null, + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-model/followup-cold/scripts/cold.ps1 b/corpus/page-model/followup-cold/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-model/followup-cold/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/page-model/followup-cold/scripts/read.ps1 b/corpus/page-model/followup-cold/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-model/followup-cold/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/page-model/followup-cold/source.json b/corpus/page-model/followup-cold/source.json new file mode 100644 index 0000000000000000000000000000000000000000..eea6760b5ae2ae7b63654d66a2f7f891bbc8782e --- /dev/null +++ b/corpus/page-model/followup-cold/source.json @@ -0,0 +1,14 @@ +[ + { + "path": "Open Notebook.onetoc2", + "bytes": 4800, + "sha256": "341894b32b0433a1e8b647431f71e372d344c74e0f87699e45c9235964082551", + "mtime_ns": 1789109003103685572 + }, + { + "path": "synthetic.one", + "bytes": 127664, + "sha256": "d3f67a59581e9314cc476ea6f9cdef12bfcbce131335da591c68ae35886cace2", + "mtime_ns": 1789109003103953701 + } +] diff --git a/corpus/page-model/followup-cold/table-autofit.json b/corpus/page-model/followup-cold/table-autofit.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/corpus/page-model/followup-cold/table-autofit.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/corpus/page-model/followup-cold/teardown.json b/corpus/page-model/followup-cold/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-model/followup-cold/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-model/followup/before.xml b/corpus/page-model/followup/before.xml new file mode 100644 index 0000000000000000000000000000000000000000..68aca4c763f483fc8ff7037544deb3fb58cf9f1a --- /dev/null +++ b/corpus/page-model/followup/before.xml @@ -0,0 +1,7 @@ + +Target 🦀 é Link label]]>Trailing sibling]]>Rust 🦀 é 東京 שלום]]> diff --git a/corpus/page-model/followup/commands.jsonl b/corpus/page-model/followup/commands.jsonl new file mode 100644 index 0000000000000000000000000000000000000000..0344ee05bb75f4950c49dbae5380d59594c70dd2 --- /dev/null +++ b/corpus/page-model/followup/commands.jsonl @@ -0,0 +1,4 @@ +{"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-A302D412", "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-A302D412 -ExpectedPages 15 -UseCurrentCache", "exit": 0, "stdout": "Read 1 sections and 15 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/page-model/followup/machine.json b/corpus/page-model/followup/machine.json new file mode 100644 index 0000000000000000000000000000000000000000..6e97d47cc8edf5c9b65c203076631b82c349f6b8 --- /dev/null +++ b/corpus/page-model/followup/machine.json @@ -0,0 +1 @@ +{"name": "m6-a302d412", "hostname": "ONE-M6-A302D412"} diff --git a/corpus/page-model/followup/native-text.txt b/corpus/page-model/followup/native-text.txt new file mode 100644 index 0000000000000000000000000000000000000000..e11d360e254d6f6205718d67be5af1dfa476bc7e --- /dev/null +++ b/corpus/page-model/followup/native-text.txt @@ -0,0 +1 @@ +Native after Rust 🦋 é \ No newline at end of file diff --git a/corpus/page-model/followup/notebook/Open Notebook.onetoc2 b/corpus/page-model/followup/notebook/Open Notebook.onetoc2 new file mode 100644 index 0000000000000000000000000000000000000000..5814b0f6d1941721eba9f84289aa7d970c3f3e23 GIT binary patch literal 4800 zcmZ3e|KIuM`!b(-j|5(YE0x8k*3bLU5_!w1)hgFw_X_4i3~0dq?koZ6iC;aJUJ#%7 z_Qbjy(m;7+3{(Ce2taIBm;jW9iK7Xla6xK704&G>m0|(XAPfRP8lnQC=711H7)DlR zud0o@ZSB3`NTrJKguJEPP>HPkCnxNbzWXoD^;+`pLjFgXdTjI-&4v8P7@L|=vC$A1 z>LGCC%lEGvtHPEDKs~~d!!WghQH5nqwMgIH2>%wthR?>O#&(QAX_kbB25jO(JqSkK zKN~$`k>?d|+J+kpkR}An6wk4X@=-p7q&T>pAV}=N<1>+n9pNN^C%3-G!gK?e8)|c7K@UlQW$!WJpwWj1lC6yG&I1}$pDS~FTl_MmLZxrzz0>z!oUElKY$_) zP|*e!hAFZPGCO4$M6!YOJ|GRMO=d1Rp~GUJ?=!_>Tjz7B#6=)y%K&jPLnT8VLkU9$ zLn@HWWJqSvW5@@JqyptY9sp8608|ZjH50=(83q-QnIQdJ=G_C!GB6;=4@d?S2aE3t zikELpcihV`-9>TPp+t~4ws?6E`xaLmw4L^OUo*wfXPe2^rS)|uzp4TQ4`d_AC|G=4 zGS%wIT`um_w@SXieAD)mAUQ_^hTbcTEL=b~D=2PGGIGPh99P`bXfpf)#RpLLC>RZa P(Gb8H0?5T0to#80*j_}$ literal 0 HcmV?d00001 diff --git a/corpus/page-model/followup/notebook/synthetic.one b/corpus/page-model/followup/notebook/synthetic.one new file mode 100644 index 0000000000000000000000000000000000000000..866983b63f7a2c0a91045600e6e0090d2e38eff2 GIT binary patch literal 127664 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 b24*a`bS#+Il*`-etpwgm;J1)KSN;FLdd~7r literal 0 HcmV?d00001 diff --git a/corpus/page-model/followup/read/environment.json b/corpus/page-model/followup/read/environment.json new file mode 100644 index 0000000000000000000000000000000000000000..5cdb893b75c3763b7d1d48e57820340706abdfab --- /dev/null +++ b/corpus/page-model/followup/read/environment.json @@ -0,0 +1,7 @@ +{ + "powershell": "5.1.14409.1005", + "schema": "xs2010", + "hostname": "ONE-M6-A302D412", + "cold": false, + "onenote": "14.0.4763.1000" +} diff --git a/corpus/page-model/followup/read/hierarchy.xml b/corpus/page-model/followup/read/hierarchy.xml new file mode 100644 index 0000000000000000000000000000000000000000..b52a9683103c379e8d667177ed785422c7d0e480 --- /dev/null +++ b/corpus/page-model/followup/read/hierarchy.xml @@ -0,0 +1,2 @@ + + diff --git a/corpus/page-model/followup/read/page-000.xml b/corpus/page-model/followup/read/page-000.xml new file mode 100644 index 0000000000000000000000000000000000000000..363e762804622eacbb17f591a85b642b2be3fae8 --- /dev/null +++ b/corpus/page-model/followup/read/page-000.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-001.xml b/corpus/page-model/followup/read/page-001.xml new file mode 100644 index 0000000000000000000000000000000000000000..1a0b4451a204865b60ba37f0cc53eef945d242b1 --- /dev/null +++ b/corpus/page-model/followup/read/page-001.xml @@ -0,0 +1,25 @@ + +Bold 🦀 italic é color 東京
+End
Fictitious: café, 東京, مرحبا]]>
diff --git a/corpus/page-model/followup/read/page-002.xml b/corpus/page-model/followup/read/page-002.xml new file mode 100644 index 0000000000000000000000000000000000000000..9389a42efac96f459f0d93e910dd93b4ca4e139d --- /dev/null +++ b/corpus/page-model/followup/read/page-002.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-003.xml b/corpus/page-model/followup/read/page-003.xml new file mode 100644 index 0000000000000000000000000000000000000000..33b71f7005065483933c2b8f508f8dda46d00b23 --- /dev/null +++ b/corpus/page-model/followup/read/page-003.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-004.xml b/corpus/page-model/followup/read/page-004.xml new file mode 100644 index 0000000000000000000000000000000000000000..6f9775dd4525bad8801ea845aba404d9938222c5 --- /dev/null +++ b/corpus/page-model/followup/read/page-004.xml @@ -0,0 +1,4 @@ + +Target 🦀 é Link label]]> diff --git a/corpus/page-model/followup/read/page-005.xml b/corpus/page-model/followup/read/page-005.xml new file mode 100644 index 0000000000000000000000000000000000000000..021307b398a98489e03a78fd15e5e888dafc1395 --- /dev/null +++ b/corpus/page-model/followup/read/page-005.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-006.xml b/corpus/page-model/followup/read/page-006.xml new file mode 100644 index 0000000000000000000000000000000000000000..cf113ac78d4d6711887a19fa0ec8b4ec8c586cf0 --- /dev/null +++ b/corpus/page-model/followup/read/page-006.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-007.xml b/corpus/page-model/followup/read/page-007.xml new file mode 100644 index 0000000000000000000000000000000000000000..977329f812d5d008a352e23d4a18c39f30c0195a --- /dev/null +++ b/corpus/page-model/followup/read/page-007.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-008.xml b/corpus/page-model/followup/read/page-008.xml new file mode 100644 index 0000000000000000000000000000000000000000..ae9e2068507babfd6fa79e4d6f8b898e39b6fb75 --- /dev/null +++ b/corpus/page-model/followup/read/page-008.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-009.xml b/corpus/page-model/followup/read/page-009.xml new file mode 100644 index 0000000000000000000000000000000000000000..b6ba79ceac6a28f81ed5ae44fb8e35877847dcb6 --- /dev/null +++ b/corpus/page-model/followup/read/page-009.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-010.xml b/corpus/page-model/followup/read/page-010.xml new file mode 100644 index 0000000000000000000000000000000000000000..dc3dcfb57e76efc3dedf75b7db0b986d374ea962 --- /dev/null +++ b/corpus/page-model/followup/read/page-010.xml @@ -0,0 +1,8 @@ + +Anchor]]>Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-011.xml b/corpus/page-model/followup/read/page-011.xml new file mode 100644 index 0000000000000000000000000000000000000000..95ef98b2d062ea6bf46fee0e90319458de3eaf3d --- /dev/null +++ b/corpus/page-model/followup/read/page-011.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-012.xml b/corpus/page-model/followup/read/page-012.xml new file mode 100644 index 0000000000000000000000000000000000000000..453ad11a0f0ddb88ed9b013a8cfe84558c1f3b37 --- /dev/null +++ b/corpus/page-model/followup/read/page-012.xml @@ -0,0 +1,6 @@ + +Anchor]]>Target 🦀 é Link label]]>Child]]> diff --git a/corpus/page-model/followup/read/page-013.xml b/corpus/page-model/followup/read/page-013.xml new file mode 100644 index 0000000000000000000000000000000000000000..c2c4b785287053dd76899a6263395a27f08e7634 --- /dev/null +++ b/corpus/page-model/followup/read/page-013.xml @@ -0,0 +1,4 @@ + +Target 🦀 é Link label]]> diff --git a/corpus/page-model/followup/read/page-014.xml b/corpus/page-model/followup/read/page-014.xml new file mode 100644 index 0000000000000000000000000000000000000000..8f855d392b08bddf15a2edadde9ef00211dacde8 --- /dev/null +++ b/corpus/page-model/followup/read/page-014.xml @@ -0,0 +1,5 @@ + +Target 🦀 é Link label]]>Trailing sibling]]> diff --git a/corpus/page-model/followup/read/payloads.json b/corpus/page-model/followup/read/payloads.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843 --- /dev/null +++ b/corpus/page-model/followup/read/payloads.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/corpus/page-model/followup/run.json b/corpus/page-model/followup/run.json new file mode 100644 index 0000000000000000000000000000000000000000..2c2228dcca8537c4d58958caac70e53c1bd67949 --- /dev/null +++ b/corpus/page-model/followup/run.json @@ -0,0 +1,19 @@ +{ + "notebook": "/private/tmp/page-model/cold/notebook", + "expected_pages": 15, + "author": "tools/native/page-model-followup.ps1", + "author_timeout_seconds": 600, + "inspect": false, + "collect_notebook": true, + "base": { + "file": "win7-office-base.qcow2", + "format": "qcow2", + "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346", + "virtual_size": 68719476736 + }, + "scripts": { + "author.ps1": "60d2c5b969cafc4e6f066aec2be18323779ea8dceb9bd72473094332895d1219", + "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331", + "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41" + } +} diff --git a/corpus/page-model/followup/scripts/author.ps1 b/corpus/page-model/followup/scripts/author.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..d688498ef5ab9a3085e693a3a107ada481501e1d --- /dev/null +++ b/corpus/page-model/followup/scripts/author.ps1 @@ -0,0 +1,43 @@ +param([Parameter(Mandatory=$true)][string]$Root, [Parameter(Mandatory=$true)][string]$CloneHost) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +& "$PSScriptRoot\cold-current.ps1" -Root $Root -CloneHost $CloneHost +$app = New-Object -ComObject OneNote.Application +$notebook = '' +try { + $app.OpenHierarchy((Join-Path $Root 'notebook'), '', [ref]$notebook, 0) + $section = '' + $app.OpenHierarchy('synthetic.one', $notebook, [ref]$section, 0) + $deadline = [DateTime]::UtcNow.AddSeconds(60) + $matches = @() + $content = '' + do { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$tree = $hierarchy + $pages = @($tree.SelectNodes('//*[local-name()="Page"]') | Where-Object { $_.GetAttribute('name') -eq 'Move leaf down' }) + if ($pages.Count -eq 1) { + $app.GetPageContent($pages[0].GetAttribute('ID'), [ref]$content, 3, 1) + [xml]$page = $content + $matches = @($page.SelectNodes('//*[local-name()="T"]') | Where-Object { $_.InnerText -like '*>Rust *' -or $_.InnerText -like 'Rust *' }) + if ($matches.Count -eq 1) { break } + } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if ($matches.Count -ne 1) { throw 'Expected exactly one Rust-written paragraph on the Move leaf down page.' } + [IO.File]::WriteAllText("$Root\before.xml", $content, [Text.Encoding]::UTF8) + $text = 'Native after Rust ' + [char]::ConvertFromUtf32(0x1F98B) + ' e' + [char]0x0301 + $matches[0].InnerText = [Security.SecurityElement]::Escape($text) + $app.UpdatePageContent($page.OuterXml, [DateTime]::MinValue, 1, $false) + $app.SyncHierarchy($notebook) + [IO.File]::WriteAllText("$Root\native-text.txt", $text, [Text.Encoding]::UTF8) +} finally { + try { if ($notebook) { $app.CloseNotebook($notebook, $false) } } + finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 120 -ErrorAction SilentlyContinue + } +} diff --git a/corpus/page-model/followup/scripts/cold.ps1 b/corpus/page-model/followup/scripts/cold.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f --- /dev/null +++ b/corpus/page-model/followup/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/page-model/followup/scripts/read.ps1 b/corpus/page-model/followup/scripts/read.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b --- /dev/null +++ b/corpus/page-model/followup/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/page-model/followup/source.json b/corpus/page-model/followup/source.json new file mode 100644 index 0000000000000000000000000000000000000000..a1a9c059da619a4e9242f685bfc44eeec98f76ca --- /dev/null +++ b/corpus/page-model/followup/source.json @@ -0,0 +1,14 @@ +[ + { + "path": "Open Notebook.onetoc2", + "bytes": 4800, + "sha256": "341894b32b0433a1e8b647431f71e372d344c74e0f87699e45c9235964082551", + "mtime_ns": 1789108125813547146 + }, + { + "path": "synthetic.one", + "bytes": 123872, + "sha256": "cb246a4fb88a30dd1dad710ebde9b209a150175fd5dfd3d4e3e36d5d4a505cff", + "mtime_ns": 1789108125813805311 + } +] diff --git a/corpus/page-model/followup/teardown.json b/corpus/page-model/followup/teardown.json new file mode 100644 index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70 --- /dev/null +++ b/corpus/page-model/followup/teardown.json @@ -0,0 +1 @@ +{"absent": true} diff --git a/corpus/page-model/provenance.json b/corpus/page-model/provenance.json new file mode 100644 index 0000000000000000000000000000000000000000..fa132445ac30879709c9395ed5903154e20b2951 --- /dev/null +++ b/corpus/page-model/provenance.json @@ -0,0 +1,37 @@ +{ + "source": { + "path": "corpus/outline-edit/before/notebook/synthetic.one", + "sha256": "924389ae0f4e9fc583fb6de17c0859257994847cbf674bc75b821b3513ca18e2" + }, + "candidate": { + "sha256": "a5ca37027575ea012fce7fd4131ffb7c184b65bc32836a3f33556ee5162cdbc3", + "generator": "cargo test -p onestore --test page_writer export_native_page_model_candidates -- --ignored", + "cases": 8 + }, + "captures": { + "cold": { + "clone": "m6-a298124b", + "teardown_absent": true, + "notebook_sha256": "cb246a4fb88a30dd1dad710ebde9b209a150175fd5dfd3d4e3e36d5d4a505cff", + "pages": 15 + }, + "followup": { + "clone": "m6-a302d412", + "teardown_absent": true, + "notebook_sha256": "d3f67a59581e9314cc476ea6f9cdef12bfcbce131335da591c68ae35886cace2", + "pages": 15 + }, + "followup-cold": { + "clone": "m6-3caf6d8e", + "teardown_absent": true, + "notebook_sha256": "d3f67a59581e9314cc476ea6f9cdef12bfcbce131335da591c68ae35886cace2", + "pages": 15 + } + }, + "author_script": "tools/native/page-model-followup.ps1", + "rejected_attempts": [ + "m6-7b68c992: author script matched no paragraph because native CDATA wraps text in ; matcher widened", + "m6-4c165dd4: native edit saved, script failed waiting 10 s for OneNote to exit; wait made tolerant" + ], + "verifier": "PYTHONPATH=tools python3 -m unittest test_page_model" +} diff --git a/crates/onestore/tests/page_writer.rs b/crates/onestore/tests/page_writer.rs index 73db735cbf78605dba8e8fa75756200f4eaad8fa..69b3e6252676e604e7c7fcd935145b172f77ad7e 100644 --- a/crates/onestore/tests/page_writer.rs +++ b/crates/onestore/tests/page_writer.rs @@ -627,3 +627,361 @@ fn an_unchanged_model_publishes_nothing() { let prepared = PreparedEdit::page(OUTLINES, space, &page, AUTHOR).unwrap(); assert_eq!(prepared.as_bytes(), OUTLINES); } + +const JOIN_PAGE: &str = "Bold 🦀 italic e\u{301} color 東京"; + +fn native_candidate_edits() -> Vec<(&'static str, &'static str)> { + vec![ + ( + "Move leaf down", + "Anchor moved last and replaced with Unicode text, bold range on Trailing sibling", + ), + ( + "Move subtree down", + "Target subtree moved last with a new nested child, italic blue 14 pt range on Anchor", + ), + ( + "Delete leaf", + "Anchor deleted, paragraph appended, new outline with two paragraphs at (300, 400)", + ), + ("Delete subtree", "Anchor split in the middle"), + ( + "Collapse subtree", + "Target collapsed, outline moved to (90, 250.5) with a fixed 300 pt width", + ), + ( + "Move outline", + "first body outline moved after the second, first paragraph of each extended", + ), + ( + "Delete outline", + "second body outline deleted, underline, highlight and Consolas on a range of Anchor", + ), + ( + JOIN_PAGE, + "the two paragraphs joined, strike and subscript on the first three units", + ), + ] +} + +fn fresh(template: &onestore::page::PageParagraph, text: &str) -> onestore::page::PageParagraph { + let mut paragraph = template.clone(); + paragraph.id = new_id().unwrap(); + paragraph.parent = None; + paragraph.level = 1; + paragraph.lists.clear(); + paragraph.tags.clear(); + paragraph.style = None; + paragraph.collapsed = false; + let format = template.text().unwrap().text.format_at(0).unwrap().clone(); + paragraph.content = ParagraphContent::Text(onestore::page::TextObject { + id: new_id().unwrap(), + date_field: None, + text: onestore::page::Paragraph::new(text.into(), format), + tags: Vec::new(), + }); + paragraph +} + +fn restyle( + text: &mut onestore::page::TextObject, + range: std::ops::Range, + change: impl Fn(&mut onestore::document::Format), +) { + let slice = text.text.slice(range.clone()).unwrap(); + let mut runs = Vec::new(); + let mut from = 0; + for span in slice.spans() { + let mut format = span.format.clone(); + change(&mut format); + runs.push((slice.text()[from..span.end].to_owned(), format)); + from = span.end; + } + text.text + .apply(onestore::page::text::Edit { + range, + replacement: onestore::page::Paragraph::from_runs(runs), + }) + .unwrap(); +} + +fn set_text(text: &mut onestore::page::TextObject, replacement: &str) { + let end = text.text.utf16_offset(text.text.text().len()).unwrap(); + let format = text.text.format_at(0).unwrap().clone(); + text.text + .apply(onestore::page::text::Edit { + range: 0..end, + replacement: onestore::page::Paragraph::new(replacement.into(), format), + }) + .unwrap(); +} + +/// Removes a top-level subtree and returns it in order. +fn take_subtree( + outline: &mut onestore::page::Outline, + index: usize, +) -> Vec { + let mut ids = BTreeSet::from([outline.paragraphs[index].id]); + loop { + let before = ids.len(); + let more: Vec = outline + .paragraphs + .iter() + .filter(|p| p.parent.is_some_and(|q| ids.contains(&q))) + .map(|p| p.id) + .collect(); + ids.extend(more); + if ids.len() == before { + break; + } + } + let (subtree, rest): (Vec<_>, Vec<_>) = outline + .paragraphs + .drain(..) + .partition(|p| ids.contains(&p.id)); + outline.paragraphs = rest; + subtree +} + +fn expectation(page: &Page) -> serde_json::Value { + let outlines: Vec = body(page) + .iter() + .map(|outline| { + let index: std::collections::BTreeMap = + outline.paragraphs.iter().enumerate().map(|(i, p)| (p.id, i)).collect(); + serde_json::json!({ + "x": outline.layout.x, + "y": outline.layout.y, + "max_width": outline.layout.max_width, + "width_set_by_user": outline.layout.width_set_by_user, + "paragraphs": outline.paragraphs.iter().map(|p| serde_json::json!({ + "text": p.text().map(|t| t.text.text()), + "parent": p.parent.map(|q| index[&q]), + "collapsed": p.collapsed, + "spans": p.text().map(|t| t.text.spans().iter().map(|s| serde_json::json!({ + "end": t.text.utf16_offset(s.end).unwrap(), + "bold": s.format.bold, "italic": s.format.italic, "underline": s.format.underline, + "strike": s.format.strike, "subscript": s.format.subscript, + "font": s.format.font, "font_size": s.format.font_size, + "color": s.format.color, "highlight": s.format.highlight, + })).collect::>()), + })).collect::>(), + }) + }) + .collect(); + serde_json::json!({ "title": page.title, "outlines": outlines }) +} + +#[test] +#[ignore = "exports a page-model candidate notebook for cold native validation"] +fn export_native_page_model_candidates() { + let output = std::path::PathBuf::from(std::env::var_os("ONESTORE_PAGE_MODEL_OUTPUT").unwrap()); + assert!(output.is_absolute()); + std::fs::create_dir_all(output.join("candidate/notebook")).unwrap(); + let mut bytes = OUTLINES.to_vec(); + let mut cases = Vec::new(); + for (title, description) in native_candidate_edits() { + let (space, _) = page_by_title(&bytes, title); + let mut after = page_in(&bytes, space); + let outlines: Vec = after + .objects + .iter() + .enumerate() + .filter(|(_, o)| matches!(o, PageObject::Outline(_))) + .map(|(i, _)| i) + .collect(); + fn body_outline(page: &mut Page, i: usize) -> &mut onestore::page::Outline { + match &mut page.objects[i] { + PageObject::Outline(outline) => outline, + _ => unreachable!(), + } + } + match title { + "Move leaf down" => { + let outline = body_outline(&mut after, outlines[0]); + let subtree = take_subtree(outline, 0); + outline.paragraphs.extend(subtree); + let last = outline.paragraphs.len() - 1; + set_text( + outline.paragraphs[last].text_mut().unwrap(), + "Rust 🦀 é 東京 שלום", + ); + let trailing = outline + .paragraphs + .iter() + .position(|p| { + p.text() + .is_some_and(|t| t.text.text() == "Trailing sibling") + }) + .unwrap(); + restyle( + outline.paragraphs[trailing].text_mut().unwrap(), + 0..4, + |f| f.bold = Some(true), + ); + } + "Move subtree down" => { + let outline = body_outline(&mut after, outlines[0]); + let parent_index = outline + .paragraphs + .iter() + .position(|p| outline.paragraphs.iter().any(|q| q.parent == Some(p.id))) + .unwrap(); + let parent_id = outline.paragraphs[parent_index].id; + let subtree = take_subtree(outline, parent_index); + outline.paragraphs.extend(subtree); + let mut child = fresh(&outline.paragraphs[0], "Nested by Rust"); + child.parent = Some(parent_id); + child.level = 2; + outline.paragraphs.push(child); + restyle(outline.paragraphs[0].text_mut().unwrap(), 0..6, |f| { + f.italic = Some(true); + f.color = Some(0xff0000); + f.font_size = Some(14.0); + }); + } + "Delete leaf" => { + let template = body(&after)[0].paragraphs[0].clone(); + let outline = body_outline(&mut after, outlines[0]); + take_subtree(outline, 0); + outline + .paragraphs + .push(fresh(&template, "Appended by Rust")); + let new_outline = onestore::page::Outline { + id: new_id().unwrap(), + title: false, + min_width: None, + layout: onestore::document::Layout { + x: Some(300.0), + y: Some(400.0), + ..Default::default() + }, + indents: Vec::new(), + paragraphs: vec![ + fresh(&template, "Rust outline one"), + fresh(&template, "Rust outline two"), + ], + unsupported: Vec::new(), + }; + let at = after + .objects + .iter() + .position(|o| matches!(o, PageObject::Title(_))) + .unwrap_or(after.objects.len()); + after.objects.insert(at, PageObject::Outline(new_outline)); + } + "Delete subtree" => { + let outline = body_outline(&mut after, outlines[0]); + let first = outline.paragraphs[0].clone(); + let text = first.text().unwrap(); + let end = text.text.utf16_offset(text.text.text().len()).unwrap(); + let offset = (end / 2..end) + .find(|at| text.text.byte_offset(*at).is_ok()) + .unwrap(); + let tail = text.text.slice(offset..end).unwrap(); + let mut right = fresh(&first, ""); + right.style = first.style; + right.text_mut().unwrap().text = tail; + let left = outline.paragraphs[0].text_mut().unwrap(); + left.text = left.text.slice(0..offset).unwrap(); + outline.paragraphs.insert(1, right); + } + "Collapse subtree" => { + let outline = body_outline(&mut after, outlines[0]); + let parent = outline + .paragraphs + .iter() + .position(|p| outline.paragraphs.iter().any(|q| q.parent == Some(p.id))) + .unwrap(); + outline.paragraphs[parent].collapsed = true; + outline.layout.x = Some(90.0); + outline.layout.y = Some(250.5); + outline.layout.max_width = Some(300.0); + outline.layout.width_set_by_user = Some(true); + } + "Move outline" => { + assert!(outlines.len() >= 2); + let first = after.objects.remove(outlines[0]); + after.objects.insert(outlines[1], first); + for i in [outlines[0], outlines[1]] { + let outline = body_outline(&mut after, i); + let text = outline.paragraphs[0].text_mut().unwrap(); + let end = text.text.utf16_offset(text.text.text().len()).unwrap(); + let format = text.text.format_at(end).unwrap().clone(); + text.text + .apply(onestore::page::text::Edit { + range: end..end, + replacement: onestore::page::Paragraph::new(" (Rust)".into(), format), + }) + .unwrap(); + } + } + "Delete outline" => { + assert!(outlines.len() >= 2); + after.objects.remove(outlines[1]); + let outline = body_outline(&mut after, outlines[0]); + restyle(outline.paragraphs[0].text_mut().unwrap(), 1..5, |f| { + f.underline = Some(true); + f.highlight = Some(0x00ffff); + f.font = Some("Consolas".into()); + }); + } + _ => { + let outline = body_outline(&mut after, outlines[0]); + assert_eq!(outline.paragraphs.len(), 2); + let right = outline.paragraphs.remove(1); + outline.paragraphs[0] + .text_mut() + .unwrap() + .text + .append(right.text().unwrap().text.clone()) + .unwrap(); + restyle(outline.paragraphs[0].text_mut().unwrap(), 0..3, |f| { + f.strike = Some(true); + f.subscript = Some(true); + }); + } + } + let edit = PreparedEdit::page(&bytes, space, &after, "Rust page writer").unwrap(); + bytes = edit.as_bytes().to_vec(); + let stored = page_in(&bytes, space); + let index = { + let store = Store::parse(&bytes).unwrap(); + let index = RevisionIndex::parse(&store).unwrap(); + let document = Document::parse(&index).unwrap(); + document + .pages() + .unwrap() + .iter() + .position(|(sid, _)| *sid == space) + .unwrap() + }; + cases.push(serde_json::json!({ + "title": title, + "index": index, + "description": description, + "space": space.to_string(), + "expected": expectation(&stored), + })); + } + std::fs::write(output.join("candidate/notebook/synthetic.one"), &bytes).unwrap(); + std::fs::copy( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../corpus/outline-edit/before/notebook/Open Notebook.onetoc2" + ), + output.join("candidate/notebook/Open Notebook.onetoc2"), + ) + .unwrap(); + std::fs::write( + output.join("candidate/manifest.json"), + serde_json::to_string_pretty(&serde_json::json!({ + "source": "corpus/outline-edit/before/notebook/synthetic.one", + "author": "Rust page writer", + "transactions_added": cases.len(), + "cases": cases, + })) + .unwrap(), + ) + .unwrap(); +} diff --git a/tools/native/page-model-followup.ps1 b/tools/native/page-model-followup.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..d688498ef5ab9a3085e693a3a107ada481501e1d --- /dev/null +++ b/tools/native/page-model-followup.ps1 @@ -0,0 +1,43 @@ +param([Parameter(Mandatory=$true)][string]$Root, [Parameter(Mandatory=$true)][string]$CloneHost) +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +& "$PSScriptRoot\cold-current.ps1" -Root $Root -CloneHost $CloneHost +$app = New-Object -ComObject OneNote.Application +$notebook = '' +try { + $app.OpenHierarchy((Join-Path $Root 'notebook'), '', [ref]$notebook, 0) + $section = '' + $app.OpenHierarchy('synthetic.one', $notebook, [ref]$section, 0) + $deadline = [DateTime]::UtcNow.AddSeconds(60) + $matches = @() + $content = '' + do { + $hierarchy = '' + $app.GetHierarchy($section, 4, [ref]$hierarchy, 1) + [xml]$tree = $hierarchy + $pages = @($tree.SelectNodes('//*[local-name()="Page"]') | Where-Object { $_.GetAttribute('name') -eq 'Move leaf down' }) + if ($pages.Count -eq 1) { + $app.GetPageContent($pages[0].GetAttribute('ID'), [ref]$content, 3, 1) + [xml]$page = $content + $matches = @($page.SelectNodes('//*[local-name()="T"]') | Where-Object { $_.InnerText -like '*>Rust *' -or $_.InnerText -like 'Rust *' }) + if ($matches.Count -eq 1) { break } + } + Start-Sleep -Milliseconds 250 + } while ([DateTime]::UtcNow -lt $deadline) + if ($matches.Count -ne 1) { throw 'Expected exactly one Rust-written paragraph on the Move leaf down page.' } + [IO.File]::WriteAllText("$Root\before.xml", $content, [Text.Encoding]::UTF8) + $text = 'Native after Rust ' + [char]::ConvertFromUtf32(0x1F98B) + ' e' + [char]0x0301 + $matches[0].InnerText = [Security.SecurityElement]::Escape($text) + $app.UpdatePageContent($page.OuterXml, [DateTime]::MinValue, 1, $false) + $app.SyncHierarchy($notebook) + [IO.File]::WriteAllText("$Root\native-text.txt", $text, [Text.Encoding]::UTF8) +} finally { + try { if ($notebook) { $app.CloseNotebook($notebook, $false) } } + finally { + [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app) + $app = $null + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 120 -ErrorAction SilentlyContinue + } +} diff --git a/tools/test_page_model.py b/tools/test_page_model.py new file mode 100644 index 0000000000000000000000000000000000000000..717c335ac3ce0c8d4f6474f00c13b69196b30ab6 --- /dev/null +++ b/tools/test_page_model.py @@ -0,0 +1,133 @@ +"""Rust page-model edits survive a cold native reopen and a native edit on top of them.""" +import json +from pathlib import Path +import runpy +import subprocess +from tempfile import TemporaryDirectory +import unittest + +from document_model import EXPORTER, ordered_pages, walk + +ROOT = Path(__file__).resolve().parent.parent +FIXTURE = ROOT / 'corpus/page-model' +compare = runpy.run_path(str(ROOT / 'tools/verify-document.py'))['compare'] + + +def projection(space, page_root): + """Outlines with their positions and pre-order paragraphs (text, parent index, collapsed).""" + page = space['nodes'][page_root] + outlines = [] + for oid in page['children']: + node = space['nodes'][oid] + if node['kind']['type'] != 'Outline': + continue + paragraphs = [] + index = {} + pending = [(child, None) for child in reversed(node['children'])] + while pending: + pid, parent = pending.pop() + paragraph = space['nodes'][pid] + if paragraph['kind']['type'] == 'OutlineGroup': + pending.extend((child, parent) for child in reversed(paragraph['children'])) + continue + assert paragraph['kind']['type'] == 'Paragraph', paragraph['kind']['type'] + text = None + for cid in paragraph['content']: + content = space['nodes'][cid] + if content['kind']['type'] == 'RichText': + text = content['kind']['text'] + index[pid] = len(paragraphs) + paragraphs.append({'text': text, 'parent': index.get(parent), 'collapsed': paragraph['kind'].get('collapse_state') == 1}) + pending.extend((child, pid) for child in reversed(paragraph['children'])) + layout = node['layout'] + outlines.append({'x': points(layout['x']), 'y': points(layout['y']), 'max_width': points(layout['max_width']), + 'width_set_by_user': layout.get('width_set_by_user'), 'paragraphs': paragraphs}) + return outlines + + +def points(value): + """Single-precision points survive JSON with different digits in Rust and Python.""" + return None if value is None else round(value, 3) + + +def expected_projection(case): + return [{'x': points(o['x']), 'y': points(o['y']), 'max_width': points(o['max_width']), 'width_set_by_user': o['width_set_by_user'], + 'paragraphs': [{'text': p['text'], 'parent': p['parent'], 'collapsed': p['collapsed']} for p in o['paragraphs']]} + for o in case['expected']['outlines']] + + +def model(notebook): + with TemporaryDirectory() as temporary: + subprocess.run([EXPORTER, notebook / 'synthetic.one', Path(temporary) / 'model'], check=True) + return json.loads((Path(temporary) / 'model/document.json').read_text()) + + +class PageModelTest(unittest.TestCase): + def setUp(self): + self.manifest = json.loads((FIXTURE / 'candidate/manifest.json').read_text()) + self.assertEqual(len(self.manifest['cases']), 8) + + def check_cases(self, notebook, exceptions=()): + pages = list(ordered_pages(model(notebook))) + self.assertEqual(len(pages), 15) + for case in self.manifest['cases']: + with self.subTest(case=case['title']): + _, _, space, root = pages[case['index']] + actual = projection(space, root) + expected = expected_projection(case) + for index, replacement in exceptions: + if index == case['index']: + expected = replacement(expected) + self.assertEqual(actual, expected) + + def assert_only_navigation_cache_changed(self, candidate, cold): + """OneNote adds per-series metadata copies on open (as it does for the untouched + outline-edit fixture); every page space must keep its exact active revision.""" + context = '{00000000-0000-0000-0000-000000000000},0' + self.assertEqual(set(candidate['spaces']), set(cold['spaces'])) + for sid, space in candidate['spaces'].items(): + if sid == candidate['root']: + continue + self.assertEqual(space['contexts'][context], cold['spaces'][sid]['contexts'][context], sid) + before = candidate['spaces'][candidate['root']] + after = cold['spaces'][cold['root']] + before = before['revisions'][before['contexts'][context]]['nodes'] + after = after['revisions'][after['contexts'][context]]['nodes'] + self.assertTrue(set(before) <= set(after)) + for oid, node in before.items(): + other = after[oid] + if node['kind']['type'] == 'Metadata': + continue + if node['kind']['type'] == 'PageSeries': + strip = lambda n: {k: v for k, v in n.items() if k != 'extra'} + self.assertEqual(strip(node), strip(other), oid) + continue + self.assertEqual(node, other, oid) + for oid in set(after) - set(before): + self.assertEqual(after[oid]['kind']['type'], 'Metadata', oid) + + def test_rust_page_model_edits_survive_cold_native_reopen(self): + compare(FIXTURE / 'candidate/notebook', FIXTURE / 'cold/read') + compare(FIXTURE / 'cold/notebook', FIXTURE / 'cold/read') + self.assert_only_navigation_cache_changed(model(FIXTURE / 'candidate/notebook'), model(FIXTURE / 'cold/notebook')) + self.check_cases(FIXTURE / 'candidate/notebook') + self.check_cases(FIXTURE / 'cold/notebook') + + def test_native_edit_after_rust_page_model_edits(self): + compare(FIXTURE / 'followup-cold/notebook', FIXTURE / 'followup-cold/read') + native = (FIXTURE / 'followup/native-text.txt').read_text(encoding='utf-8-sig') + self.assertTrue(native.startswith('Native after Rust')) + moved = next(case for case in self.manifest['cases'] if case['title'] == 'Move leaf down') + + def replace_rust_text(outlines): + outlines = json.loads(json.dumps(outlines)) + hits = [p for o in outlines for p in o['paragraphs'] if p['text'].startswith('Rust ')] + assert len(hits) == 1 + hits[0]['text'] = native + return outlines + + self.check_cases(FIXTURE / 'followup-cold/notebook', exceptions=[(moved['index'], replace_rust_text)]) + + +if __name__ == '__main__': + unittest.main() -- 2.54.0