M3: copy with formatting keeps one clipboard open and is tested through a stand-in

Review fixes for Copy with formatting.

- ui-egui: the HTML copy goes through one arboard Clipboard, created on
  first use and kept in the app (os_clipboard::with_kept, under the same
  process-wide lock), instead of a fresh one per copy. On X11 the copied
  data is served only while its Clipboard lives, so a fresh one dropped
  at once could leave nothing to paste without a clipboard manager. A
  failed create or set falls back to egui's plain-text copy.
- ui-egui: html_clipboard_override stands in for the system clipboard in
  tests. With the system clipboard on, Copy sets HTML and plain text in
  one set and emits no CopyText; when the set is refused it emits
  CopyText with the plain text. The HTML is built only when a clipboard
  will take it (system clipboard on, not the web build). The
  last_copied_html field is gone.
- export: clipboard HTML text is escaped in one pass and also drops C1
  controls, a bare carriage return and the bidirectional overrides and
  isolates. Font sizes are written within 1 to 1000 pt.
- engine: the glyph-to-block step budget is a parameter, tested; the copy
  says styles_incomplete only when matching actually ran out of steps.
- automation: text_extract format "html" has one 32 MiB HTML budget
  across all pages; a page past it gets none, and the result carries
  html_truncated. The tool description says so.
- parity: the new tests are evidence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
This commit is contained in:
KenM76andClaude Opus 5.5 committed 2026-11-04 15:51:57 -05:00
1 parent 352355ab77
commit a955373428
11 files changed
+255 -66

No files matched your search

+1 -1
View File
@@ -1574,7 +1574,7 @@ milestone = "M3"
status = "partial"
commands = ["edit.copy"]
tools = ["text_extract"]
evidence = ["crates/export/src/clip.rs::heading_body_and_coloured_span_keep_their_formatting", "crates/export/src/clip.rs::special_characters_are_escaped_and_cannot_leave_the_style", "crates/export/src/clip.rs::empty_and_huge_selections_are_bounded", "crates/engine/src/rich_copy.rs::copy_keeps_headings_body_and_colour_as_html", "crates/engine/src/rich_copy.rs::copy_with_formatting_is_refused_when_copying_is_withheld", "crates/automation/tests/it/automation.rs::text_extract_as_html_keeps_the_formatting", "crates/ui-egui/tests/it/text_select.rs::selected_text_copy_keeps_the_formatting_as_html", "crates/ui-egui/tests/it/text_select.rs::selected_text_copy_with_formatting_honours_permissions"]
evidence = ["crates/export/src/clip.rs::heading_body_and_coloured_span_keep_their_formatting", "crates/export/src/clip.rs::special_characters_are_escaped_and_cannot_leave_the_style", "crates/export/src/clip.rs::empty_and_huge_selections_are_bounded", "crates/export/src/clip.rs::invisible_controls_and_bidi_overrides_are_dropped", "crates/export/src/clip.rs::font_sizes_stay_within_range", "crates/engine/src/rich_copy.rs::copy_keeps_headings_body_and_colour_as_html", "crates/engine/src/rich_copy.rs::copy_with_formatting_is_refused_when_copying_is_withheld", "crates/engine/src/rich_copy.rs::running_out_of_match_steps_copies_the_rest_unstyled", "crates/automation/tests/it/automation.rs::text_extract_as_html_keeps_the_formatting", "crates/automation/src/tests.rs::text_extract_html_has_one_budget_across_pages", "crates/ui-egui/tests/it/text_select.rs::selected_text_copy_keeps_the_formatting_as_html", "crates/ui-egui/tests/it/text_select.rs::selected_text_copy_falls_back_to_plain_text_when_html_is_refused", "crates/ui-egui/tests/it/text_select.rs::selected_text_copy_with_formatting_honours_permissions"]
notes = "Copy of a page-text selection also puts HTML on the system clipboard (paragraphs, bold, italic, size, colour, font family; plain text as the alternative), and text_extract format html returns the same. Missing: RTF, underline and strike-through, tables, Select All of the whole document (plain text only), the web build (plain text only), and styles for glyphs outside the page's reading blocks (copied unstyled)"
[[feature]]