Fixes R4.7 round 2: a heading change or split is parsed again and
refused as Misread when its text, formats or kind would change;
closing hashes and block openers are escaped at split ends; task
boxes below a marker stay; indented code is written from its value;
alerts unwrap past blank and lazy lines; delete counts every gone
opener.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Round-1 fixes for R4.7: a caret in heading marks splits at the text; a
split closes and reopens bold, italic and strike, refusing inside links,
code, math and HTML; a task's first text takes no block; retype keeps
task boxes and code indent and takes siblings past the list; an alert
in an item keeps the item's opener; paragraph-before moves a holder's
first text below its opener; delete keeps neighbors from joining; a
heading's text keeps closing hashes and block openers escaped; a heading
level is idempotent, as Typora's menu calls it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
MarkdownDocument::block runs a BlockCommand at the caret: heading
levels, paragraph, promote and demote; quote and list toggles;
rule, code, math, toc, footnote, link definition and front matter
inserts; empty paragraphs before and after; delete. Formats and
block commands share one runner off the UI thread; FormatRefusal
is now EditRefusal.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The format command never parses on the UI thread; refusals past the
size checks come by event. The document's at-once read returns to
128 KiB, so a visual opening between the cutoffs starts at the top.
Timing test takes web_time::Instant.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Unwrapping a style now runs the crossing check on the found node, so an
end in a nested link address or strike mark refuses. Clear keeps an
autolink's backslashes. Block lookups use a sorted search, so the walk
grows linearly. A long format refuses a second one as Busy and reports
refusals, a changed text and a shown preview through FormatRefused.
markdown-rs grows with the square of its nodes, so texts read at once
only up to 16 KiB.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Unwrap and merge check the original ends against marks and link
addresses. Blocks take text up to their end spaces; a cell between its
pipes. Clear also takes inline math's dollars, footnote brackets and
escape backslashes. Underline finds its <u> pair past other tags. Blank
lines split on CR too; a selection across blocks says Across. Past
128 KiB the toggle runs off the UI thread and lands only if text and
selection are unchanged; past the largest read it refuses (TooLong).
Clear and the document command move into format/.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
MarkdownDocument::format toggles bold, italic, code, strike, underline,
link and image at the selection, or clears every inline mark from the
blocks it touches, following Typora's toggleStyle: off inside the style,
wrap a selection, take the caret's word or write an empty pair. Code,
math, HTML and front matter refuse, as does a selection crossing a
block, a link or another mark. An open block keeps its field open.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Round 3 of R4.5 found five ways the reverse reading drifted from
markdown-rs: kept indents and marks were eaten as joins, autolink text
was decoded, table code kept its escaped pipes, decoded white space
could not join or drop, and C0/C1 numeric references kept their
controls. Matching now tries an equal character first, a drawn space
against any line end next, and drops white space decoded or not;
autolinks read as written, table cell code reads \| as |, and numeric
references follow markdown-rs. The reviewer's probes are regressions.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Each piece records how its source decodes: Markdown's escapes and
references for text, HTML's for an HTML block's runs, none for code
spans, cut as CommonMark cuts their end spaces. Matching runs from the
piece's end, so quote marks and indents at a line's start are never
taken for text, and an alert's text needs no moved position: alert()
takes no source again.
Lines split on LF, CRLF and CR alike; LineMap matches each drawn line
to the written line it ends once, so an HTML block maps in linear time
and a tab cut to spaces lands on the tab. A write-back refuses the
press when the pressed block's kind, text or drawing changed.
The hostile HTML test measures growth: a fixed 2 s budget failed under
the full suite's load on the old code too.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Each drawn character finds its written one, skipping only white
space, escapes and quote marks, so a press lands on the character
itself. Code, front matter and link definitions read back line for
line. An HTML block keeps each text run's source byte, and an alert
keeps its text past the marker; alert() now takes the source.
A secondary press refuses a target its write-back changed, and its
focus no longer opens an empty document. Run's element stack moves to
tree/stack.rs and the HTML-block reader to tree/html_block.rs.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Each drawn text piece keeps its written span, so a press maps back to a
source byte. A secondary press opens nothing: it moves the caret there and
emits DocumentEvent::Pointed with the block's kind, link, picture and
whether it lies in a table or code. Block nodes count from their own start.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The writer in ElyMark kept its own copy of the inline reading, which drifted
from the drawing. Reader goes public as MarkdownReader with block, inline,
note and label, and its blocks as MarkdownBlock. Shortcodes, InlineTag,
inline_tag and html_block_text close back to the tree; headings(text) goes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Shortcodes, inline_tag, html_block_text, alert, is_toc and headings are what
the drawing itself calls, so an export that calls them shows the same.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- The first `:name:`-shaped run in a text node decides for the whole node:
blank text or a space before it turns every shortcode, else none. Filtered
tags are text and do not split the node. Probed on GitHub's markdown API.
- `fieldset`, `menu` and the rest of HTML5's list end an open `p`.
- `CodeEditor` carries owner anchors through each edit; the document anchors
every heading it reads, and a TOC press goes where its anchor went.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
At the root a quote marked [!NOTE] and the rest, as GitHub's API reads it,
is an alert; a [toc] paragraph lists the headings and a press reveals one;
an HTML block shows its text with the inline tags, white space as a browser
lays it, scripts and styles dropped. The rule is 2px; bullets turn by depth.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A raw end tag ends the Markdown element of its name; an end tag pops every
element above its target and only formatting elements reopen, so mark, kbd
and del stop where the browser stops them; a new anchor ends the open one.
Emoji read after escapes and references, as GitHub's Markdown API shows.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>