Summary
Saving escapes a ** written on its own line, where CommonMark needs three or more markers to open a thematic break. The line is literal text as written and as escaped, so the document is unchanged, but the file gains two backslashes the author did not write. corpus/commonmark/blocks.md carries the line under the heading Too few or unsupported markers remain text, which is the property being measured.
Steps to reproduce
- Open a document whose own line holds
**.
- Save it without editing.
- Read the file.
Expected behavior
**, unchanged. Two markers cannot open a thematic break, so nothing needs holding literal, as ++ + two lines below it already stays bare.
Actual behavior
Measured against 8bc36754 by driving the editor mount used by the plugin tests, on corpus/commonmark/blocks.md line 18.
Related context
Done when
Notes, logs, screenshots
Diagnosis
opensBlockConstruct in src/features/editor/utils/markdownText.ts tests the line's character class without its length:
const thematicBreak = THEMATIC_BREAK_PATTERNS[run.character].test(line);
THEMATIC_BREAK_PATTERNS is { "*": /^[*\t ]*$/u, _: /^[_\t ]*$/u }, which ** satisfies, so a run too short to open the construct is treated as one that could and keeps its escape. The tilde branch a few lines above already makes the length check this pattern omits, returning run.end - run.start >= 3.
An underscore run reaches the same check through the _ pattern and behaves identically, measured against 8bc36754: _ is written \_ and __ is written \_\_. The length test that relaxes ** relaxes both, so this issue covers the underscore as well as the asterisk.
A single * is not affected, because nothing escapes it in the first place and these passes only remove escapes.
Out of scope
- The
-- two lines below in the same file, which is also escaped on save. A hyphen is not in ATTENTION_CHARACTERS, so it never reaches this check and is held by a different path whose cause is not established.
- The escaped backticks under
Block structure takes precedence over inline parsing in the same file, which are a code span crossing a list-item boundary rather than a block marker.
Summary
Saving escapes a
**written on its own line, where CommonMark needs three or more markers to open a thematic break. The line is literal text as written and as escaped, so the document is unchanged, but the file gains two backslashes the author did not write.corpus/commonmark/blocks.mdcarries the line under the headingToo few or unsupported markers remain text, which is the property being measured.Steps to reproduce
**.Expected behavior
**, unchanged. Two markers cannot open a thematic break, so nothing needs holding literal, as++ +two lines below it already stays bare.Actual behavior
Measured against
8bc36754by driving the editor mount used by the plugin tests, oncorpus/commonmark/blocks.mdline 18.**\*\*Related context
docs/decisions.mdunderPreserve the form a file was written in;corpus/commonmark/blocks.mdunderToo few or unsupported markers remain text.Done when
***,---, and_ _ _still round-trip as thematic breaks.Notes, logs, screenshots
Diagnosis
opensBlockConstructinsrc/features/editor/utils/markdownText.tstests the line's character class without its length:THEMATIC_BREAK_PATTERNSis{ "*": /^[*\t ]*$/u, _: /^[_\t ]*$/u }, which**satisfies, so a run too short to open the construct is treated as one that could and keeps its escape. The tilde branch a few lines above already makes the length check this pattern omits, returningrun.end - run.start >= 3.An underscore run reaches the same check through the
_pattern and behaves identically, measured against8bc36754:_is written\_and__is written\_\_. The length test that relaxes**relaxes both, so this issue covers the underscore as well as the asterisk.A single
*is not affected, because nothing escapes it in the first place and these passes only remove escapes.Out of scope
--two lines below in the same file, which is also escaped on save. A hyphen is not inATTENTION_CHARACTERS, so it never reaches this check and is held by a different path whose cause is not established.Block structure takes precedence over inline parsingin the same file, which are a code span crossing a list-item boundary rather than a block marker.