1# Rust hyperlink authoring
2
3`candidate/` is the page writer's output for
4`a_link_is_added_to_a_fresh_page_and_reads_back` in
5`crates/onestore/tests/page_links.rs`: on a section created in Rust, the
6paragraph "Read about Rust" gains a hyperlink the way OneNote stores one, a
7hidden field-code run `U+FDDF HYPERLINK "https://example.invalid/rust"` and
8the visible label "the Rust site", both flagged as hyperlink runs. The text
9and formatting writers treat such runs as ordinary text with flags; equations,
10embedded objects and runs with associated data stay refused.
11
12`cold/` is a fresh OneNote 2010 read: the paragraph text is
13`Read about Rust <a href="https://example.invalid/rust">the Rust site</a>`.
14`tools/test_link_edit.py` checks this without a VM. Regenerate with
15`ONESTORE_LINK_EXPORT` set to a new absolute directory while running the test,
16then cold-open it with `tools/native_runner.py OUTPUT COLD --expected-pages 1
17--collect-notebook`.
18
19## Internal links
20
21`native-links/` is OneNote 2010 adding links to a page, to a paragraph on it
22and to the section on the Rust-authored page above through the COM API
23(`tools/native/page-link.ps1`; `links.json` holds the `onenote:///…` URLs
24`GetHyperlinkToObject` returned, `update.xml` the submitted page). In
25`notebook/`, OneNote stored each as a `HYPERLINK` field code with the
26relative form `onenote:#Link%20target&section-id={section file identity}
27&page-id={page notebook-management identity}&end&base-path=<section path>`;
28a paragraph link ends with `&object-id={paragraph identity}&n` instead of
29`&end`, and a section link has neither title nor page. OneNote rewrote the
30target outline after linking, so its own paragraph link names an identity
31(`n` 28) the current outline no longer holds.
32
33`internal/candidate` is the writer's output for
34`a_page_links_to_another_page_and_its_paragraph` in
35`crates/onestore/tests/page_links.rs`: a section created in Rust with a
36second page, whose first page links to that page and to its first paragraph
37with URLs built by `onestore::page::link::internal_link`. `internal/cold` is
38its cold read with both links. Regenerate with
39`ONESTORE_INTERNAL_LINK_EXPORT` and cold-open with `--expected-pages 2`.
40
41## Typed links
42
43`native-typed/` is OneNote 2010 typing on the Rust-authored page above, driven by
44`tools/native_links.py` (`links.ahk` the AutoHotkey session, `links.png` the
45desktop afterwards). Each URL typed and ended by a space or Enter became a link
46of its own text, a hyperlink run with no field code and no label flag: `http`,
47`https`, `ftp`, `file`, `mailto`, `news` and `onenote` schemes, `www.` and
48`\\server\share` paths. Trailing punctuation and an unmatched closing bracket
49stay outside; `me@example.com` and `example.com` stay text. The Link dialog
50(Ctrl+K) on the word at the caret, on a selection and on nothing stored the
51address as typed (`example.net/x`, which the COM read shows as
52`http://example.net/x`) in a hidden field code before a label flagged as one,
53the address itself when the text was empty; text typed after a label is plain.
54Remove Link (Shift+F10, R) left the URL as plain text, its runs' link flag
55false. An interactive session on a copy showed the rest: a click on a link opens
56it at once, typing straight after a link of its own text extends it and its
57address, and Copy Link to Page puts
58`onenote:///<section path>#<title>&section-id={…}&page-id={…}&end` on the
59clipboard (`&object-id={…}&n` in place of `&end` for Copy Link to Paragraph),
60which pastes as a labelled link. `crates/canvas/src/editor/link.rs` replays
61the session through the editor and compares every paragraph's link runs.
62
63## Links and equations from the editor
64
65`editor/candidate` is the canvas editor's output for
66`crates/canvas/tests/links_equations.rs` on the internal-link section above:
67URLs typed and ended by a space or Enter, the Link dialog on a selection, on the
68word at the caret and on nothing, links to the other page and to a paragraph,
69Remove Link, and equations typed after Alt+= (one switched to Linear, one after
70text in its paragraph), all saved as the ops the editor recorded.
71`editor/cold` is its cold OneNote 2010 read: `tools/test_link_edit.py`
72compares it with the candidate and checks the links and MathML in
73`editor/expected.json`. OneNote's read opens an address without a scheme over
74http and links URL text again when it opens a page; its own section does the
75same after Remove Link (`native-typed/cold`, its cold read, shows `Gone
76ftp://h.example/f` linked again). Regenerate with
77`CANVAS_LINKS_EQUATIONS_EXPORT` set to a new directory, move `expected.json`
78beside the candidate, and cold-open with `--expected-pages 2 --screenshots`.