authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-09-13 01:35:55-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-09-25 20:26:20-07:00
log94b162d4813c318a27b96cc9f1923bd80c21c1d6
tree99056cb9a0b9ca3d42b80f18a50740a5c699dbd5
parent3d72c72fcc4bf5ea8b86377b6117843fea073b61
signature Signed by SSH key SHA256:52mNGHRsVFBDED9IAX5pe+LRWUefqTbxEReunq21QvU

feat: notebook structure over SMB, nested-table page copies, run language

`Notebook` now runs over a `Storage` trait: a mounted directory or an SMB share (`Notebook::open_smb`), so sections and groups are created, renamed, coloured, ordered and deleted on the share too. The native-compatible SMB client gained file creation, directory creation, rename (`FileRenameInformation`), delete-on-close and header placement (`onestore::place` on any `CommitIo`); `smb::tests::live_structure` runs against the Samba lab VM through `tools/test_smb_structure.py`. Page copies cover nested tables and paragraph subtrees inside new cells: the place pass builds tables round by round as their holders appear, and a run's language id is a text attribute the formatting writer sets. Pages whose indent levels only an outline group can carry refuse to copy, since the model holds no outline groups. `corpus/page-copy` grows to seventeen copied pages. Assisted-by: claude-fable-5.1

77 files changed, 865 insertions(+), 191 deletions(-)

