Skip to content

The serializer escapes a hyphen run that cannot open a block where it sits #375

Description

@Azganoth

Summary

Saving escapes a -- at the start of a line, where no block a hyphen can open will form. Two hyphens are too few for a thematic break, a bullet marker is one hyphen followed by whitespace, and a setext underline needs a paragraph line directly above it inside the same block. The line is literal text as written and as escaped, so the file gains a backslash the author did not write and the document is unchanged.

corpus/commonmark/blocks.md carries the line under the heading Too few or unsupported markers remain text, which is the property being measured. The ++ + two lines below it already stays bare.

Steps to reproduce

  1. Open a document whose own line holds --.
  2. Save it without editing.
  3. Read the file.

Expected behavior

--, unchanged.

Actual behavior

Measured against 8bc36754 by driving the editor mount used by the plugin tests, on corpus/commonmark/blocks.md line 20.

Document Saved
-- \--
text / blank / -- -- still escaped
> -- > \--

The neighbouring cases are all left alone, which is what makes the escape inconsistent rather than a house style:

Document Saved
- unchanged
--- unchanged, a thematic break
+, ++ +, * unchanged
- x unchanged, a bullet list
a -- b unchanged, not at a line start
- -- unchanged, inside a list item

The last row is the sharpest: the same two hyphens are escaped at the start of a top-level line and inside a blockquote, but not inside a list item.

Related context

Done when

  • A hyphen run at a line start that can open no block is written without an escape, at top level and inside a blockquote.
  • A hyphen that can open one keeps what it needs: --- still writes a thematic break, - x still writes a bullet item, and a setext underline under a paragraph is still written so it reloads as a heading.
  • Regression coverage asserts the saved bytes and the document the saved file reopens as, since closure already holds and cannot catch this.

Notes, logs, screenshots

Diagnosis

No relaxation pass reaches a hyphen. relaxBlockMarkerEscapes branches only on #, the ordered-list markers, and |, and ATTENTION_CHARACTERS is *_~, so a hyphen never reaches opensBlockConstruct either. The escape state.safe emits is never revisited.

That check is the model for what a hyphen branch needs to answer, and it is more than the thematic break: a hyphen also opens a bullet item and, unlike an asterisk or an underscore, a setext underline. The setext case is the one a fix must not relax away, since dropping the escape there would change what the file reloads as rather than only how it is spelled.

Out of scope

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

BugSomething isn't working

Projects

  • Status
    In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions