- A line change into a block of another style is a wrap only when the next
line starts within half a line below the last one; a line far above it
(the next column) starts a paragraph. The size compare treats NaN as
"not the same size".
- A smaller block must overlap a block's interior, not just touch its edge,
to stop the block being used as a hint.
- font_family drops only the part after the last hyphen, and only when it
names a style (Segoe-UI-Bold gives Segoe UI).
- text_extract's description and html_truncated doc now cover a page's own
copy caps and say that rect HTML is in line order.
- Parity: the new tests are evidence; column selection HTML is listed as
missing (plain text only).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
- Spaces HTML would collapse keep their width across runs, at a
paragraph's start and after a break.
- font_family returns the families to try: spaced, then as spelt
('Sim Sun','SimSun'); a hyphen splits only before a style word, so
MS-Gothic stays whole.
- clip_html reports its cut; empty paragraphs count against the cap;
the span cap is checked before a paragraph opens; ClipBuilder's
Default starts a paragraph; a negative size clamps to 1pt.
- RichCopy::truncated: a capped copy is marked, the clipboard then puts
plain text only, and text_extract sets html_truncated. No HTML for any
page after the shared budget runs out.
- A style change at a line end is a wrap, not a paragraph; the block
hint is skipped when a smaller block overlaps it; no editor reports
styles_incomplete.
- A column selection copies plain text only.
Each new test fails with its fix reverted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9
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
Copying selected page text now also puts an HTML fragment on the system
clipboard, so a paste into a word processor or mail client keeps
paragraphs, bold, italic, size, colour and font family. The plain text
is unchanged and stays on the clipboard as the alternative.
- export: clip.rs, the clipboard model (ClipText of paragraphs of
styled spans), its builder with caps (20 000 spans, 2 MiB of text,
16 MiB of HTML), font_family (subset tag and style suffixes off,
camel case spaced) and clip_html. Family names are reduced to
letters, digits, space, '-', '_' and '.', so a font name cannot leave
the CSS string; text goes through esc, which drops control
characters.
- engine: Document::rich_copy(page, text, glyphs). Glyphs (view space)
take the style of the reading block their centre lies in; blocks are
style-homogeneous. A line wrap inside a block is a space (none after
a hyphen), a change of block a new paragraph. Refused when the
document does not allow copying. compare.rs's display unit and
weight/slant inference are shared, not duplicated.
- automation: text_extract takes format "text" (default) or "html";
html adds each page's html and styles_incomplete, for the whole page
or only what rect takes. Other values are InvalidArgs.
- ui-egui: Copy of a run or column selection writes HTML plus the
plain text in one arboard set (desktop only); the web build and
Select All of the whole document stay plain text. last_copied_html
records what was produced, for tests.
- parity: view.copy-with-layout is partial; notes list what is missing
(RTF, underline/strike-through, tables, Select All, web, glyphs
outside reading blocks).
Formatting inference and the HTML serialiser are adapted from pdfcer
(MIT, same author) at 540b00ef1a405d1baa67c92f3858535037c7cde8.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqmHYx8FiWM5PcsoiErgp9