corpus/page-copy/README.md+4-1
......@@ -6,7 +6,10 @@
66`Section::import_page` copied one page from each of eight earlier rows (text
77with an attachment and its icon, a table, an inserted picture, a page-level
88ink drawing, note tags, bullets and numbering, equations, paragraph
9formatting), each as a page creation and a save queued through the replica
9formatting) and the `table-edit/nested` pages whose indent levels the model
10can express (nested tables, cell subtrees, mixed languages; four outdent
11pages need outline groups and refuse), each as a page creation and a save
12queued through the replica
1013and published to the file; the last copy (paragraph formatting) was then deleted permanently
1114through `Section::delete_pages` (`expected-count.txt` is the page count
1215left). Every object carries a fresh identity (`Page::copy`), paragraph
corpus/page-copy/candidate/Open Notebook.onetoc2
Binary files a/corpus/page-copy/candidate/Open Notebook.onetoc2 and b/corpus/page-copy/candidate/Open Notebook.onetoc2 differ
corpus/page-copy/candidate/copies.one
Binary files a/corpus/page-copy/candidate/copies.one and b/corpus/page-copy/candidate/copies.one differ
corpus/page-copy/candidate/expected-count.txt+1-1
......@@ -1 +1 @@
19
\ No newline at end of file
117
\ No newline at end of file
corpus/page-copy/cold/commands.jsonl+1-1
......@@ -1,3 +1,3 @@
11{"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}
2{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-1C0F2CDE -ExpectedPages 9 -KeepOpen", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
2{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-33218F72 -ExpectedPages 17 -KeepOpen", "exit": 0, "stdout": "Read 1 sections and 17 pages.\r\n", "stderr": "", "error": null}
33{"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}
corpus/page-copy/cold/machine.json+1-1
......@@ -1 +1 @@
1{"name": "m6-1c0f2cde", "hostname": "ONE-M6-1C0F2CDE"}
1{"name": "m6-33218f72", "hostname": "ONE-M6-33218F72"}
corpus/page-copy/cold/notebook/Open Notebook.onetoc2
Binary files a/corpus/page-copy/cold/notebook/Open Notebook.onetoc2 and b/corpus/page-copy/cold/notebook/Open Notebook.onetoc2 differ
corpus/page-copy/cold/notebook/copies.one
Binary files a/corpus/page-copy/cold/notebook/copies.one and b/corpus/page-copy/cold/notebook/copies.one differ
corpus/page-copy/cold/notebook/expected-count.txt+1-1
......@@ -1 +1 @@
19
\ No newline at end of file
117
\ No newline at end of file
corpus/page-copy/cold/read/environment.json+1-1
......@@ -1,7 +1,7 @@
11{
22 "powershell": "5.1.14409.1005",
33 "schema": "xs2010",
4 "hostname": "ONE-M6-1C0F2CDE",
4 "hostname": "ONE-M6-33218F72",
55 "cold": true,
66 "onenote": "14.0.4763.1000"
77}
corpus/page-copy/cold/read/hierarchy.xml+1-1
......@@ -1,2 +1,2 @@
11<?xml version="1.0"?>
2<one:Notebook xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" name="notebook" nickname="notebook" ID="{CA49439A-5FEF-43A6-AB60-E8C051A59087}{1}{B0}" path="C:\one-tests\runs\capture\notebook" lastModifiedTime="2026-09-13T07:34:46.000Z" color="#B49EDE"><one:Section name="copies" ID="{6D7B6C59-2E45-0D8F-286E-4FD72999E63A}{1}{B0}" path="C:\one-tests\runs\capture\notebook\copies.one" lastModifiedTime="2026-09-13T07:34:46.000Z" color="#8AA8E4"><one:Page ID="{8BB0D046-3BC7-0CE9-33B2-04F7D5E9C6FD}{1}{B0}" name="Destination" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:35.000Z" pageLevel="1"/><one:Page ID="{C12C0ECF-DDF8-0A21-11BE-3074429542E0}{1}{B0}" name="Before the file" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:35.000Z" pageLevel="1"/><one:Page ID="{91EAB23E-CBE0-0D18-1A25-23B9CBC39112}{1}{B0}" name="Before the table" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:35.000Z" pageLevel="1"/><one:Page ID="{B5A45771-4A39-05F8-1953-4F2F9B2B33A5}{1}{B0}" name="Before the picture" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1"/><one:Page ID="{B28A26BE-5DF2-0214-1827-B1747FE95ECC}{1}{B0}" name="Beside the drawing" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1"/><one:Page ID="{5C003E48-8717-05C2-096E-6762316BC0A0}{1}{B0}" name="Open task" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1"/><one:Page ID="{C5E005CB-753E-07E2-0C53-CD40FBB64A63}{1}{B0}" name="Bullet item" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1"/><one:Page ID="{5A5E0FDA-1644-0F00-0C45-8D72178B2031}{1}{B0}" name="Equations below" dateTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1"/><one:Page ID="{D4C06049-3C91-0190-0C2E-1BB1EBA49EBA}{1}{B0}" name="A notebook created in Rust." dateTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1"/></one:Section></one:Notebook>
2<one:Notebook xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" name="notebook" nickname="notebook" ID="{3D7C62EC-5CB3-485B-BB1F-23FA56C52E8D}{1}{B0}" path="C:\one-tests\runs\capture\notebook" lastModifiedTime="2026-09-13T08:14:37.000Z" color="#B49EDE"><one:Section name="copies" ID="{8631621B-321A-0F71-03FE-3BCA53E86583}{1}{B0}" path="C:\one-tests\runs\capture\notebook\copies.one" lastModifiedTime="2026-09-13T08:14:37.000Z" color="#8AA8E4"><one:Page ID="{0A5A2909-7069-0DA0-2457-FE8F9CA25885}{1}{B0}" name="Destination" dateTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:14:26.000Z" pageLevel="1"/><one:Page ID="{62E12C49-D5FE-0850-17D5-B4DC95B736E9}{1}{B0}" name="Before the file" dateTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:14:26.000Z" pageLevel="1"/><one:Page ID="{FBBA4589-4114-0DBB-1DDE-9AEBE04435E8}{1}{B0}" name="Before the table" dateTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:14:26.000Z" pageLevel="1"/><one:Page ID="{5E04C302-1E83-0CCD-1715-B0A2566E0191}{1}{B0}" name="Bold 🦀 italic é color 東京" dateTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:14:26.000Z" pageLevel="1"/><one:Page ID="{55B596AA-4540-085D-142D-9F788431ACE5}{1}{B0}" name="Indent first subtree" dateTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{BA810F75-DBC0-0827-0990-F9FBFC84B7D7}{1}{B0}" name="Delete cell subtree" dateTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{493E9D0C-5976-0886-2ADB-636A30B81D20}{1}{B0}" name="Delete sole cell paragraph" dateTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{79EFBB50-C028-09DE-005B-75E21D0ED54C}{1}{B0}" name="Move numbered subtree down" dateTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{6EC9E652-85BD-0524-17E7-232F5951B731}{1}{B0}" name="Delete numbered subtree" dateTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{25E90FFA-6C7E-0A8D-3F8B-FC658F7AAF3B}{1}{B0}" name="Indent bullet subtree" dateTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{AA29BE5C-9249-0610-1036-E2735CEC0BB9}{1}{B0}" name="Move cell subtree down" dateTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{1E9DFA9B-2BEB-0C4E-3FEA-12F1C294A76E}{1}{B0}" name="Before the picture" dateTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{D28E7576-C55F-0047-2C51-4C855C536D13}{1}{B0}" name="Beside the drawing" dateTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{8E5634C2-26CB-0458-2810-125D129037C8}{1}{B0}" name="Open task" dateTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{35E45165-B253-07BF-1324-6FC7DCE3552B}{1}{B0}" name="Bullet item" dateTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{78595C91-C5E1-0D03-3A98-A98CA31DE5A8}{1}{B0}" name="Equations below" dateTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/><one:Page ID="{EF547C09-87EA-0A35-039B-F5512549E931}{1}{B0}" name="A notebook created in Rust." dateTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1"/></one:Section></one:Notebook>
corpus/page-copy/cold/read/page-000.navigation.json+1-1
......@@ -6,7 +6,7 @@
66 "h": 600,
77 "error": null,
88 "win": {
9 "title": "Equations below - Microsoft OneNote",
9 "title": "Destination - Microsoft OneNote",
1010 "class": "Framework::CFrame",
1111 "dialog": false
1212 }
corpus/page-copy/cold/read/page-000.png
Binary files a/corpus/page-copy/cold/read/page-000.png and b/corpus/page-copy/cold/read/page-000.png differ
corpus/page-copy/cold/read/page-000.xml+1-2
......@@ -1,3 +1,2 @@
11<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{5A5E0FDA-1644-0F00-0C45-8D72178B2031}{1}{B0}" name="Equations below" dateTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{5A5E0FDA-1644-0F00-0C45-8D72178B2031}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Equations below]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{75AB7537-48D1-0C4C-297D-B4D4CFA87CA2}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="140.9678649902344" height="208.9916534423828"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{D6CEF286-AFD3-0A03-0655-BA825F09BE5C}{1}{B0}" alignment="left"><one:T><![CDATA[Equations below]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{111AB493-1B15-0171-1BEC-C517BF808F15}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:msup><mml:mi>x</mml:mi><mml:mn>2</mml:mn></mml:msup><mml:mo>+</mml:mo><mml:msup><mml:mi>y</mml:mi><mml:mn>2</mml:mn></mml:msup><mml:mo>=</mml:mo><mml:msup><mml:mi>z</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{E963BDE9-C0E4-02BE-2D54-23989FC58846}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:mfrac><mml:mrow><mml:mi>a</mml:mi><mml:mo>+</mml:mo><mml:mi>b</mml:mi></mml:mrow><mml:mrow><mml:mi>c</mml:mi><mml:mo>+</mml:mo><mml:mi>d</mml:mi></mml:mrow></mml:mfrac></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{869A34E1-759D-03DC-1F28-DE83A586BDD6}{1}{B0}" alignment="left" style="font-size:11.0pt"><one:T><![CDATA[<span
3style='font-family:Calibri' lang=en-US>Inline </span><!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mi>&#120572;</mml:mi><mml:mo>+</mml:mo><mml:mi>&#120573;</mml:mi></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{877DD34D-81AC-038C-0477-B3E0645DD63E}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:msub><mml:mi>a</mml:mi><mml:mn>1</mml:mn></mml:msub><mml:mo>+</mml:mo><mml:msub><mml:mi>b</mml:mi><mml:mn>2</mml:mn></mml:msub></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{CD4EC150-40D1-074B-1157-F388604EEBE0}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:msubsup><mml:mi>x</mml:mi><mml:mi>i</mml:mi><mml:mn>2</mml:mn></mml:msubsup></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{1B908B9B-F5DF-0E47-3861-D55838C5AB28}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:mfenced><mml:mrow><mml:mi>a</mml:mi><mml:mo>+</mml:mo><mml:mi>b</mml:mi></mml:mrow></mml:mfenced></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{2A2E6B30-0040-052F-26F1-91BABCAE46B2}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:msubsup><mml:mo stretchy="false">∫</mml:mo><mml:mn>0</mml:mn><mml:mn>1</mml:mn></mml:msubsup><mml:mrow><mml:mi>x</mml:mi><mml:mo>&nbsp;</mml:mo><mml:mi>d</mml:mi><mml:mi>x</mml:mi><mml:mo>&nbsp;</mml:mo></mml:mrow></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{3110679E-A6C8-08CA-14E7-D38AABF07619}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:munderover><mml:mo stretchy="false">∑</mml:mo><mml:mrow><mml:mi>i</mml:mi><mml:mo>=</mml:mo><mml:mn>1</mml:mn></mml:mrow><mml:mi>n</mml:mi></mml:munderover><mml:mrow><mml:mi>i</mml:mi><mml:mo>&nbsp;</mml:mo></mml:mrow></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{58A7316B-7529-03F0-2F54-20F513A79572}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:msup><mml:mi>x</mml:mi><mml:mn>2</mml:mn></mml:msup><mml:mo>+</mml:mo><mml:mn>1</mml:mn></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{BFE82679-7A72-09C5-266D-FBEC819E237D}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:mfrac><mml:mrow><mml:mi>a</mml:mi><mml:mo>+</mml:mo><mml:mi>b</mml:mi></mml:mrow><mml:mrow><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:mfrac></mml:math><![endif]-->]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{0A5A2909-7069-0DA0-2457-FE8F9CA25885}{1}{B0}" name="Destination" dateTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:14:26.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Outline author="Author" lastModifiedBy="Author" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{8631621B-321A-0F71-03FE-3BCA53E86583}{23}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="118.3393707275391" height="13.4277172088623"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{8631621B-321A-0F71-03FE-3BCA53E86583}{24}{B0}" alignment="left"><one:T><![CDATA[Destination]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-001.navigation.json+1-1
......@@ -6,7 +6,7 @@
66 "h": 600,
77 "error": null,
88 "win": {
9 "title": "Open task - Microsoft OneNote",
9 "title": "Before the picture - Microsoft OneNote",
1010 "class": "Framework::CFrame",
1111 "dialog": false
1212 }
corpus/page-copy/cold/read/page-001.png
Binary files a/corpus/page-copy/cold/read/page-001.png and b/corpus/page-copy/cold/read/page-001.png differ
corpus/page-copy/cold/read/page-001.xml+3-1
......@@ -1,2 +1,4 @@
11<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{5C003E48-8717-05C2-096E-6762316BC0A0}{1}{B0}" name="Open task" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:TagDef index="0" type="0" symbol="3" fontColor="automatic" highlightColor="none" name="Rust task"/><one:TagDef index="1" type="1" symbol="13" fontColor="#FF0000" highlightColor="#FFFF00" name="Important"/><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{5C003E48-8717-05C2-096E-6762316BC0A0}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Open task]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{EA96F1EA-D912-043B-3585-EF6DB73F7D60}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="158.2036895751953" height="53.71086883544922"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{2B4A358D-B65A-0B30-167C-A3C772956F2F}{1}{B0}" alignment="left"><one:Tag index="0" completed="false" disabled="false" creationDate="2020-01-02T03:04:05.000Z"/><one:T><![CDATA[Open task]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{30380DA0-EF03-0A04-03AD-6F50C3F095CB}{1}{B0}" alignment="left"><one:Tag index="0" completed="true" disabled="false" creationDate="2020-01-02T03:04:05.000Z" completionDate="2020-01-02T04:05:06.000Z"/><one:T><![CDATA[Completed task]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{26502F9C-1811-0C5C-23BE-395D96FFF797}{1}{B0}" alignment="left"><one:Tag index="0" completed="false" disabled="false" creationDate="2020-01-02T03:04:05.000Z"/><one:Tag index="1" completed="false" disabled="false" creationDate="2020-01-02T03:04:05.000Z"/><one:T><![CDATA[Important open task]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{B17CBFD9-E3D1-0CC8-0837-B615ED83C6E5}{1}{B0}" alignment="left"><one:T><![CDATA[Untagged]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{1E9DFA9B-2BEB-0C4E-3FEA-12F1C294A76E}{1}{B0}" name="Before the picture" dateTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{1E9DFA9B-2BEB-0C4E-3FEA-12F1C294A76E}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Before the picture]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{4DA80AD4-95E4-0563-13A1-48595B5FF4B8}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="148.3100738525391" height="27.60543251037598"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{AFD96465-6096-07A5-2297-9F5092B2C4D0}{1}{B0}" alignment="left" style="font-family:Calibri;font-size:11.0pt"><one:T><![CDATA[Before the picture]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{EAFF9A35-4964-0B98-232B-BE4FC1E5AC7A}{1}{B0}" alignment="left"><one:Image format="png"><one:Data>iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4z8AAAAMBAQAY3Y2w
3AAAAAElFTkSuQmCC
4</one:Data></one:Image></one:OE><one:OE creationTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{30FDBCD9-EBE5-0C42-3241-15D4E7312FCD}{1}{B0}" alignment="left" style="font-family:Calibri;font-size:11.0pt"><one:T><![CDATA[After the picture]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-002.navigation.json+1-1
......@@ -6,7 +6,7 @@
66 "h": 600,
77 "error": null,
88 "win": {
9 "title": "Destination - Microsoft OneNote",
9 "title": "Indent bullet subtree - Microsoft OneNote",
1010 "class": "Framework::CFrame",
1111 "dialog": false
1212 }
corpus/page-copy/cold/read/page-002.png
Binary files a/corpus/page-copy/cold/read/page-002.png and b/corpus/page-copy/cold/read/page-002.png differ
corpus/page-copy/cold/read/page-002.xml+4-1
......@@ -1,2 +1,5 @@
11<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{8BB0D046-3BC7-0CE9-33B2-04F7D5E9C6FD}{1}{B0}" name="Destination" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:35.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Outline author="Author" lastModifiedBy="Author" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{6D7B6C59-2E45-0D8F-286E-4FD72999E63A}{23}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="118.3393707275391" height="13.4277172088623"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{6D7B6C59-2E45-0D8F-286E-4FD72999E63A}{24}{B0}" alignment="left"><one:T><![CDATA[Destination]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{25E90FFA-6C7E-0A8D-3F8B-FC658F7AAF3B}{1}{B0}" name="Indent bullet subtree" dateTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" lang="en-US"><one:TagDef index="0" type="0" symbol="3" fontColor="automatic" highlightColor="none" name="Preserved task"/><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{25E90FFA-6C7E-0A8D-3F8B-FC658F7AAF3B}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Indent bullet subtree]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{E70D26B4-5E53-0439-14D6-AB435B274370}{1}{B0}"><one:Position x="72.0" y="108.0" z="0"/><one:Size width="142.6107788085937" height="67.13858032226562"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{C20780E2-91FA-0C79-3266-C1E8843F8C27}{1}{B0}" alignment="left" quickStyleIndex="1"><one:List><one:Bullet bullet="3" fontSize="11.0"/></one:List><one:T><![CDATA[Anchor]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{B9F245E8-A24F-019A-3F3E-540901F3F3F1}{1}{B0}" alignment="left" quickStyleIndex="1"><one:Tag index="0" completed="true" disabled="false" creationDate="2020-01-02T03:04:05.000Z" completionDate="2020-01-02T04:05:06.000Z"/><one:List><one:Bullet bullet="3" fontSize="11.0"/></one:List><one:T><![CDATA[<span
3style='font-weight:bold'>Target &#129408; é</span> <a
4href="https://example.invalid/tree">Link label</a>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{F762F81C-0C7D-0D7E-318B-18934A658911}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T style="font-family:Calibri;font-size:11.0pt"><![CDATA[<span
5style='font-style:italic'>Child</span>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{25F7C65A-45FD-03F5-31CF-DCA9A335FC64}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Grandchild]]></one:T></one:OE></one:OEChildren></one:OE></one:OEChildren></one:OE><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{91205826-B132-0A1C-0828-370A55059BE9}{1}{B0}" alignment="left" quickStyleIndex="1"><one:List><one:Bullet bullet="3" fontSize="11.0"/></one:List><one:T><![CDATA[Trailing sibling]]></one:T></one:OE></one:OEChildren></one:Outline><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{7E8151C3-CE0D-083C-29FA-66EB4C60734C}{1}{B0}"><one:Position x="540.0" y="108.0" z="1"/><one:Size width="99.85796356201171" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{A50B7E04-F685-06D4-3602-48EC3C9D5381}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Other outline]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-003.navigation.json+1-1
......@@ -6,7 +6,7 @@
66 "h": 600,
77 "error": null,
88 "win": {
9 "title": "Before the table - Microsoft OneNote",
9 "title": "Bullet item - Microsoft OneNote",
1010 "class": "Framework::CFrame",
1111 "dialog": false
1212 }
corpus/page-copy/cold/read/page-003.png
Binary files a/corpus/page-copy/cold/read/page-003.png and b/corpus/page-copy/cold/read/page-003.png differ
corpus/page-copy/cold/read/page-003.xml+1-1
......@@ -1,2 +1,2 @@
11<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{91EAB23E-CBE0-0D18-1A25-23B9CBC39112}{1}{B0}" name="Before the table" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:35.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{91EAB23E-CBE0-0D18-1A25-23B9CBC39112}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Before the table]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{899FA9AA-6E30-05C6-0039-C1174852FBAA}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="395.1299438476562" height="67.21086883544922"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{03DB4753-6DD9-0476-0A44-807F1E239611}{1}{B0}" alignment="left"><one:T><![CDATA[Before the table]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{CC36F460-50AA-0CAC-185C-B2DD3405EC23}{1}{B0}" alignment="left"><one:Table bordersVisible="true" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{F406EA96-EABF-0750-358B-13B077B8877C}{1}{B0}"><one:Columns><one:Column index="0" width="144.0" isLocked="true"/><one:Column index="1" width="216.0" isLocked="true"/></one:Columns><one:Row objectID="{B57E3F32-D364-012F-129A-7A8AFA0A8DE1}{1}{B0}" lastModifiedTime="2026-09-13T07:33:14.000Z"><one:Cell lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{8B99B904-69FB-0ABF-25D8-6EDED1F41EED}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{2F0315A5-D396-09FD-0772-968EDD6113D6}{1}{B0}" alignment="left"><one:T><![CDATA[Name]]></one:T></one:OE></one:OEChildren></one:Cell><one:Cell lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{58E45041-62CE-0EFA-3F22-C4509482E3BF}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{0F92F8F0-F5F6-0CCA-3E1C-10A217EA11EF}{1}{B0}" alignment="left"><one:T><![CDATA[Value]]></one:T></one:OE></one:OEChildren></one:Cell></one:Row><one:Row objectID="{6D9AA72E-D225-0D46-3D00-5B12D99343C3}{1}{B0}" lastModifiedTime="2026-09-13T07:33:14.000Z"><one:Cell lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{2555B7CF-F12A-013D-0652-4CA9AEF5284C}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{A0E15DEA-0A8D-0F42-12FA-36CC54EA289A}{1}{B0}" alignment="left"><one:T><![CDATA[Rust &#129408;]]></one:T></one:OE></one:OEChildren></one:Cell><one:Cell lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{7ED49F5B-8C93-0208-16B6-8816DB6B4151}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{D60ED3D2-2081-02A2-1EC5-A3D1190448EB}{1}{B0}" alignment="left"><one:T><![CDATA[Written natively]]></one:T></one:OE></one:OEChildren></one:Cell></one:Row></one:Table></one:OE><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{F18DD402-3CA3-01AB-32DC-D1D5A8545B7F}{1}{B0}" alignment="left"><one:T><![CDATA[After the table]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{35E45165-B253-07BF-1324-6FC7DCE3552B}{1}{B0}" name="Bullet item" dateTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{35E45165-B253-07BF-1324-6FC7DCE3552B}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Bullet item]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{1030C98D-AF8F-01AF-0FE4-4821037C552D}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="174.7353515625" height="93.99401092529296"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{41E8A28A-ADD0-072D-0780-D5A47F095985}{1}{B0}" alignment="left"><one:List><one:Bullet bullet="3" fontSize="11.0"/></one:List><one:T><![CDATA[Bullet item]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{45462BD4-B2B9-0403-1A75-2A2CFE1C6368}{1}{B0}" alignment="left"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="I."/></one:List><one:T><![CDATA[First numbered]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{0547114E-6093-0FBB-0257-A78B4D838BFB}{1}{B0}" alignment="left"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="II."/></one:List><one:T><![CDATA[Second numbered]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{BBD74A7A-615E-04F9-0758-5D319A106A96}{1}{B0}" alignment="left"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="I."/></one:List><one:T><![CDATA[Nested numbered]]></one:T></one:OE></one:OEChildren></one:OE><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{73CB0260-61B9-026E-068D-9106DD4C284F}{1}{B0}" alignment="left"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="III."/></one:List><one:T><![CDATA[Restarted at three]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{D4851817-9021-0C2E-1FB9-78CACB7483E5}{1}{B0}" alignment="left"><one:T><![CDATA[Nested plain]]></one:T></one:OE></one:OEChildren></one:OE><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{7F1ACAD9-03E3-0D2C-0854-83C7B46AA88A}{1}{B0}" alignment="left"><one:T><![CDATA[Plain again]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-004.navigation.json+1-1
......@@ -6,7 +6,7 @@
66 "h": 600,
77 "error": null,
88 "win": {
9 "title": "Beside the drawing - Microsoft OneNote",
9 "title": "Delete sole cell paragraph - Microsoft OneNote",
1010 "class": "Framework::CFrame",
1111 "dialog": false
1212 }
corpus/page-copy/cold/read/page-004.png
Binary files a/corpus/page-copy/cold/read/page-004.png and b/corpus/page-copy/cold/read/page-004.png differ
corpus/page-copy/cold/read/page-004.xml+3-6
......@@ -1,7 +1,4 @@
11<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{B28A26BE-5DF2-0214-1827-B1747FE95ECC}{1}{B0}" name="Beside the drawing" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{B28A26BE-5DF2-0214-1827-B1747FE95ECC}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Beside the drawing]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{BA59696B-EAE1-0771-0BCB-5878F45A65F8}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="152.4244079589843" height="13.4277172088623"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{38FEF76B-56AE-0456-1B54-A2C668C24685}{1}{B0}" alignment="left"><one:T><![CDATA[Beside the drawing]]></one:T></one:OE></one:OEChildren></one:Outline><one:InkDrawing lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{501D4164-CA81-04D3-1BDC-D2CA0006F088}{1}{B0}"><one:Position x="299.9905395507812" y="119.9905471801758" z="1"/><one:Size width="60.03781127929687" height="60.03779220581055"/><one:Data>AM8CHQSiAaIBAWAqABofi0JwRYR1gL7QRdkE+oeVMvLsF0G4wBa/8yv0et67E4vlXrNInJuhJVq3
3URK/7HHMzCKxQYkOuxMs7nqhWM9UiuaXxU+PBvi60uGbIsRmbacNslhJmh1OQDQGbBACEQZIEEUj
4RiMJSBBE/wFFI0YjBQgLZU9mZ2hkaRkUMggAgB4CIeLiQTMIAPAQAovF4kFkAxVGAEAKXAWH8gln
5jCj7wnvCe8IAh/B8h4Pke8I7wnvCQAUURgBAAAAJBAUURgAAAAASABEgKFNtArpWcU+AsrjC8JNY
6RQo/QCNkARXUNSA7oAMVRgBACj9AIm9GCC70WAqACQEKTAIPUq7GcA5CJYzgBRRGAIAAAAkEBRRG
7AAAAABIAESAJY0kvgp5dSp0WwhnX6NwFCj9AI2QBFdQ1IDugAxVGAEAKP0Aib0YILvRYCoA=</one:Data></one:InkDrawing></one:Page>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{493E9D0C-5976-0886-2ADB-636A30B81D20}{1}{B0}" name="Delete sole cell paragraph" dateTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" lang="en-US"><one:TagDef index="0" type="0" symbol="3" fontColor="automatic" highlightColor="none" name="Preserved task"/><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{493E9D0C-5976-0886-2ADB-636A30B81D20}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Delete sole cell paragraph]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{9721CF72-8007-0180-29C3-D0F422003C1B}{1}{B0}"><one:Position x="72.0" y="108.0" z="0"/><one:Size width="428.1300048828125" height="21.94771385192871"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{76A5FFBC-C8EC-0E30-2663-51714300B179}{1}{B0}" alignment="left"><one:Table bordersVisible="true" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{EFDBE2D8-39D5-0EDF-075C-26A7D704FD28}{1}{B0}"><one:Columns><one:Column index="0" width="240.0" isLocked="true"/><one:Column index="1" width="180.0" isLocked="true"/></one:Columns><one:Row objectID="{8D1D5F63-2DD1-0274-04FA-38A73347200A}{1}{B0}" lastModifiedTime="2026-09-13T08:12:57.000Z"><one:Cell lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{7258A0AD-D622-0854-0122-8EBEB7B70203}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{63217049-E82C-0F04-08AE-9CB184551B5D}{1}{B0}" alignment="left" quickStyleIndex="1"><one:Tag index="0" completed="true" disabled="false" creationDate="2020-01-02T03:04:05.000Z" completionDate="2020-01-02T04:05:06.000Z"/><one:T><![CDATA[<span
3style='font-weight:bold'>Target &#129408; é</span> <a
4href="https://example.invalid/tree">Link label</a>]]></one:T></one:OE></one:OEChildren></one:Cell><one:Cell lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{05B95457-4B57-0270-392F-6988B33CE2A8}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{D490ACFE-4E2D-09CE-1F5F-0866F94CA145}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Other cell]]></one:T></one:OE></one:OEChildren></one:Cell></one:Row></one:Table></one:OE></one:OEChildren></one:Outline><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{4D870AE7-2513-0CB4-3066-2217A47AB044}{1}{B0}"><one:Position x="540.0" y="108.0" z="1"/><one:Size width="99.85796356201171" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{EFA33014-C3C9-0764-0876-5357D230EE70}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Other outline]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-005.navigation.json+1-1
......@@ -6,7 +6,7 @@
66 "h": 600,
77 "error": null,
88 "win": {
9 "title": "Before the picture - Microsoft OneNote",
9 "title": "Indent first subtree - Microsoft OneNote",
1010 "class": "Framework::CFrame",
1111 "dialog": false
1212 }
corpus/page-copy/cold/read/page-005.png
Binary files a/corpus/page-copy/cold/read/page-005.png and b/corpus/page-copy/cold/read/page-005.png differ
corpus/page-copy/cold/read/page-005.xml+4-3
......@@ -1,4 +1,5 @@
11<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{B5A45771-4A39-05F8-1953-4F2F9B2B33A5}{1}{B0}" name="Before the picture" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{B5A45771-4A39-05F8-1953-4F2F9B2B33A5}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Before the picture]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{6323EB68-A315-07CD-37C1-E46DAF4BAB42}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="148.3100738525391" height="27.60543251037598"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{078AE9E1-0253-0D93-182A-750B047E4D60}{1}{B0}" alignment="left" style="font-family:Calibri;font-size:11.0pt"><one:T><![CDATA[Before the picture]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{4DBAC23A-2DBC-0548-3811-E4D1B951886F}{1}{B0}" alignment="left"><one:Image format="png"><one:Data>iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4z8AAAAMBAQAY3Y2w
3AAAAAElFTkSuQmCC
4</one:Data></one:Image></one:OE><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{79D39D0E-8F58-05A6-1C44-0CB6265FFE97}{1}{B0}" alignment="left" style="font-family:Calibri;font-size:11.0pt"><one:T><![CDATA[After the picture]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{55B596AA-4540-085D-142D-9F788431ACE5}{1}{B0}" name="Indent first subtree" dateTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" lang="en-US"><one:TagDef index="0" type="0" symbol="3" fontColor="automatic" highlightColor="none" name="Preserved task"/><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{55B596AA-4540-085D-142D-9F788431ACE5}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Indent first subtree]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{5BD6B4E1-21C1-08FD-38E8-4C7ADD81FBB1}{1}{B0}"><one:Position x="72.0" y="108.0" z="0"/><one:Size width="142.6107788085937" height="53.71086883544922"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{8B6DEB92-F345-02E1-1FB6-90BBC691E721}{1}{B0}" alignment="left" quickStyleIndex="1"><one:Tag index="0" completed="true" disabled="false" creationDate="2020-01-02T03:04:05.000Z" completionDate="2020-01-02T04:05:06.000Z"/><one:T><![CDATA[<span
3style='font-weight:bold'>Target &#129408; é</span> <a
4href="https://example.invalid/tree">Link label</a>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{365B8C25-37F9-0C75-1AD0-A969AB393EEC}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T style="font-family:Calibri;font-size:11.0pt"><![CDATA[<span
5style='font-style:italic'>Child</span>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{53D9A482-FB38-09F8-318E-E7A2A0EA655A}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Grandchild]]></one:T></one:OE></one:OEChildren></one:OE></one:OEChildren></one:OE><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{C7BC8628-6A45-0A7E-10CA-1A957E36B827}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Trailing sibling]]></one:T></one:OE></one:OEChildren></one:Outline><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{B5066461-BBDD-09E8-223D-5B839E2A8637}{1}{B0}"><one:Position x="540.0" y="108.0" z="1"/><one:Size width="99.85796356201171" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{EDB23709-B01D-0CD2-08A7-A9EB953087ED}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Other outline]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-006.navigation.json+1-1
......@@ -6,7 +6,7 @@
66 "h": 600,
77 "error": null,
88 "win": {
9 "title": "Before the file - Microsoft OneNote",
9 "title": "Bold \ud83e\udd80 italic e\u0301 color \u6771\u4eac - Microsoft OneNote",
1010 "class": "Framework::CFrame",
1111 "dialog": false
1212 }
corpus/page-copy/cold/read/page-006.png
Binary files a/corpus/page-copy/cold/read/page-006.png and b/corpus/page-copy/cold/read/page-006.png differ
corpus/page-copy/cold/read/page-006.xml+19-1
......@@ -1,2 +1,20 @@
11<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{C12C0ECF-DDF8-0A21-11BE-3074429542E0}{1}{B0}" name="Before the file" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:35.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{C12C0ECF-DDF8-0A21-11BE-3074429542E0}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Before the file]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{A4D24969-1B13-0F34-3174-834AD8FF8832}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="130.4619598388672" height="89.85542297363281"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{6D8ADE9E-3EE4-03A9-2EC9-0A80C321B126}{1}{B0}" alignment="left" style="font-family:Calibri;font-size:11.0pt"><one:T><![CDATA[Before the file]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{03AD9394-425B-0B9C-0D27-CA384DFFCEBF}{1}{B0}" alignment="left"><one:InsertedFile pathCache="C:\Users\clover\AppData\Local\Microsoft\OneNote\14.0\OneNoteOfflineCache_Files\6d823ba5-6b7e-4df3-947b-a1047440dfa2.txt" preferredName="notes 🦀.txt"/></one:OE><one:OE creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{A6E026B4-3D17-078E-20A3-50C86A85A2AB}{1}{B0}" alignment="left" style="font-family:Calibri;font-size:11.0pt"><one:T><![CDATA[After the file]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{5E04C302-1E83-0CCD-1715-B0A2566E0191}{1}{B0}" name="Bold 🦀 italic é color 東京" dateTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:14:26.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{5E04C302-1E83-0CCD-1715-B0A2566E0191}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Bold &#129408; italic é color 東京]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{B63306AF-2B95-0428-2EB2-67405305D5CD}{1}{B0}"><one:Position x="36.0" y="14.40000057220459" z="0"/><one:Size width="127.5136947631836" height="42.03070831298828"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{07F96F7E-EE93-0108-00D0-9E4BE9011C40}{1}{B0}" alignment="left"><one:T><![CDATA[<span style='font-weight:bold;
3text-decoration:underline;font-family:Calibri;font-size:11.0pt'>Bold</span><span
4style='font-family:Calibri;font-size:11.0pt'> </span><span style='font-family:
5Arial;font-size:13.5pt'>&#129408;</span><span style='font-family:Calibri;
6font-size:11.0pt'> </span><span style='font-style:italic;text-decoration:line-through;
7font-family:Calibri;font-size:11.0pt'>italic</span><span style='font-family:
8Calibri;font-size:11.0pt'> </span><span style='vertical-align:super;font-family:
9Calibri;font-size:11.0pt'>é</span><span style='font-family:Calibri;font-size:
1011.0pt'> </span><span style='font-family:Calibri;font-size:11.0pt;color:#0C2238;
11background:yellow;mso-highlight:yellow'>color</span><span style='font-family:
12Calibri;font-size:11.0pt'> </span><span style='vertical-align:sub;font-family:
13Calibri;font-size:11.0pt'>東京</span><span style='font-family:Calibri;font-size:
1411.0pt'><br>
15End</span>]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{EEA4A13A-3CBD-04DA-02B1-47CF8F1BE77E}{1}{B0}" alignment="left" quickStyleIndex="1" style="font-size:11.0pt;color:#1F4E79"><one:T><![CDATA[<span
16style='font-weight:bold;font-family:Calibri' lang=en-US>Fictitious: café, </span><span
17style='font-weight:bold;font-family:SimSun' lang=en-US>東京</span><span
18style='font-weight:bold;font-family:Calibri' lang=en-US>, </span><span
19style='font-weight:bold;font-family:Arial;direction:rtl;unicode-bidi:embed'
20lang=ar-SA>مرحبا</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-007.navigation.json+1-1
......@@ -6,7 +6,7 @@
66 "h": 600,
77 "error": null,
88 "win": {
9 "title": "Bullet item - Microsoft OneNote",
9 "title": "Before the file - Microsoft OneNote",
1010 "class": "Framework::CFrame",
1111 "dialog": false
1212 }
corpus/page-copy/cold/read/page-007.png
Binary files a/corpus/page-copy/cold/read/page-007.png and b/corpus/page-copy/cold/read/page-007.png differ
corpus/page-copy/cold/read/page-007.xml+1-1
......@@ -1,2 +1,2 @@
11<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{C5E005CB-753E-07E2-0C53-CD40FBB64A63}{1}{B0}" name="Bullet item" dateTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T07:33:14.000Z" lastModifiedTime="2026-09-13T07:33:14.000Z" objectID="{C5E005CB-753E-07E2-0C53-CD40FBB64A63}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Bullet item]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{04550845-DFD8-0D15-199D-14BBB6068FC4}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="174.7353515625" height="93.99401092529296"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{FADAD1EB-13D4-0679-1470-A27D6E3C4C82}{1}{B0}" alignment="left"><one:List><one:Bullet bullet="3" fontSize="11.0"/></one:List><one:T><![CDATA[Bullet item]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{D1386D56-B57F-01DD-3DCE-AE2F7E41CF7B}{1}{B0}" alignment="left"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="I."/></one:List><one:T><![CDATA[First numbered]]></one:T></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{8F5A5D13-ADD9-0514-013E-D1A0CBA1E68F}{1}{B0}" alignment="left"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="II."/></one:List><one:T><![CDATA[Second numbered]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{448444D9-663C-0454-150E-544F2D29DAED}{1}{B0}" alignment="left"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="I."/></one:List><one:T><![CDATA[Nested numbered]]></one:T></one:OE></one:OEChildren></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{AB4C6543-D5B5-02F2-18CD-1EA3C75D0B5F}{1}{B0}" alignment="left"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="III."/></one:List><one:T><![CDATA[Restarted at three]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{1E15DFFF-2CEC-03FA-0FEF-75E2303FB336}{1}{B0}" alignment="left"><one:T><![CDATA[Nested plain]]></one:T></one:OE></one:OEChildren></one:OE><one:OE creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{49D667B4-861E-0253-29DB-8BA25CF21B9E}{1}{B0}" alignment="left"><one:T><![CDATA[Plain again]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{62E12C49-D5FE-0850-17D5-B4DC95B736E9}{1}{B0}" name="Before the file" dateTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:14:26.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{62E12C49-D5FE-0850-17D5-B4DC95B736E9}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Before the file]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{FBCA9C23-1A13-020A-35BC-1365A45C381E}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="130.4619598388672" height="89.85542297363281"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{2A6BB41D-EDD1-0546-0571-2950BFD2D187}{1}{B0}" alignment="left" style="font-family:Calibri;font-size:11.0pt"><one:T><![CDATA[Before the file]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{9E89195D-B7EC-0AC4-34FD-F47D633F0533}{1}{B0}" alignment="left"><one:InsertedFile pathCache="C:\Users\clover\AppData\Local\Microsoft\OneNote\14.0\OneNoteOfflineCache_Files\6bf086f4-be12-4374-9140-4ddaf36216fe.txt" preferredName="notes 🦀.txt"/></one:OE><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{48D46AA0-F634-084B-171A-1D72CF298968}{1}{B0}" alignment="left" style="font-family:Calibri;font-size:11.0pt"><one:T><![CDATA[After the file]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-008.navigation.json+1-1
......@@ -6,7 +6,7 @@
66 "h": 600,
77 "error": null,
88 "win": {
9 "title": "A notebook created in Rust. - Microsoft OneNote",
9 "title": "Delete numbered subtree - Microsoft OneNote",
1010 "class": "Framework::CFrame",
1111 "dialog": false
1212 }
corpus/page-copy/cold/read/page-008.png
Binary files a/corpus/page-copy/cold/read/page-008.png and b/corpus/page-copy/cold/read/page-008.png differ
corpus/page-copy/cold/read/page-008.xml+4-1
......@@ -1,2 +1,5 @@
11<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{D4C06049-3C91-0190-0C2E-1BB1EBA49EBA}{1}{B0}" name="A notebook created in Rust." dateTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:34:36.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T07:33:15.000Z" lastModifiedTime="2026-09-13T07:33:15.000Z" objectID="{D4C06049-3C91-0190-0C2E-1BB1EBA49EBA}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[A notebook created in Rust.]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T07:33:16.000Z" objectID="{F0CA7185-BDBF-066E-0D2C-CAE46E036850}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="191.1661224365234" height="13.4277172088623"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T07:33:16.000Z" lastModifiedTime="2026-09-13T07:33:16.000Z" objectID="{F7D0FEC9-71DC-00E3-30D7-07DB00C2623B}{1}{B0}" alignment="left"><one:T><![CDATA[A notebook created in Rust.]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{6EC9E652-85BD-0524-17E7-232F5951B731}{1}{B0}" name="Delete numbered subtree" dateTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" lang="en-US"><one:TagDef index="0" type="0" symbol="3" fontColor="automatic" highlightColor="none" name="Preserved task"/><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{6EC9E652-85BD-0524-17E7-232F5951B731}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Delete numbered subtree]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{7D694249-C0B4-02DD-1DC7-3136ED2FFA27}{1}{B0}"><one:Position x="72.0" y="108.0" z="0"/><one:Size width="142.6107788085937" height="67.13858032226562"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{758447BB-8217-0430-1A24-108E47546937}{1}{B0}" alignment="left" quickStyleIndex="1"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="I."/></one:List><one:T><![CDATA[Anchor]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{72575BCE-8279-0163-3BD9-443858B25152}{1}{B0}" alignment="left" quickStyleIndex="1"><one:Tag index="0" completed="true" disabled="false" creationDate="2020-01-02T03:04:05.000Z" completionDate="2020-01-02T04:05:06.000Z"/><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="II."/></one:List><one:T><![CDATA[<span
3style='font-weight:bold'>Target &#129408; é</span> <a
4href="https://example.invalid/tree">Link label</a>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{59A91EE5-A5B6-06B1-328F-DCF3FC7EDAAC}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T style="font-family:Calibri;font-size:11.0pt"><![CDATA[<span
5style='font-style:italic'>Child</span>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{9B857AAD-2B9A-0AB3-1341-A048617E97BC}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Grandchild]]></one:T></one:OE></one:OEChildren></one:OE></one:OEChildren></one:OE><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{C4A6021B-B90F-0CD2-2BDB-0BDD084AB0A6}{1}{B0}" alignment="left" quickStyleIndex="1"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="III."/></one:List><one:T><![CDATA[Trailing sibling]]></one:T></one:OE></one:OEChildren></one:Outline><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{194A9C6A-9CCD-07AA-13B8-DE3F2E45394E}{1}{B0}"><one:Position x="540.0" y="108.0" z="1"/><one:Size width="99.85796356201171" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{D3A6B926-9395-0950-1BB5-A6C460D39349}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Other outline]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-009.navigation.json created+13
......@@ -0,0 +1,13 @@
1{
2 "exit": 0,
3 "stdout": "",
4 "stderr": "",
5 "w": 800,
6 "h": 600,
7 "error": null,
8 "win": {
9 "title": "Equations below - Microsoft OneNote",
10 "class": "Framework::CFrame",
11 "dialog": false
12 }
13}
\ No newline at end of file
corpus/page-copy/cold/read/page-009.png created
Binary files /dev/null and b/corpus/page-copy/cold/read/page-009.png differ
corpus/page-copy/cold/read/page-009.xml created+3
......@@ -0,0 +1,3 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{78595C91-C5E1-0D03-3A98-A98CA31DE5A8}{1}{B0}" name="Equations below" dateTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{78595C91-C5E1-0D03-3A98-A98CA31DE5A8}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Equations below]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{FF465D92-B6F0-0E57-3F42-D3F428E0F163}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="140.9678649902344" height="208.9916534423828"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{25D933DF-AC4B-0333-0643-3483B2E2652A}{1}{B0}" alignment="left"><one:T><![CDATA[Equations below]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{73426626-83B5-05D8-26F7-5D6887ED2AB5}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:msup><mml:mi>x</mml:mi><mml:mn>2</mml:mn></mml:msup><mml:mo>+</mml:mo><mml:msup><mml:mi>y</mml:mi><mml:mn>2</mml:mn></mml:msup><mml:mo>=</mml:mo><mml:msup><mml:mi>z</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{45DEE337-060F-078E-1093-87D9A54DF41A}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:mfrac><mml:mrow><mml:mi>a</mml:mi><mml:mo>+</mml:mo><mml:mi>b</mml:mi></mml:mrow><mml:mrow><mml:mi>c</mml:mi><mml:mo>+</mml:mo><mml:mi>d</mml:mi></mml:mrow></mml:mfrac></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{68218407-AC5B-0355-295E-667A238EAC19}{1}{B0}" alignment="left" style="font-size:11.0pt"><one:T><![CDATA[<span
3style='font-family:Calibri' lang=en-US>Inline </span><!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mi>&#120572;</mml:mi><mml:mo>+</mml:mo><mml:mi>&#120573;</mml:mi></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{3F067690-E557-00BC-3846-0628BB3D7133}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:msub><mml:mi>a</mml:mi><mml:mn>1</mml:mn></mml:msub><mml:mo>+</mml:mo><mml:msub><mml:mi>b</mml:mi><mml:mn>2</mml:mn></mml:msub></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{7156930C-7D25-0CD1-1992-346BE0DD05FD}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:msubsup><mml:mi>x</mml:mi><mml:mi>i</mml:mi><mml:mn>2</mml:mn></mml:msubsup></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{1DE19BC8-B93A-02DB-2FA8-92B03D373A73}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:mfenced><mml:mrow><mml:mi>a</mml:mi><mml:mo>+</mml:mo><mml:mi>b</mml:mi></mml:mrow></mml:mfenced></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{5C43FBBD-302D-09D2-28A9-18789A71A072}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:msubsup><mml:mo stretchy="false">∫</mml:mo><mml:mn>0</mml:mn><mml:mn>1</mml:mn></mml:msubsup><mml:mrow><mml:mi>x</mml:mi><mml:mo>&nbsp;</mml:mo><mml:mi>d</mml:mi><mml:mi>x</mml:mi><mml:mo>&nbsp;</mml:mo></mml:mrow></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{8DBDED4C-17CA-0463-240E-91F1134B5E9F}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:munderover><mml:mo stretchy="false">∑</mml:mo><mml:mrow><mml:mi>i</mml:mi><mml:mo>=</mml:mo><mml:mn>1</mml:mn></mml:mrow><mml:mi>n</mml:mi></mml:munderover><mml:mrow><mml:mi>i</mml:mi><mml:mo>&nbsp;</mml:mo></mml:mrow></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{214F8EE1-64A0-0957-0A3F-F8E7D05B6586}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:msup><mml:mi>x</mml:mi><mml:mn>2</mml:mn></mml:msup><mml:mo>+</mml:mo><mml:mn>1</mml:mn></mml:math><![endif]-->]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{3715C26F-37BB-031C-1197-F79A9E19EE60}{1}{B0}" alignment="left" style="font-family:'Cambria Math';font-size:11.0pt"><one:T><![CDATA[<!--[if mathML]><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block"><mml:mfrac><mml:mrow><mml:mi>a</mml:mi><mml:mo>+</mml:mo><mml:mi>b</mml:mi></mml:mrow><mml:mrow><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:mfrac></mml:math><![endif]-->]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-010.navigation.json created+13
......@@ -0,0 +1,13 @@
1{
2 "exit": 0,
3 "stdout": "",
4 "stderr": "",
5 "w": 800,
6 "h": 600,
7 "error": null,
8 "win": {
9 "title": "Move numbered subtree down - Microsoft OneNote",
10 "class": "Framework::CFrame",
11 "dialog": false
12 }
13}
\ No newline at end of file
corpus/page-copy/cold/read/page-010.png created
Binary files /dev/null and b/corpus/page-copy/cold/read/page-010.png differ
corpus/page-copy/cold/read/page-010.xml created+5
......@@ -0,0 +1,5 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{79EFBB50-C028-09DE-005B-75E21D0ED54C}{1}{B0}" name="Move numbered subtree down" dateTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" lang="en-US"><one:TagDef index="0" type="0" symbol="3" fontColor="automatic" highlightColor="none" name="Preserved task"/><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{79EFBB50-C028-09DE-005B-75E21D0ED54C}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Move numbered subtree down]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{0A534E63-2DFE-07C6-0A28-71334DEE9E4D}{1}{B0}"><one:Position x="72.0" y="108.0" z="0"/><one:Size width="142.6107788085937" height="67.13858032226562"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{ED619F07-F6A1-0AC3-1461-04C34315FB37}{1}{B0}" alignment="left" quickStyleIndex="1"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="I."/></one:List><one:T><![CDATA[Anchor]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{055B6314-3B1F-00E1-2734-2684ACC53EA4}{1}{B0}" alignment="left" quickStyleIndex="1"><one:Tag index="0" completed="true" disabled="false" creationDate="2020-01-02T03:04:05.000Z" completionDate="2020-01-02T04:05:06.000Z"/><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="II."/></one:List><one:T><![CDATA[<span
3style='font-weight:bold'>Target &#129408; é</span> <a
4href="https://example.invalid/tree">Link label</a>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{BC5317C5-A40F-01F9-038E-5AED4EB7626B}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T style="font-family:Calibri;font-size:11.0pt"><![CDATA[<span
5style='font-style:italic'>Child</span>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{7F1F3536-4683-03A0-2FCB-4FF372F15926}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Grandchild]]></one:T></one:OE></one:OEChildren></one:OE></one:OEChildren></one:OE><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{4ECF5731-6B02-0ABE-1485-8D4A0B859DBE}{1}{B0}" alignment="left" quickStyleIndex="1"><one:List><one:Number numberSequence="1" numberFormat="##." fontSize="11.0" font="Calibri" text="III."/></one:List><one:T><![CDATA[Trailing sibling]]></one:T></one:OE></one:OEChildren></one:Outline><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{4A7372E3-CEB5-09D5-18D7-2A37D082BE91}{1}{B0}"><one:Position x="540.0" y="108.0" z="1"/><one:Size width="99.85796356201171" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:57.000Z" lastModifiedTime="2026-09-13T08:12:57.000Z" objectID="{DB6D2123-9BB9-016D-3D56-77B46F2BEE20}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Other outline]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-011.navigation.json created+13
......@@ -0,0 +1,13 @@
1{
2 "exit": 0,
3 "stdout": "",
4 "stderr": "",
5 "w": 800,
6 "h": 600,
7 "error": null,
8 "win": {
9 "title": "Open task - Microsoft OneNote",
10 "class": "Framework::CFrame",
11 "dialog": false
12 }
13}
\ No newline at end of file
corpus/page-copy/cold/read/page-011.png created
Binary files /dev/null and b/corpus/page-copy/cold/read/page-011.png differ
corpus/page-copy/cold/read/page-011.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{8E5634C2-26CB-0458-2810-125D129037C8}{1}{B0}" name="Open task" dateTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:TagDef index="0" type="0" symbol="3" fontColor="automatic" highlightColor="none" name="Rust task"/><one:TagDef index="1" type="1" symbol="13" fontColor="#FF0000" highlightColor="#FFFF00" name="Important"/><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{8E5634C2-26CB-0458-2810-125D129037C8}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Open task]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{0F36D11A-3FE8-0019-2E63-9AD912439D52}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="158.2036895751953" height="53.71086883544922"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{89DFA126-B932-01B1-1C58-55D810AA0133}{1}{B0}" alignment="left"><one:Tag index="0" completed="false" disabled="false" creationDate="2020-01-02T03:04:05.000Z"/><one:T><![CDATA[Open task]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{AD861E4A-D898-031B-25E9-10EBF29DCD25}{1}{B0}" alignment="left"><one:Tag index="0" completed="true" disabled="false" creationDate="2020-01-02T03:04:05.000Z" completionDate="2020-01-02T04:05:06.000Z"/><one:T><![CDATA[Completed task]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{EF2ED991-5964-0515-2042-9727E177E093}{1}{B0}" alignment="left"><one:Tag index="0" completed="false" disabled="false" creationDate="2020-01-02T03:04:05.000Z"/><one:Tag index="1" completed="false" disabled="false" creationDate="2020-01-02T03:04:05.000Z"/><one:T><![CDATA[Important open task]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{C1E4EF5F-DDB5-09B3-355F-A6449BF88678}{1}{B0}" alignment="left"><one:T><![CDATA[Untagged]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-012.navigation.json created+13
......@@ -0,0 +1,13 @@
1{
2 "exit": 0,
3 "stdout": "",
4 "stderr": "",
5 "w": 800,
6 "h": 600,
7 "error": null,
8 "win": {
9 "title": "Move cell subtree down - Microsoft OneNote",
10 "class": "Framework::CFrame",
11 "dialog": false
12 }
13}
\ No newline at end of file
corpus/page-copy/cold/read/page-012.png created
Binary files /dev/null and b/corpus/page-copy/cold/read/page-012.png differ
corpus/page-copy/cold/read/page-012.xml created+5
......@@ -0,0 +1,5 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{AA29BE5C-9249-0610-1036-E2735CEC0BB9}{1}{B0}" name="Move cell subtree down" dateTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" lang="en-US"><one:TagDef index="0" type="0" symbol="3" fontColor="automatic" highlightColor="none" name="Preserved task"/><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{AA29BE5C-9249-0610-1036-E2735CEC0BB9}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Move cell subtree down]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{5DFCE2F7-804C-019E-3F4A-DD0FF39FFE62}{1}{B0}"><one:Position x="72.0" y="108.0" z="0"/><one:Size width="428.1300048828125" height="62.23086929321289"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{2A47635E-2030-0AED-007C-5D9D0EE60320}{1}{B0}" alignment="left"><one:Table bordersVisible="true" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{132A6189-E6A3-06C8-2C3B-1301E8466F92}{1}{B0}"><one:Columns><one:Column index="0" width="240.0" isLocked="true"/><one:Column index="1" width="180.0" isLocked="true"/></one:Columns><one:Row objectID="{FFF81FBB-C1B7-0BED-2BAB-5A466882083D}{1}{B0}" lastModifiedTime="2026-09-13T08:12:59.000Z"><one:Cell lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{DE630286-2FC5-0B54-347C-FF399A93BA12}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{4B5A9D99-8F4C-0DE8-0E0A-5A618E02264F}{1}{B0}" alignment="left" quickStyleIndex="1"><one:Tag index="0" completed="true" disabled="false" creationDate="2020-01-02T03:04:05.000Z" completionDate="2020-01-02T04:05:06.000Z"/><one:T><![CDATA[<span
3style='font-weight:bold'>Target &#129408; é</span> <a
4href="https://example.invalid/tree">Link label</a>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{27BE0601-EB2D-059C-24C6-205D71642566}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T style="font-family:Calibri;font-size:11.0pt"><![CDATA[<span
5style='font-style:italic'>Child</span>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{E96A9E1E-A5AB-0668-1244-4836285586EF}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Grandchild]]></one:T></one:OE></one:OEChildren></one:OE></one:OEChildren></one:OE><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{6E58F561-F9E2-085E-1864-3AEDF1A5E9F7}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Cell tail]]></one:T></one:OE></one:OEChildren></one:Cell><one:Cell lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{703BD781-4848-05D8-0381-00C40C756723}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{3A828837-47ED-0922-39C9-7A291414EFE2}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Other cell]]></one:T></one:OE></one:OEChildren></one:Cell></one:Row></one:Table></one:OE></one:OEChildren></one:Outline><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{68C4CF29-651E-0F55-2987-5FF0DC3E0D05}{1}{B0}"><one:Position x="540.0" y="108.0" z="1"/><one:Size width="99.85796356201171" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{901AFAAD-146E-0CB5-1C0A-135DFC01AF28}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Other outline]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-013.navigation.json created+13
......@@ -0,0 +1,13 @@
1{
2 "exit": 0,
3 "stdout": "",
4 "stderr": "",
5 "w": 800,
6 "h": 600,
7 "error": null,
8 "win": {
9 "title": "Delete cell subtree - Microsoft OneNote",
10 "class": "Framework::CFrame",
11 "dialog": false
12 }
13}
\ No newline at end of file
corpus/page-copy/cold/read/page-013.png created
Binary files /dev/null and b/corpus/page-copy/cold/read/page-013.png differ
corpus/page-copy/cold/read/page-013.xml created+5
......@@ -0,0 +1,5 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{BA810F75-DBC0-0827-0990-F9FBFC84B7D7}{1}{B0}" name="Delete cell subtree" dateTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" lang="en-US"><one:TagDef index="0" type="0" symbol="3" fontColor="automatic" highlightColor="none" name="Preserved task"/><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{BA810F75-DBC0-0827-0990-F9FBFC84B7D7}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Delete cell subtree]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{EF2F80B0-92D7-0C40-3469-9AB6923AC934}{1}{B0}"><one:Position x="72.0" y="108.0" z="0"/><one:Size width="428.1300048828125" height="62.30315780639648"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{A3D5DD07-CAAA-0FC1-3434-2BFCD5EAFB3A}{1}{B0}" alignment="left"><one:Table bordersVisible="true" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{1C90E39E-CEB9-072B-1045-5350DE91C9BA}{1}{B0}"><one:Columns><one:Column index="0" width="240.0" isLocked="true"/><one:Column index="1" width="180.0" isLocked="true"/></one:Columns><one:Row objectID="{00FE4CB7-3AD9-0A13-02EC-F45825DA0837}{1}{B0}" lastModifiedTime="2026-09-13T08:12:56.000Z"><one:Cell lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{C0215DC2-A310-09E1-2C56-611011EEDEDA}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{B168AA68-D0D0-0783-3211-7CBCF62C1878}{1}{B0}" alignment="left" quickStyleIndex="1"><one:Tag index="0" completed="true" disabled="false" creationDate="2020-01-02T03:04:05.000Z" completionDate="2020-01-02T04:05:06.000Z"/><one:T><![CDATA[<span
3style='font-weight:bold'>Target &#129408; é</span> <a
4href="https://example.invalid/tree">Link label</a>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{51E78125-5D88-02B2-1F60-3564BF9AB799}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T style="font-family:Calibri;font-size:11.0pt"><![CDATA[<span
5style='font-style:italic'>Child</span>]]></one:T><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{9EE1315E-F0F0-01F2-236C-CED603CE6C83}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Grandchild]]></one:T></one:OE></one:OEChildren></one:OE></one:OEChildren></one:OE><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{FD8B95A9-B069-065B-24ED-358E77DA9126}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Cell tail]]></one:T></one:OE></one:OEChildren></one:Cell><one:Cell lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{C371CC3D-4164-0E42-20D2-92CDC0E0162E}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{3A7C1016-52CD-0EE0-1D98-5D6464F47C40}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Other cell]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{D4CC12A4-5B3C-0061-0FC8-329CFD2237A8}{1}{B0}" alignment="left" style="font-family:Calibri;font-size:11.0pt"><one:Table bordersVisible="true" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{2BDFCA04-550A-0B11-3229-C359C02CEC1A}{1}{B0}"><one:Columns><one:Column index="0" width="72.0" isLocked="true"/></one:Columns><one:Row objectID="{933BCC33-B101-006B-1B06-D1EA10BD608E}{1}{B0}" lastModifiedTime="2026-09-13T08:12:56.000Z"><one:Cell lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{C9AC97DE-B8A6-079A-05EA-1C006AE7F1F6}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{F3B663D9-B871-0F4A-0480-14D1C093E86C}{1}{B0}" alignment="left"><one:T><![CDATA[Inner one]]></one:T></one:OE></one:OEChildren></one:Cell></one:Row><one:Row objectID="{49CDA646-4B5C-05D4-1D4A-377146640436}{1}{B0}" lastModifiedTime="2026-09-13T08:12:56.000Z"><one:Cell lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{4C20D881-145C-0B85-3B52-D9FC9DA41CF8}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{23ACBCB6-41CC-0F28-29A2-649DCD1F070A}{1}{B0}" alignment="left"><one:T><![CDATA[Inner two]]></one:T></one:OE></one:OEChildren></one:Cell></one:Row></one:Table></one:OE></one:OEChildren></one:Cell></one:Row></one:Table></one:OE></one:OEChildren></one:Outline><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{DD272184-6150-017E-0C7B-E0A6C9D33F67}{1}{B0}"><one:Position x="540.0" y="108.0" z="1"/><one:Size width="99.85796356201171" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-13T08:12:56.000Z" lastModifiedTime="2026-09-13T08:12:56.000Z" objectID="{E23E61E5-7407-0548-006A-201CB1623B82}{1}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Other outline]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-014.navigation.json created+13
......@@ -0,0 +1,13 @@
1{
2 "exit": 0,
3 "stdout": "",
4 "stderr": "",
5 "w": 800,
6 "h": 600,
7 "error": null,
8 "win": {
9 "title": "Beside the drawing - Microsoft OneNote",
10 "class": "Framework::CFrame",
11 "dialog": false
12 }
13}
\ No newline at end of file
corpus/page-copy/cold/read/page-014.png created
Binary files /dev/null and b/corpus/page-copy/cold/read/page-014.png differ
corpus/page-copy/cold/read/page-014.xml created+7
......@@ -0,0 +1,7 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{D28E7576-C55F-0047-2C51-4C855C536D13}{1}{B0}" name="Beside the drawing" dateTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:58.000Z" lastModifiedTime="2026-09-13T08:12:58.000Z" objectID="{D28E7576-C55F-0047-2C51-4C855C536D13}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Beside the drawing]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{110E90F1-B6EC-0EE0-1F13-367858D96194}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="152.4244079589843" height="13.4277172088623"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T08:12:59.000Z" lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{14A2DDB9-EF56-053E-2D5F-B9FF92056636}{1}{B0}" alignment="left"><one:T><![CDATA[Beside the drawing]]></one:T></one:OE></one:OEChildren></one:Outline><one:InkDrawing lastModifiedTime="2026-09-13T08:12:59.000Z" objectID="{A013EA2B-3C74-0FE2-0325-A02BD639D5F9}{1}{B0}"><one:Position x="299.9905395507812" y="119.9905471801758" z="1"/><one:Size width="60.03781127929687" height="60.03779220581055"/><one:Data>AM8CHQSiAaIBAWAqABofi0JwRYR1gL7QRdkE+oeVMvLsF0G4wBa/8yv0et67E4vlXrNInJuhJVq3
3URK/7HHMzCKxQYkOuxMs7nqhWM9UiuaXxU+PBvi60uGbIsRmbacNslhJmh1OQDQGbBACEQZIEEUj
4RiMJSBBE/wFFI0YjBQgLZU9mZ2hkaRkUMggAgB4CIeLiQTMIAPAQAovF4kFkAxVGAEAKXAWH8gln
5jCj7wnvCe8IAh/B8h4Pke8I7wnvCQAUURgBAAAAJBAUURgAAAAASABEgNO2fBK2iXEeJsDGBngJF
6LQoAESCAd0ywV0PdAQMVRgBACj9AIm9GCC70WAqACQEKTAIPUq7GcA5CJYzgBRRGAIAAAAkEBRRG
7AAAAABIAESDm2ofXdOgLSJUWT/x4VvZtCgARIIB3TLBXQ90BAxVGAEAKP0Aib0YILvRYCoA=</one:Data></one:InkDrawing></one:Page>
corpus/page-copy/cold/read/page-015.navigation.json created+13
......@@ -0,0 +1,13 @@
1{
2 "exit": 0,
3 "stdout": "",
4 "stderr": "",
5 "w": 800,
6 "h": 600,
7 "error": null,
8 "win": {
9 "title": "A notebook created in Rust. - Microsoft OneNote",
10 "class": "Framework::CFrame",
11 "dialog": false
12 }
13}
\ No newline at end of file
corpus/page-copy/cold/read/page-015.png created
Binary files /dev/null and b/corpus/page-copy/cold/read/page-015.png differ
corpus/page-copy/cold/read/page-015.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{EF547C09-87EA-0A35-039B-F5512549E931}{1}{B0}" name="A notebook created in Rust." dateTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:14:27.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:13:00.000Z" lastModifiedTime="2026-09-13T08:13:00.000Z" objectID="{EF547C09-87EA-0A35-039B-F5512549E931}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[A notebook created in Rust.]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{B7774BCB-9107-00A0-2BFE-95DC3CB2134F}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="191.1661224365234" height="13.4277172088623"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T08:13:01.000Z" lastModifiedTime="2026-09-13T08:13:01.000Z" objectID="{C3848036-370C-04C5-0022-5090B87608DD}{1}{B0}" alignment="left"><one:T><![CDATA[A notebook created in Rust.]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/page-016.navigation.json created+13
......@@ -0,0 +1,13 @@
1{
2 "exit": 0,
3 "stdout": "",
4 "stderr": "",
5 "w": 800,
6 "h": 600,
7 "error": null,
8 "win": {
9 "title": "Before the table - Microsoft OneNote",
10 "class": "Framework::CFrame",
11 "dialog": false
12 }
13}
\ No newline at end of file
corpus/page-copy/cold/read/page-016.png created
Binary files /dev/null and b/corpus/page-copy/cold/read/page-016.png differ
corpus/page-copy/cold/read/page-016.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{FBBA4589-4114-0DBB-1DDE-9AEBE04435E8}{1}{B0}" name="Before the table" dateTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:14:26.000Z" pageLevel="1" style="font-family:Calibri;font-size:11.0pt" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Copier" lastModifiedBy="Copier" creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{FBBA4589-4114-0DBB-1DDE-9AEBE04435E8}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Before the table]]></one:T></one:OE></one:Title><one:Outline author="Copier" lastModifiedBy="Copier" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{B66EC4E0-90E0-065D-16BD-8AE6D17D38E2}{1}{B0}"><one:Position x="36.0" y="36.0" z="0"/><one:Size width="395.1299438476562" height="67.21086883544922"/><one:Indents><one:Indent level="0" indent="0.0"/></one:Indents><one:OEChildren><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{D00B3AB9-E98D-02AC-00A5-64F7F0B73D24}{1}{B0}" alignment="left"><one:T><![CDATA[Before the table]]></one:T></one:OE><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{A910B5E4-106E-091B-042B-85260A415D85}{1}{B0}" alignment="left"><one:Table bordersVisible="true" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{E2111011-156E-0E62-3045-C3CA9B0171B1}{1}{B0}"><one:Columns><one:Column index="0" width="144.0" isLocked="true"/><one:Column index="1" width="216.0" isLocked="true"/></one:Columns><one:Row objectID="{EFFCB8A1-87E0-0D1C-2007-873484353285}{1}{B0}" lastModifiedTime="2026-09-13T08:12:55.000Z"><one:Cell lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{58537E0F-3889-000A-30F5-5B63A4AEDDF4}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{766E8FDE-7B1E-0BE1-2EA2-786315A5EE3A}{1}{B0}" alignment="left"><one:T><![CDATA[Name]]></one:T></one:OE></one:OEChildren></one:Cell><one:Cell lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{33808FC6-C25F-040B-157F-8170CE036733}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{90D3178B-5FBE-03CD-3CC8-4D2F6E8B7FD3}{1}{B0}" alignment="left"><one:T><![CDATA[Value]]></one:T></one:OE></one:OEChildren></one:Cell></one:Row><one:Row objectID="{EA57AB8A-1061-0815-135C-39D97AF028C6}{1}{B0}" lastModifiedTime="2026-09-13T08:12:55.000Z"><one:Cell lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{92B2BEB0-1EE8-0D4A-1D27-79EC8DB2F9A2}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{DCEBCF8B-F7DA-0C20-0F76-44AC9B43F901}{1}{B0}" alignment="left"><one:T><![CDATA[Rust &#129408;]]></one:T></one:OE></one:OEChildren></one:Cell><one:Cell lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{71E65FA6-5919-0FAD-16C0-ADD201204FEE}{1}{B0}"><one:OEChildren><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{A457D70F-1E86-09AC-0205-D8DFEA8EEC54}{1}{B0}" alignment="left"><one:T><![CDATA[Written natively]]></one:T></one:OE></one:OEChildren></one:Cell></one:Row></one:Table></one:OE><one:OE creationTime="2026-09-13T08:12:55.000Z" lastModifiedTime="2026-09-13T08:12:55.000Z" objectID="{534343F8-0718-0974-08DF-524AD8D8860E}{1}{B0}" alignment="left"><one:T><![CDATA[After the table]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-copy/cold/read/payloads.json+2-2
......@@ -2,9 +2,9 @@
22 {
33 "sha256": "b20a14e044e33eac39b4665e7d79813b8a3672dbbd27ed9d2e4ac866c13ec4b6",
44 "name": "notes 🦀.txt",
5 "object": "{03AD9394-425B-0B9C-0D27-CA384DFFCEBF}{1}{B0}",
5 "object": "{9E89195D-B7EC-0AC4-34FD-F47D633F0533}{1}{B0}",
66 "kind": "InsertedFile",
7 "page": "{C12C0ECF-DDF8-0A21-11BE-3074429542E0}{1}{B0}",
7 "page": "{62E12C49-D5FE-0850-17D5-B4DC95B736E9}{1}{B0}",
88 "bytes": 28
99 }
1010]
\ No newline at end of file
corpus/page-copy/cold/run.json+1-1
......@@ -1,6 +1,6 @@
11{
22 "notebook": "/private/tmp/m4/copy",
3 "expected_pages": 9,
3 "expected_pages": 17,
44 "author": null,
55 "author_timeout_seconds": 600,
66 "inspect": false,
corpus/page-copy/cold/source.json+8-8
......@@ -2,19 +2,19 @@
22 {
33 "path": "Open Notebook.onetoc2",
44 "bytes": 1604,
5 "sha256": "bf856a7700054971543fb890257cba327dfd35ef6e5438a41483490c4e06407b",
6 "mtime_ns": 1789284797191547350
5 "sha256": "acb0747c250f7bebed1e90b18d5dbbf8c32731f9287571b1e732681921fd323a",
6 "mtime_ns": 1789287183577857848
77 },
88 {
99 "path": "copies.one",
10 "bytes": 91008,
11 "sha256": "8f6c9b66379c4bf6730e281d8363737d88fbe1c521a62fd4d054f735b0505cc7",
12 "mtime_ns": 1789284797187906252
10 "bytes": 185400,
11 "sha256": "dcd7c226d86477adc1ad2f8da8a408ffa2b993b372517ab8d464e5746a971aac",
12 "mtime_ns": 1789287183575141938
1313 },
1414 {
1515 "path": "expected-count.txt",
16 "bytes": 1,
17 "sha256": "19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7",
18 "mtime_ns": 1789284797191633183
16 "bytes": 2,
17 "sha256": "4523540f1504cd17100c4835e85b7eefd49911580f8efff0599a8f283be6b9e3",
18 "mtime_ns": 1789287183577930514
1919 }
2020]
crates/notebook/README.md+5-2
......@@ -334,8 +334,11 @@ metadata; a deleted section moves into `OneNote_RecycleBin`, a group with its
334334own TOC. Every created, renamed or moved file is placed with
335335`onestore::place_file`, which sets the header's ancestor to the parent TOC's
336336identity and the name CRC OneNote checks on open; a file without them is
337re-identified and listed anew. These operate on the mounted directory;
338the SMB transport has no create, rename or delete.
337re-identified and listed anew. They run over `Storage`: a mounted directory
338(`Notebook::open`) or an SMB share (`Notebook::open_smb` with a
339`smb::Client`, which gained create, directory creation, rename, delete and
340header placement under native writer coordination); `tools/test_smb_structure.py
341VM OUTPUT` drives them against a disposable Samba lab VM.
339342
340343`Notebook::find_page(url)` resolves a stored internal link to a section path
341344and page space by identity: the linked section first, then every readable
crates/notebook/src/session.rs+303-114
......@@ -66,9 +66,195 @@ fn entries(folder: &discover::Folder) -> Entries {
6666 out
6767}
6868
69/// A notebook directory and the cache directory holding its section replicas.
69/// Where a notebook's files live: a mounted directory or an SMB share. Paths are catalog
70/// paths, `/`-separated and relative to the notebook root.
71pub trait Storage: Send + Sync {
72 fn discover(&self, limits: discover::Limits) -> Result<discover::Folder>;
73 fn exists(&self, path: &str) -> bool;
74 fn read(&self, path: &str) -> Result<Vec<u8>>;
75 /// Creates a file holding `bytes`; an existing file is an error.
76 fn create(&self, path: &str, bytes: &[u8]) -> Result<()>;
77 fn create_directory(&self, path: &str) -> Result<()>;
78 /// Renames or moves a file or directory; an existing target is an error.
79 fn rename(&self, from: &str, to: &str) -> Result<()>;
80 /// Names a section or TOC file for its notebook, as `onestore::place`.
81 fn place(&self, path: &str, ancestor: [u8; 16], name: &str) -> Result<()>;
82 fn commit(&self, path: &str, edit: &PreparedEdit<'_>) -> Result<()>;
83 fn set_property(
84 &self,
85 path: &str,
86 source: &[u8],
87 space: ExGuid,
88 object: ExGuid,
89 property: u32,
90 value: &[u8],
91 ) -> Result<()>;
92}
93
94/// A mounted notebook directory.
95struct Directory(PathBuf);
96
97impl Directory {
98 fn path(&self, relative: &str) -> PathBuf {
99 if relative.is_empty() {
100 self.0.clone()
101 } else {
102 self.0.join(relative)
103 }
104 }
105}
106
107impl Storage for Directory {
108 fn discover(&self, limits: discover::Limits) -> Result<discover::Folder> {
109 Ok(discover::discover(
110 &mut discover::Local::open(&self.0)?,
111 limits,
112 )?)
113 }
114
115 fn exists(&self, path: &str) -> bool {
116 self.path(path).exists()
117 }
118
119 fn read(&self, path: &str) -> Result<Vec<u8>> {
120 Ok(onestore::read_file(self.path(path))?)
121 }
122
123 fn create(&self, path: &str, bytes: &[u8]) -> Result<()> {
124 std::fs::File::create_new(self.path(path))?.write_all(bytes)?;
125 Ok(())
126 }
127
128 fn create_directory(&self, path: &str) -> Result<()> {
129 Ok(std::fs::create_dir(self.path(path))?)
130 }
131
132 fn rename(&self, from: &str, to: &str) -> Result<()> {
133 Ok(std::fs::rename(self.path(from), self.path(to))?)
134 }
135
136 fn place(&self, path: &str, ancestor: [u8; 16], name: &str) -> Result<()> {
137 Ok(onestore::place_file(self.path(path), ancestor, name)?)
138 }
139
140 fn commit(&self, path: &str, edit: &PreparedEdit<'_>) -> Result<()> {
141 Ok(edit.commit_file(self.path(path))?)
142 }
143
144 fn set_property(
145 &self,
146 path: &str,
147 source: &[u8],
148 space: ExGuid,
149 object: ExGuid,
150 property: u32,
151 value: &[u8],
152 ) -> Result<()> {
153 Ok(onestore::commit_file_property(
154 self.path(path),
155 source,
156 space,
157 object,
158 property,
159 value,
160 )?)
161 }
162}
163
164/// A notebook directory on an SMB share, reached through the native-compatible client.
165#[cfg(feature = "smb")]
166pub struct Share {
167 client: Arc<crate::smb::Client>,
168 root: String,
169}
170
171#[cfg(feature = "smb")]
172impl Share {
173 fn path(&self, relative: &str) -> String {
174 match (self.root.is_empty(), relative.is_empty()) {
175 (_, true) => self.root.clone(),
176 (true, false) => relative.to_owned(),
177 (false, false) => format!("{}/{relative}", self.root),
178 }
179 }
180}
181
182#[cfg(feature = "smb")]
183impl Storage for Share {
184 fn discover(&self, limits: discover::Limits) -> Result<discover::Folder> {
185 Ok(discover::discover(
186 &mut discover::Smb::new(&self.client, &self.root)?,
187 limits,
188 )?)
189 }
190
191 fn exists(&self, path: &str) -> bool {
192 let (folder, name) = split(path);
193 self.client
194 .read_dir(&self.path(folder), 100_000)
195 .is_ok_and(|entries| entries.iter().any(|entry| entry.name == name))
196 }
197
198 fn read(&self, path: &str) -> Result<Vec<u8>> {
199 Ok(self
200 .client
201 .read_storage(&self.path(path), 256 * 1024 * 1024)?)
202 }
203
204 fn create(&self, path: &str, bytes: &[u8]) -> Result<()> {
205 Ok(self.client.create(&self.path(path), bytes)?)
206 }
207
208 fn create_directory(&self, path: &str) -> Result<()> {
209 Ok(self.client.create_directory(&self.path(path))?)
210 }
211
212 fn rename(&self, from: &str, to: &str) -> Result<()> {
213 Ok(self.client.rename(&self.path(from), &self.path(to))?)
214 }
215
216 fn place(&self, path: &str, ancestor: [u8; 16], name: &str) -> Result<()> {
217 Ok(self.client.place(&self.path(path), ancestor, name)?)
218 }
219
220 fn commit(&self, path: &str, edit: &PreparedEdit<'_>) -> Result<()> {
221 Ok(self.client.commit_prepared(&self.path(path), edit)?)
222 }
223
224 fn set_property(
225 &self,
226 path: &str,
227 source: &[u8],
228 space: ExGuid,
229 object: ExGuid,
230 property: u32,
231 value: &[u8],
232 ) -> Result<()> {
233 Ok(self.client.commit_property_bytes(
234 &self.path(path),
235 source,
236 space,
237 object,
238 property,
239 value,
240 )?)
241 }
242}
243
244const LIMITS: discover::Limits = discover::Limits {
245 entries: 100_000,
246 bytes_per_file: 256 * 1024 * 1024,
247 depth: 64,
248};
249
250const TOC: &str = "Open Notebook.onetoc2";
251const RECYCLE_BIN: &str = "OneNote_RecycleBin";
252
253/// A notebook's files and the cache directory holding its section replicas.
70254pub struct Notebook {
71 root: PathBuf,
255 storage: Box<dyn Storage>,
256 /// The mounted directory, when sections open through local replicas.
257 root: Option<PathBuf>,
72258 cache: PathBuf,
73259 catalog: discover::Folder,
74260}
......@@ -76,17 +262,31 @@ pub struct Notebook {
76262impl Notebook {
77263 pub fn open(root: impl AsRef<Path>, cache: impl AsRef<Path>) -> Result<Self> {
78264 let root = root.as_ref().canonicalize()?;
265 Self::with(Box::new(Directory(root.clone())), Some(root), cache)
266 }
267
268 /// Opens the notebook at `root` on the share `client` is connected to. Sections open
269 /// through `Section::resume_smb` with the catalog's paths.
270 #[cfg(feature = "smb")]
271 pub fn open_smb(
272 client: Arc<crate::smb::Client>,
273 root: &str,
274 cache: impl AsRef<Path>,
275 ) -> Result<Self> {
276 let root = root.replace('\\', "/");
277 Self::with(Box::new(Share { client, root }), None, cache)
278 }
279
280 fn with(
281 storage: Box<dyn Storage>,
282 root: Option<PathBuf>,
283 cache: impl AsRef<Path>,
284 ) -> Result<Self> {
79285 let cache = cache.as_ref().to_path_buf();
80286 std::fs::create_dir_all(&cache)?;
81 let catalog = discover::discover(
82 &mut discover::Local::open(&root)?,
83 discover::Limits {
84 entries: 100_000,
85 bytes_per_file: 256 * 1024 * 1024,
86 depth: 64,
87 },
88 )?;
287 let catalog = storage.discover(LIMITS)?;
89288 Ok(Self {
289 storage,
90290 root,
91291 cache,
92292 catalog,
......@@ -97,18 +297,11 @@ impl Notebook {
97297 &self.catalog
98298 }
99299
100 /// Rereads the notebook directory and reports what changed since the last catalog,
101 /// keyed by file identity so a renamed or moved section stays the same section. A
102 /// failed read keeps the previous catalog: an unreachable notebook is not an empty one.
300 /// Rereads the notebook and reports what changed since the last catalog, keyed by
301 /// file identity so a renamed or moved section stays the same section. A failed read
302 /// keeps the previous catalog: an unreachable notebook is not an empty one.
103303 pub fn refresh(&mut self) -> Result<Vec<Change>> {
104 let catalog = discover::discover(
105 &mut discover::Local::open(&self.root)?,
106 discover::Limits {
107 entries: 100_000,
108 bytes_per_file: 256 * 1024 * 1024,
109 depth: 64,
110 },
111 )?;
304 let catalog = self.storage.discover(LIMITS)?;
112305 let (before, before_orders) = entries(&self.catalog);
113306 let (after, after_orders) = entries(&catalog);
114307 let mut changes = Vec::new();
......@@ -158,28 +351,27 @@ impl Notebook {
158351 Err(io::Error::from(io::ErrorKind::NotFound).into())
159352 }
160353
161 fn directory(&self, path: &str) -> Result<PathBuf> {
162 let directory = if path.is_empty() {
163 self.root.clone()
164 } else {
165 self.root.join(path).canonicalize()?
166 };
167 if !directory.starts_with(&self.root) || !directory.is_dir() {
168 return Err(io::Error::from(io::ErrorKind::PermissionDenied).into());
354 /// A catalog section's path, refusing paths the catalog does not list.
355 fn section_path(&self, path: &str) -> Result<&discover::Section> {
356 let mut folders = vec![&self.catalog];
357 while let Some(folder) = folders.pop() {
358 if let Some(section) = folder.sections.iter().find(|section| section.path == path) {
359 return Ok(section);
360 }
361 folders.extend(&folder.groups);
169362 }
170 Ok(directory)
363 Err(io::Error::from(io::ErrorKind::NotFound).into())
171364 }
172365
173366 /// A folder's TOC path and file identity, creating the TOC when the folder has none
174367 /// (OneNote names it `Open Notebook.onetoc2`).
175 fn toc(&self, folder: &str) -> Result<(PathBuf, [u8; 16])> {
176 let directory = self.directory(folder)?;
368 fn toc(&self, folder: &str) -> Result<(String, [u8; 16])> {
177369 match &self.folder(folder)?.toc {
178 Some(toc) => Ok((directory.join(&toc.filename), toc.file_id)),
370 Some(toc) => Ok((catalog_path(folder, &toc.filename), toc.file_id)),
179371 None => {
180 let path = directory.join("Open Notebook.onetoc2");
181 let bytes = onestore::create_table_of_contents("Open Notebook.onetoc2", &[])?;
182 std::fs::File::create_new(&path)?.write_all(&bytes)?;
372 let path = catalog_path(folder, TOC);
373 let bytes = onestore::create_table_of_contents(TOC, &[])?;
374 self.storage.create(&path, &bytes)?;
183375 Ok((path, onestore::Store::parse(&bytes)?.header.file_id))
184376 }
185377 }
......@@ -187,23 +379,21 @@ impl Notebook {
187379
188380 fn edit_toc(&self, folder: &str, edits: &[onestore::TocEdit]) -> Result<()> {
189381 let (toc, _) = self.toc(folder)?;
190 let source = onestore::read_file(&toc)?;
191 PreparedEdit::table_of_contents(&source, edits)?
192 .commit_file(&toc)
193 .map_err(|error| error.error)?;
194 Ok(())
382 let source = self.storage.read(&toc)?;
383 self.storage
384 .commit(&toc, &PreparedEdit::table_of_contents(&source, edits)?)
195385 }
196386
197387 /// Creates `name.one` in `folder` with one empty page and lists it last in the folder's
198388 /// TOC, as OneNote creates a section. Returns the new catalog path.
199389 pub fn create_section(&mut self, folder: &str, name: &str, author: &str) -> Result<String> {
200390 let filename = format!("{name}.one");
201 let directory = self.directory(folder)?;
391 self.folder(folder)?;
202392 let (_, ancestor) = self.toc(folder)?;
203393 let bytes = onestore::create_section(&filename, "", author)?;
204 let path = directory.join(&filename);
205 std::fs::File::create_new(&path)?.write_all(&bytes)?;
206 onestore::place_file(&path, ancestor, &filename)?;
394 let path = catalog_path(folder, &filename);
395 self.storage.create(&path, &bytes)?;
396 self.storage.place(&path, ancestor, &filename)?;
207397 let identity = onestore::Store::parse(&bytes)?.header.file_id;
208398 self.edit_toc(
209399 folder,
......@@ -214,22 +404,22 @@ impl Notebook {
214404 }],
215405 )?;
216406 self.refresh()?;
217 Ok(catalog_path(folder, &filename))
407 Ok(path)
218408 }
219409
220410 /// Creates a section group: a folder with its own TOC, listed last in the parent's TOC.
221411 pub fn create_group(&mut self, folder: &str, name: &str) -> Result<String> {
222 let directory = self.directory(folder)?;
412 self.folder(folder)?;
223413 if !component(name) {
224414 return Err(io::Error::from(io::ErrorKind::InvalidInput).into());
225415 }
226 let group = directory.join(name);
227416 let (_, ancestor) = self.toc(folder)?;
228 std::fs::create_dir(&group)?;
229 let bytes = onestore::create_table_of_contents("Open Notebook.onetoc2", &[])?;
230 let path = group.join("Open Notebook.onetoc2");
231 std::fs::File::create_new(&path)?.write_all(&bytes)?;
232 onestore::place_file(&path, ancestor, name)?;
417 let group = catalog_path(folder, name);
418 self.storage.create_directory(&group)?;
419 let bytes = onestore::create_table_of_contents(TOC, &[])?;
420 let path = catalog_path(&group, TOC);
421 self.storage.create(&path, &bytes)?;
422 self.storage.place(&path, ancestor, name)?;
233423 let identity = onestore::Store::parse(&bytes)?.header.file_id;
234424 self.edit_toc(
235425 folder,
......@@ -240,48 +430,46 @@ impl Notebook {
240430 }],
241431 )?;
242432 self.refresh()?;
243 Ok(catalog_path(folder, name))
433 Ok(group)
244434 }
245435
246 /// Renames a section or section group: the file or folder on disk and its TOC entry.
436 /// Renames a section or section group: the file or folder and its TOC entry.
247437 pub fn rename(&mut self, path: &str, name: &str) -> Result<String> {
248438 let (folder, entry) = split(path);
249 let directory = self.directory(folder)?;
250439 let (filename, identity) = self.entry(folder, entry)?;
251440 let target = if filename.to_ascii_lowercase().ends_with(".one") {
252441 format!("{name}.one")
253442 } else {
254443 name.to_owned()
255444 };
256 if !component(&target) || directory.join(&target).exists() {
445 let renamed = catalog_path(folder, &target);
446 if !component(&target) || self.storage.exists(&renamed) {
257447 return Err(io::Error::from(io::ErrorKind::AlreadyExists).into());
258448 }
259 std::fs::rename(directory.join(&filename), directory.join(&target))?;
449 self.storage
450 .rename(&catalog_path(folder, &filename), &renamed)?;
260451 let (_, ancestor) = self.toc(folder)?;
261452 let placed = if target.ends_with(".one") {
262 directory.join(&target)
453 renamed.clone()
263454 } else {
264 directory.join(&target).join("Open Notebook.onetoc2")
455 catalog_path(&renamed, TOC)
265456 };
266 onestore::place_file(placed, ancestor, &target)?;
457 self.storage.place(&placed, ancestor, &target)?;
267458 self.edit_toc(
268459 folder,
269460 &[onestore::TocEdit::Rename {
270461 identity,
271 filename: target.clone(),
462 filename: target,
272463 }],
273464 )?;
274465 self.refresh()?;
275 Ok(catalog_path(folder, &target))
466 Ok(renamed)
276467 }
277468
278469 /// Sets a section's colour (COLORREF) in its own metadata, where OneNote keeps it.
279470 pub fn set_section_color(&mut self, path: &str, color: Option<u32>) -> Result<()> {
280 let file = self.root.join(path).canonicalize()?;
281 if !file.starts_with(&self.root) {
282 return Err(io::Error::from(io::ErrorKind::PermissionDenied).into());
283 }
284 let source = onestore::read_file(&file)?;
471 let path = self.section_path(path)?.path.clone();
472 let source = self.storage.read(&path)?;
285473 let store = onestore::Store::parse(&source)?;
286474 let index = onestore::RevisionIndex::parse(&store)?;
287475 let document = Document::parse(&index)?;
......@@ -290,15 +478,14 @@ impl Notebook {
290478 .roots
291479 .get(&2)
292480 .ok_or_else(|| io::Error::from(io::ErrorKind::InvalidData))?;
293 onestore::commit_file_property(
294 &file,
481 self.storage.set_property(
482 &path,
295483 &source,
296484 document.root,
297485 metadata,
298486 0x14001cbe,
299487 &color.unwrap_or(0xffff_ffff).to_le_bytes(),
300 )
301 .map_err(|error| error.error)?;
488 )?;
302489 self.refresh()?;
303490 Ok(())
304491 }
......@@ -322,23 +509,23 @@ impl Notebook {
322509 /// the root TOC lists), and its own folder's TOC entry goes.
323510 pub fn delete(&mut self, path: &str) -> Result<()> {
324511 let (folder, entry) = split(path);
325 let directory = self.directory(folder)?;
326512 let (filename, identity) = self.entry(folder, entry)?;
327513 if !filename.to_ascii_lowercase().ends_with(".one") {
328514 return Err(io::Error::from(io::ErrorKind::InvalidInput).into());
329515 }
330 let bin = self.root.join("OneNote_RecycleBin");
331 let bin_toc = bin.join("Open Notebook.onetoc2");
332 if !bin_toc.exists() {
333 std::fs::create_dir_all(&bin)?;
334 let bytes = onestore::create_table_of_contents("Open Notebook.onetoc2", &[])?;
335 std::fs::File::create_new(&bin_toc)?.write_all(&bytes)?;
336 onestore::place_file(&bin_toc, self.toc("")?.1, "OneNote_RecycleBin")?;
516 let bin_toc = catalog_path(RECYCLE_BIN, TOC);
517 if !self.storage.exists(&bin_toc) {
518 if !self.storage.exists(RECYCLE_BIN) {
519 self.storage.create_directory(RECYCLE_BIN)?;
520 }
521 let bytes = onestore::create_table_of_contents(TOC, &[])?;
522 self.storage.create(&bin_toc, &bytes)?;
523 self.storage.place(&bin_toc, self.toc("")?.1, RECYCLE_BIN)?;
337524 let bin_identity = onestore::Store::parse(&bytes)?.header.file_id;
338525 self.edit_toc(
339526 "",
340527 &[onestore::TocEdit::Add {
341 filename: "OneNote_RecycleBin".into(),
528 filename: RECYCLE_BIN.into(),
342529 identity: bin_identity,
343530 group: true,
344531 }],
......@@ -346,28 +533,31 @@ impl Notebook {
346533 }
347534 let mut target = filename.clone();
348535 let mut attempt = 1;
349 while bin.join(&target).exists() {
536 while self.storage.exists(&catalog_path(RECYCLE_BIN, &target)) {
350537 attempt += 1;
351538 let (stem, extension) = filename.rsplit_once('.').unwrap_or((&filename, ""));
352539 target = format!("{stem} ({attempt}).{extension}");
353540 }
354 std::fs::rename(directory.join(&filename), bin.join(&target))?;
355 let source = onestore::read_file(&bin_toc)?;
356 onestore::place_file(
357 bin.join(&target),
541 let binned = catalog_path(RECYCLE_BIN, &target);
542 self.storage
543 .rename(&catalog_path(folder, &filename), &binned)?;
544 let source = self.storage.read(&bin_toc)?;
545 self.storage.place(
546 &binned,
358547 onestore::Store::parse(&source)?.header.file_id,
359548 &target,
360549 )?;
361 PreparedEdit::table_of_contents(
362 &source,
363 &[onestore::TocEdit::Add {
364 filename: target,
365 identity,
366 group: false,
367 }],
368 )?
369 .commit_file(&bin_toc)
370 .map_err(|error| error.error)?;
550 self.storage.commit(
551 &bin_toc,
552 &PreparedEdit::table_of_contents(
553 &source,
554 &[onestore::TocEdit::Add {
555 filename: target,
556 identity,
557 group: false,
558 }],
559 )?,
560 )?;
371561 self.edit_toc(folder, &[onestore::TocEdit::Remove { identity }])?;
372562 self.refresh().map(drop)
373563 }
......@@ -419,7 +609,7 @@ impl Notebook {
419609 .map(|section| (section.path.clone(), None)));
420610 };
421611 for section in sections {
422 let bytes = onestore::read_file(self.root.join(&section.path))?;
612 let bytes = self.storage.read(&section.path)?;
423613 let store = Store::parse(&bytes)?;
424614 let index = RevisionIndex::parse(&store)?;
425615 let document = Document::parse(&index)?;
......@@ -436,11 +626,8 @@ impl Notebook {
436626 /// written, and the decoded buffers go when the pages have been built.
437627 #[cfg(feature = "protected")]
438628 pub fn unlock(&self, path: &str, password: &str) -> Result<Vec<(ExGuid, Page)>> {
439 let file = self.root.join(path).canonicalize()?;
440 if !file.starts_with(&self.root) {
441 return Err(io::Error::from(io::ErrorKind::PermissionDenied).into());
442 }
443 let bytes = onestore::read_file(&file)?;
629 let path = self.section_path(path)?.path.clone();
630 let bytes = self.storage.read(&path)?;
444631 let store = Store::parse(&bytes)?;
445632 let index = RevisionIndex::parse(&store)?;
446633 let unlocked = onestore::protected::UnlockedSection::open(
......@@ -456,20 +643,22 @@ impl Notebook {
456643 .collect()
457644 }
458645
459 /// Opens a section by its catalog path.
646 /// Opens a section of a mounted notebook by its catalog path.
460647 pub fn section(&self, path: &str, notify: impl Fn() + Send + 'static) -> Result<Section> {
461 let mut folders = vec![&self.catalog];
462 while let Some(folder) = folders.pop() {
463 if folder.sections.iter().any(|section| section.path == path) {
464 let file = self.root.join(path).canonicalize()?;
465 if !file.starts_with(&self.root) {
466 return Err(io::Error::from(io::ErrorKind::PermissionDenied).into());
467 }
468 return Section::open(file, &self.cache, notify);
469 }
470 folders.extend(&folder.groups);
648 let path = self.section_path(path)?.path.clone();
649 let Some(root) = &self.root else {
650 return Err(io::Error::new(
651 io::ErrorKind::Unsupported,
652 "Sections on a share open through Section::resume_smb",
653 )
654 .into());
655 };
656 // A section replaced by a link out of the notebook is not the catalog's section.
657 let file = root.join(path).canonicalize()?;
658 if !file.starts_with(root) {
659 return Err(io::Error::from(io::ErrorKind::PermissionDenied).into());
471660 }
472 Err(io::Error::from(io::ErrorKind::NotFound).into())
661 Section::open(file, &self.cache, notify)
473662 }
474663}
475664
crates/notebook/src/smb/mod.rs+93-3
......@@ -13,6 +13,7 @@ use smb2::{
1313 lock::{LockElement, LockRequest, LockResponse},
1414 query_info::{InfoType, QueryInfoRequest, QueryInfoResponse},
1515 read::{ReadRequest, ReadResponse},
16 set_info::{SetInfoRequest, SetInfoResponse},
1617 write::{WriteRequest, WriteResponse},
1718 },
1819 pack::{Pack, ReadCursor, Unpack},
......@@ -180,6 +181,23 @@ impl Client {
180181 }
181182
182183 fn open_shared(&self, path: &str, write: bool, sharing: u32) -> io::Result<File<'_>> {
184 self.open_with(
185 path,
186 if write { 0xc0000000 } else { 0x80000000 },
187 sharing,
188 CreateDisposition::FileOpen,
189 0x42,
190 )
191 }
192
193 fn open_with(
194 &self,
195 path: &str,
196 access: u32,
197 sharing: u32,
198 disposition: CreateDisposition,
199 options: u32,
200 ) -> io::Result<File<'_>> {
183201 if path.is_empty() || path.contains('\0') || path.encode_utf16().count() > 32767 {
184202 return Err(io::ErrorKind::InvalidInput.into());
185203 }
......@@ -188,11 +206,11 @@ impl Client {
188206 CreateRequest {
189207 requested_oplock_level: OplockLevel::None,
190208 impersonation_level: ImpersonationLevel::Impersonation,
191 desired_access: FileAccessMask::new(if write { 0xc0000000 } else { 0x80000000 }),
209 desired_access: FileAccessMask::new(access),
192210 file_attributes: 0,
193211 share_access: ShareAccess(sharing),
194 create_disposition: CreateDisposition::FileOpen,
195 create_options: 0x42,
212 create_disposition: disposition,
213 create_options: options,
196214 name: smb2::encode_path(&path.replace('\\', "/")),
197215 create_contexts: Vec::new(),
198216 },
......@@ -203,6 +221,78 @@ impl Client {
203221 })
204222 }
205223
224 /// Creates a file holding `bytes`; an existing file is an error.
225 pub fn create(&self, path: &str, bytes: &[u8]) -> io::Result<()> {
226 let mut file = self.open_with(path, 0xc0000000, 0, CreateDisposition::FileCreate, 0x40)?;
227 let mut written = 0;
228 while written < bytes.len() {
229 let count = file.write_at(written as u64, &bytes[written..])?;
230 if count == 0 {
231 return Err(io::ErrorKind::WriteZero.into());
232 }
233 written += count;
234 }
235 file.flush()?;
236 file.close()
237 }
238
239 /// Creates a directory; an existing one is an error.
240 pub fn create_directory(&self, path: &str) -> io::Result<()> {
241 self.open_with(path, 0x80000000, 7, CreateDisposition::FileCreate, 0x1)?
242 .close()
243 }
244
245 /// Renames or moves a file or directory within the share; an existing target is an
246 /// error.
247 pub fn rename(&self, from: &str, to: &str) -> io::Result<()> {
248 if to.is_empty() || to.contains('\0') {
249 return Err(io::ErrorKind::InvalidInput.into());
250 }
251 let file = self.open_with(
252 from,
253 0x00010000 | 0x80000000,
254 7,
255 CreateDisposition::FileOpen,
256 0,
257 )?;
258 let name: Vec<u8> = to
259 .replace('/', "\\")
260 .encode_utf16()
261 .flat_map(u16::to_le_bytes)
262 .collect();
263 let mut buffer = vec![0; 16];
264 buffer.extend_from_slice(&u32::try_from(name.len()).unwrap().to_le_bytes());
265 buffer.extend_from_slice(&name);
266 let _: SetInfoResponse = self.request(
267 Command::SetInfo,
268 SetInfoRequest {
269 info_type: InfoType::File,
270 file_info_class: 10,
271 additional_information: 0,
272 file_id: file.id.ok_or(io::ErrorKind::InvalidInput)?,
273 buffer,
274 },
275 )?;
276 file.close()
277 }
278
279 /// Deletes a file or an empty directory.
280 pub fn delete(&self, path: &str) -> io::Result<()> {
281 self.open_with(path, 0x00010000, 7, CreateDisposition::FileOpen, 0x1000)?
282 .close()
283 }
284
285 /// Names a section or TOC file for its notebook (`onestore::place`) under native
286 /// writer coordination.
287 pub fn place(&self, path: &str, ancestor: [u8; 16], name: &str) -> Result<(), CommitError> {
288 self.commit(path, |file| {
289 onestore::place(file, ancestor, name).map_err(|error| CommitError {
290 state: CommitState::NotCommitted,
291 error,
292 })
293 })
294 }
295
206296 /// Reads a bounded external payload while denying concurrent writes and deletion.
207297 /// Empty files succeed; limits, sharing contention and failed close return no payload.
208298 pub fn read_asset(&self, path: &str, limit: usize) -> io::Result<Vec<u8>> {
crates/notebook/src/smb/tests.rs+99
......@@ -505,3 +505,102 @@ fn read_limits_respect_negotiation_and_available_credits() {
505505 }
506506 }
507507}
508
509/// Notebook structure over the share: sections and groups created, renamed, coloured,
510/// ordered and deleted through `Notebook::open_smb`, seen again by a fresh discovery.
511#[test]
512#[ignore = "requires an owned Samba share at ONESTORE_SMB_LAB"]
513fn live_structure() {
514 use crate::session::Notebook;
515 let client = std::sync::Arc::new(client());
516 let root = format!("structure-{}", std::process::id());
517 client.create_directory(&root).unwrap();
518 let first = onestore::create_section("First.one", "First page", "Author").unwrap();
519 client.create(&format!("{root}/First.one"), &first).unwrap();
520 let first_id = onestore::Store::parse(&first).unwrap().header.file_id;
521 let toc =
522 onestore::create_table_of_contents("Open Notebook.onetoc2", &[("First.one", first_id)])
523 .unwrap();
524 client
525 .create(&format!("{root}/Open Notebook.onetoc2"), &toc)
526 .unwrap();
527 let toc_id = onestore::Store::parse(&toc).unwrap().header.file_id;
528 client
529 .place(&format!("{root}/First.one"), toc_id, "First.one")
530 .unwrap();
531 let cache = tempfile::tempdir().unwrap();
532 let mut notebook =
533 Notebook::open_smb(std::sync::Arc::clone(&client), &root, cache.path()).unwrap();
534 assert_eq!(
535 notebook.create_section("", "Second", "Author").unwrap(),
536 "Second.one"
537 );
538 assert_eq!(notebook.create_group("", "Archive").unwrap(), "Archive");
539 assert_eq!(
540 notebook
541 .create_section("Archive", "Inner", "Author")
542 .unwrap(),
543 "Archive/Inner.one"
544 );
545 assert_eq!(
546 notebook.rename("Second.one", "Renamed").unwrap(),
547 "Renamed.one"
548 );
549 assert_eq!(notebook.rename("Archive", "Kept").unwrap(), "Kept");
550 notebook
551 .set_section_color("Renamed.one", Some(0x5ed7ff))
552 .unwrap();
553 notebook.reorder("", &["Kept", "Renamed.one"]).unwrap();
554 notebook.delete("First.one").unwrap();
555 let names = |folder: &crate::discover::Folder| {
556 (
557 folder
558 .sections
559 .iter()
560 .map(|s| s.path.clone())
561 .collect::<Vec<_>>(),
562 folder
563 .groups
564 .iter()
565 .map(|g| g.path.clone())
566 .collect::<Vec<_>>(),
567 )
568 };
569 let fresh = Notebook::open_smb(std::sync::Arc::clone(&client), &root, cache.path()).unwrap();
570 assert_eq!(
571 names(fresh.catalog()),
572 (
573 vec!["Renamed.one".to_owned()],
574 vec!["Kept".to_owned(), "OneNote_RecycleBin".to_owned()]
575 )
576 );
577 assert_eq!(
578 names(&fresh.catalog().groups[0]),
579 (vec!["Kept/Inner.one".to_owned()], vec![])
580 );
581 assert_eq!(
582 names(&fresh.catalog().groups[1]),
583 (vec!["OneNote_RecycleBin/First.one".to_owned()], vec![])
584 );
585 assert!(fresh.catalog().toc.as_ref().unwrap().unresolved.is_empty());
586 let renamed = client
587 .read_storage(&format!("{root}/Renamed.one"), 1 << 20)
588 .unwrap();
589 let header = onestore::Store::parse(&renamed).unwrap().header;
590 assert_eq!(header.ancestor, toc_id);
591 assert_eq!(header.name_crc, 0x6108912a);
592 assert!(fresh.section("Renamed.one", || {}).is_err());
593 for path in [
594 "Renamed.one",
595 "Kept/Inner.one",
596 "Kept/Open Notebook.onetoc2",
597 "Kept",
598 "OneNote_RecycleBin/First.one",
599 "OneNote_RecycleBin/Open Notebook.onetoc2",
600 "OneNote_RecycleBin",
601 "Open Notebook.onetoc2",
602 ] {
603 client.delete(&format!("{root}/{path}")).unwrap();
604 }
605 client.delete(&root).unwrap();
606}
crates/notebook/tests/copy.rs+25-4
......@@ -15,11 +15,12 @@ use std::{
1515};
1616
1717/// Pages the writer authored for other rows: text with an attachment and its icon, a
18/// table, an inserted picture, a page-level ink drawing, tags, lists, equations
18/// table, nested tables with cell subtrees, an inserted picture, a page-level ink drawing, tags, lists, equations
1919/// and paragraph formatting.
2020const SOURCES: &[&str] = &[
2121 "attachment-edit/icon/candidate/files.one",
2222 "table-edit/created/candidate/tables.one",
23 "table-edit/nested/candidate/synthetic.one",
2324 "picture-edit/inserted/candidate/pictures.one",
2425 "ink-edit/drawing/candidate/ink.one",
2526 "tag-edit/candidate/tags.one",
......@@ -64,8 +65,10 @@ fn shape(page: &Page) -> String {
6465 serde_json::Value::Object(fields) => {
6566 // The writer's canonical formatting: an unset flag is false and unset
6667 // spacing is zero.
67 fields.retain(|_, value| {
68 !value.is_null()
68 fields.retain(|key, value| {
69 // OneNote lays outlines out again on open.
70 key != "max_height"
71 && !value.is_null()
6972 && *value != serde_json::Value::Bool(false)
7073 && value.as_f64() != Some(0.0)
7174 });
......@@ -153,6 +156,7 @@ fn pages_copy_into_another_section_with_their_content_and_fresh_identities() {
153156 .unwrap();
154157 let section = Section::open(&file, &cache, || {}).unwrap();
155158 let mut expected = Vec::new();
159 let mut grouped = Vec::new();
156160 for source in SOURCES {
157161 let bytes = std::fs::read(
158162 Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/../../corpus")).join(source),
......@@ -166,7 +170,14 @@ fn pages_copy_into_another_section_with_their_content_and_fresh_identities() {
166170 {
167171 continue;
168172 }
169 let copy = page.copy().unwrap();
173 let copy = match page.copy() {
174 Ok(copy) => copy,
175 Err(error) if error.message == "Outline groups cannot be copied" => {
176 grouped.push(page.title.clone());
177 continue;
178 }
179 Err(error) => panic!("{source} {}: {error}", page.title),
180 };
170181 assert_ne!(copy.identity, page.identity);
171182 let space = section
172183 .import_page(&page, "Copier")
......@@ -175,6 +186,16 @@ fn pages_copy_into_another_section_with_their_content_and_fresh_identities() {
175186 }
176187 }
177188 assert!(expected.len() >= 8, "{} pages", expected.len());
189 // Outdenting leaves paragraphs at levels only an outline group carries.
190 assert_eq!(
191 grouped,
192 [
193 "Outdent first group",
194 "Delete only grouped subtree",
195 "Delete unindented sibling after group",
196 "Outdent child across indentation gap"
197 ]
198 );
178199 let deadline = Instant::now() + Duration::from_secs(120);
179200 while section
180201 .queue()
crates/onestore/README.md+2-2
......@@ -43,7 +43,7 @@ harness also accepts `--client-profile release`.
4343| `Object::file_reference`, `Store::file_data` | Identify internal/external payloads and read internal payload bytes |
4444| `document::Document`, `Revision::text_runs` | Interpret document objects and inherited text formatting while retaining unknown properties and revision identities |
4545| `Document::active`, `Document::pages_in`, `Revision::parents`, `RevisionIndex::active` | Resolve the active revision, the pages of a space and parent links without repeating the lookups |
46| `Page::copy` | The page's content under fresh identities for copying into another section, definitions and payloads included |
46| `Page::copy` | The page's content under fresh identities for copying into another section, definitions and payloads included; indent levels only an outline group carries refuse |
4747| `page::link::internal_link`, `page::link::parse_internal_link` | Build and read the `onenote:#…` URLs OneNote stores for links to sections, pages and paragraphs, by identity |
4848| `page::Page`, `page::Paragraph`, `page::Ink`, `page::Math` | Build an editable page model (title, outlines, paragraphs with coalesced text spans, tables, images, attachments, ink drawings and handwriting decoded to stroke polylines in page points) with stored identities; equations parse from their linear text and run data into a tree that renders the MathML OneNote exports; content outside the model is retained as `Unsupported` |
4949| `protected::UnlockedSection` (optional feature) | Own decoded buffers for explicit known-password inspection; clear those buffers on drop; derived document strings/exports remain caller-owned |
......@@ -53,7 +53,7 @@ harness also accepts `--client-profile release`.
5353| `PreparedEdit::delete_pages_permanently` | Remove explicit pages and their section references atomically while retaining stored revisions |
5454| `create_table_of_contents` | Create ordered section entries from filenames and file identities |
5555| `TocEdit`, `PreparedEdit::table_of_contents` | Add, rename, colour, order and remove a table of contents' section and group entries as one revision |
56| `place_file` | Name a file for its notebook as OneNote does on adoption (parent TOC identity and name CRC in the header), so OneNote keeps its identity |
56| `place`, `place_file` | Name a file for its notebook as OneNote does on adoption (parent TOC identity and name CRC in the header), so OneNote keeps its identity, on any `CommitIo` or under the filesystem adapter |
5757| `replace_property_bytes` | Append one scalar-property revision; preserve prior revisions and unrelated property values and references |
5858| `replace_text`, `commit_text`, `commit_file_text` | Replace a UTF-16 range across ordinary text runs; publish text, run boundaries and modification time together |
5959| `Insertion`, `PreparedEdit::insert` | Insert paragraphs into editable containers or positioned outlines into a page, retaining intent identities across rebases |
crates/onestore/src/commit.rs+18-14
......@@ -74,23 +74,27 @@ impl Drop for FileIo {
7474/// Places a file in its notebook the way OneNote does on adoption: the header's
7575/// `guidAncestor` becomes the parent table of contents' file identity and `crcName` the CRC
7676/// of `name` (a section's file name, a group's folder name). OneNote re-identifies a file
77/// whose header disagrees with its location, which orphans its TOC entry.
77/// whose header disagrees with its location, which orphans its TOC entry. The caller holds
78/// OneNote-compatible exclusion on `io`.
79pub fn place(io: &mut impl CommitIo, ancestor: [u8; 16], name: &str) -> io::Result<()> {
80 let mut header = [0; 1024];
81 if io.read_at(0, &mut header)? != header.len() {
82 return Err(io::Error::from(ErrorKind::UnexpectedEof));
83 }
84 crate::Header::parse(&header)
85 .map_err(|error| io::Error::new(ErrorKind::InvalidData, error.message))?;
86 let placement = crate::create::placement(ancestor, name);
87 if io.write_at(128, &placement)? != placement.len() {
88 return Err(io::Error::from(ErrorKind::WriteZero));
89 }
90 io.flush()
91}
92
93/// `place` under the conservative filesystem adapter's whole-file exclusion.
7894#[cfg(any(unix, windows))]
7995pub fn place_file(path: impl AsRef<Path>, ancestor: [u8; 16], name: &str) -> io::Result<()> {
8096 let mut io = FileIo::open(path, true)?;
81 let mut header = [0; 1024];
82 let result = (|| {
83 if io.read_at(0, &mut header)? != header.len() {
84 return Err(io::Error::from(ErrorKind::UnexpectedEof));
85 }
86 crate::Header::parse(&header)
87 .map_err(|error| io::Error::new(ErrorKind::InvalidData, error.message))?;
88 let placement = crate::create::placement(ancestor, name);
89 if io.write_at(128, &placement)? != placement.len() {
90 return Err(io::Error::from(ErrorKind::WriteZero));
91 }
92 io.flush()
93 })();
97 let result = place(&mut io, ancestor, name);
9498 let released = io.release();
9599 result?;
96100 released
crates/onestore/src/formatting.rs+3
......@@ -35,6 +35,8 @@ pub enum TextAttribute {
3535 Color(Option<[u8; 3]>),
3636 /// RGB, or None to clear highlighting.
3737 Highlight(Option<[u8; 3]>),
38 /// Windows language id of the run, such as 1033 for US English.
39 Language(u32),
3840 /// Hidden text, such as a hyperlink's field code.
3941 Hidden(bool),
4042 /// The run belongs to a hyperlink field.
......@@ -73,6 +75,7 @@ impl TextAttribute {
7375 }
7476 (0x10001c0b, ((*points * 2.0) as u16).to_le_bytes().to_vec())
7577 }
78 Self::Language(language) => (0x14001c3b, language.to_le_bytes().to_vec()),
7679 Self::Color(color) | Self::Highlight(color) => (
7780 if matches!(self, Self::Color(_)) {
7881 0x14001c0c
crates/onestore/src/lib.rs+1-1
......@@ -27,7 +27,7 @@ mod write;
2727
2828pub use commit::{
2929 CommitError, CommitIo, CommitState, PreparedEdit, commit_property_bytes, commit_text,
30 confirm_snapshot,
30 confirm_snapshot, place,
3131};
3232#[cfg(any(unix, windows))]
3333pub use commit::{
crates/onestore/src/page/mod.rs+27
......@@ -421,6 +421,33 @@ impl Page {
421421 let mut copy: Self =
422422 serde_json::from_value(value).map_err(|_| invalid("Page copy does not deserialize"))?;
423423 copy.identity = Some(crate::write::fresh_guid()?);
424 // A paragraph's indent level follows its parent chain; a level beyond that comes
425 // from an outline group, which the model does not hold.
426 fn levels(paragraphs: &[PageParagraph]) -> bool {
427 let by_id: BTreeMap<ExGuid, u32> = paragraphs.iter().map(|p| (p.id, p.level)).collect();
428 paragraphs.iter().all(|paragraph| {
429 let expected = match paragraph.parent {
430 Some(parent) => by_id.get(&parent).map_or(0, |level| level + 1),
431 None => 1,
432 };
433 paragraph.level == expected
434 && match &paragraph.content {
435 ParagraphContent::Table(table) => table
436 .rows
437 .iter()
438 .flat_map(|row| &row.cells)
439 .all(|cell| levels(&cell.paragraphs)),
440 _ => true,
441 }
442 })
443 }
444 let expressible = copy.objects.iter().all(|object| match object {
445 PageObject::Outline(outline) => levels(&outline.paragraphs),
446 _ => true,
447 });
448 if !expressible {
449 return Err(invalid("Outline groups cannot be copied"));
450 }
424451 Ok(copy)
425452 }
426453
crates/onestore/src/page/write.rs+55-7
......@@ -355,6 +355,7 @@ pub(crate) fn write_page(
355355 page: *page,
356356 author,
357357 alias: BTreeMap::new(),
358 built: BTreeSet::new(),
358359 };
359360 lowering.run(&before, after, &raw.objects.keys().copied().collect())?;
360361 if lowering.image == source {
......@@ -457,6 +458,8 @@ struct Lowering<'a> {
457458 author: &'a str,
458459 /// Model identities of new objects mapped to the identities the typed writers allocated.
459460 alias: BTreeMap<ExGuid, ExGuid>,
461 /// Tables whose structure this run has written.
462 built: BTreeSet<ExGuid>,
460463}
461464
462465impl Lowering<'_> {
......@@ -900,20 +903,48 @@ impl Lowering<'_> {
900903 collect_containers(&outline.paragraphs, &mut containers);
901904 }
902905 }
903 // Cells that do not exist yet receive their paragraphs once the table structure does.
906 // Cells that do not exist yet, and containers inside them, receive their
907 // paragraphs once the table structure does.
908 let new_cell = |id: &ExGuid| {
909 !(old.children.contains_key(id)
910 || new.paragraphs.contains_key(id)
911 || new.outlines.contains_key(id))
912 };
904913 let (existing, deferred): (Vec<ExGuid>, Vec<ExGuid>) =
905914 containers.into_iter().partition(|container| {
906 old.children.contains_key(container)
907 || new.paragraphs.contains_key(container)
908 || new.outlines.contains_key(container)
915 let mut at = *container;
916 loop {
917 if new_cell(&at) {
918 return false;
919 }
920 match new.container.get(&at) {
921 Some(parent) => at = *parent,
922 None => return true,
923 }
924 }
909925 });
910926 self.place_containers(old, new, placed, &existing)?;
911 self.edit_table_structure(old, new)?;
927 // Each round builds the tables whose holders exist and fills their cells, which
928 // may hold further new tables.
929 let mut pending = deferred;
930 loop {
931 self.edit_table_structure(old, new)?;
932 if pending.is_empty() {
933 break;
934 }
935 let (ready, waiting): (Vec<ExGuid>, Vec<ExGuid>) = pending
936 .into_iter()
937 .partition(|container| self.alias.contains_key(container));
938 if ready.is_empty() {
939 return Err(invalid("Table content has no table to hold it"));
940 }
941 self.place_containers(old, new, placed, &ready)?;
942 pending = waiting;
943 }
912944 self.edit_cells(old, new)?;
913945 self.edit_images(old, new)?;
914946 self.edit_ink_paragraphs(old, new)?;
915947 self.edit_attachments(old, new)?;
916 self.place_containers(old, new, placed, &deferred)?;
917948 Ok(())
918949 }
919950
......@@ -1577,6 +1608,13 @@ impl Lowering<'_> {
15771608 continue;
15781609 };
15791610 let previous = old_tables.get(&table.id).copied();
1611 // A table is built once its holder is placed, and only once.
1612 if !(old.paragraphs.contains_key(paragraph_id) || self.alias.contains_key(paragraph_id))
1613 || self.built.contains(&table.id)
1614 {
1615 continue;
1616 }
1617 self.built.insert(table.id);
15801618 let unchanged = previous.is_some_and(|previous| {
15811619 previous.columns == table.columns
15821620 && previous.borders == table.borders
......@@ -2450,6 +2488,9 @@ impl Lowering<'_> {
24502488 spacing!(space_before, 0x1400342e);
24512489 spacing!(space_after, 0x1400342f);
24522490 spacing!(line_spacing, 0x14003430);
2491 field!(language, value, {
2492 (0x14001c3b, value.to_le_bytes().to_vec())
2493 });
24532494 if values.is_empty() {
24542495 continue;
24552496 }
......@@ -2827,6 +2868,13 @@ fn attributes(current: &Format, target: &Format, fresh: bool) -> Result<Vec<Text
28272868 None => return Err(inherited()),
28282869 }
28292870 }
2871 if current.language != target.language {
2872 match target.language {
2873 Some(language) => out.push(TextAttribute::Language(language)),
2874 None if fresh => {}
2875 None => return Err(inherited()),
2876 }
2877 }
28302878 // An absent value and its stored default are the same formatting.
28312879 let flag = |a: Option<bool>, b: Option<bool>| a.unwrap_or(false) == b.unwrap_or(false);
28322880 let points = |a: Option<f32>, b: Option<f32>| a.unwrap_or(0.0) == b.unwrap_or(0.0);
......@@ -2840,7 +2888,7 @@ fn attributes(current: &Format, target: &Format, fresh: bool) -> Result<Vec<Text
28402888 && points(current.list_spacing, target.list_spacing);
28412889 if !same_rest {
28422890 return Err(invalid(
2843 "Fields, language and paragraph spacing cannot be edited through the page model",
2891 "Fields and paragraph spacing cannot be edited through the page model",
28442892 ));
28452893 }
28462894 Ok(out)
tools/test_smb_structure.py created+29
......@@ -0,0 +1,29 @@
1#!/usr/bin/env python3
2"""Run the notebook-structure lane against a disposable Linux lab VM's Samba share."""
3import argparse
4import os
5from pathlib import Path
6import subprocess
7import sys
8
9sys.path.insert(0, str(Path(__file__).resolve().parent / 'w7'))
10from linux_vm import load_instance
11
12
13def main():
14 parser = argparse.ArgumentParser(description=__doc__)
15 parser.add_argument('vm', help='An already running, caller-owned Linux lab VM')
16 parser.add_argument('output', type=Path)
17 args = parser.parse_args()
18 output = args.output.resolve()
19 output.mkdir(parents=True, exist_ok=False)
20 config = load_instance(args.vm)
21 env = dict(os.environ, ONESTORE_SMB_LAB=f'127.0.0.1:{config["samba_port"]}')
22 with (output / 'structure.log').open('w') as result:
23 subprocess.run(['cargo', 'test', '-p', 'notebook', '--features', 'smb', 'smb::tests::live_structure', '--', '--ignored', '--exact'],
24 env=env, stdout=result, stderr=result, check=True, timeout=600)
25 print('structure: passed', flush=True)
26
27
28if __name__ == '__main__':
29 main()