Summary
Saving inserts a blank line between blocks the author wrote adjacent. CommonMark does not require the blank line wherever the second block already interrupts the first, so the file grows lines the author did not write and the document is unchanged.
This is the most widespread of the classes under #251 by file count: it appears in five of the sixteen scoped corpus files, and it is the only remaining difference in corpus/commonmark/html.md.
Steps to reproduce
- Open a document containing a paragraph line followed immediately by
<section class="garden"> with no blank line between them.
- Save it without editing.
- Read the file.
Expected behavior
The two lines stay adjacent.
Actual behavior
Measured against 83e12b19 by driving the editor mount used by the plugin tests. Each row is a pair of adjacent lines that gains a blank line between them:
| Document |
File |
| paragraph text followed by a block-level tag |
corpus/commonmark/html.md |
[same]: /first followed by [same]: /second |
corpus/commonmark/blocks.md |
[forward reference]: /forward "Forward title" followed by [never referenced]: /unused "Unused title" |
corpus/commonmark/blocks.md |
a paragraph followed by the *** that interrupts it |
corpus/commonmark/blocks.md |
| consecutive ATX headings |
corpus/commonmark/blocks.md |
| a quoted paragraph followed by a heading outside the quote |
corpus/commonmark/lists-and-blockquotes.md |
| a paragraph followed by the list that interrupts it |
corpus/commonmark/lists-and-blockquotes.md |
| a table followed by the blockquote that terminates it |
corpus/gfm/tables.md |
| a paragraph followed by an unclosed fence |
corpus/commonmark/code.md |
Every one of these is a case where the second block interrupts the first without needing a blank line, which is why the corpus carries them: the headings above them state that the interruption is the behavior under test.
Related context
Done when
Notes, logs, screenshots
corpus/commonmark/html.md is the cheapest place to start: it has exactly one difference, this one, and fixing it moves a fifth file to byte identity.
Implementation direction
serializeMarkdownRoot in the handlers registered on remarkStringifyOptionsCtx already assembles the document and resolves deferred decisions against the assembled text, which is the seam where the separator between two blocks is decidable — it needs both blocks, which no single node handler has.
Interacts with #198: a blank-line run is already carried as a blank paragraph, so the fix must distinguish a separator the serializer adds from a blank line the author wrote, and must not reintroduce a blank paragraph where the author wrote none.
Out of scope
Summary
Saving inserts a blank line between blocks the author wrote adjacent. CommonMark does not require the blank line wherever the second block already interrupts the first, so the file grows lines the author did not write and the document is unchanged.
This is the most widespread of the classes under #251 by file count: it appears in five of the sixteen scoped corpus files, and it is the only remaining difference in
corpus/commonmark/html.md.Steps to reproduce
<section class="garden">with no blank line between them.Expected behavior
The two lines stay adjacent.
Actual behavior
Measured against
83e12b19by driving the editor mount used by the plugin tests. Each row is a pair of adjacent lines that gains a blank line between them:corpus/commonmark/html.md[same]: /firstfollowed by[same]: /secondcorpus/commonmark/blocks.md[forward reference]: /forward "Forward title"followed by[never referenced]: /unused "Unused title"corpus/commonmark/blocks.md***that interrupts itcorpus/commonmark/blocks.mdcorpus/commonmark/blocks.mdcorpus/commonmark/lists-and-blockquotes.mdcorpus/commonmark/lists-and-blockquotes.mdcorpus/gfm/tables.mdcorpus/commonmark/code.mdEvery one of these is a case where the second block interrupts the first without needing a blank line, which is why the corpus carries them: the headings above them state that the interruption is the behavior under test.
Related context
Scope; theNotessection of fix: preserve authored line breaks and represent blank paragraphs with blank lines #198, which records why blank lines carry a blank paragraph rather than<br />.Done when
corpus/commonmark/html.mdround-trips byte-identically, which this class alone should achieve for that file.corpus/commonmark/blocks.md,corpus/commonmark/code.md,corpus/commonmark/lists-and-blockquotes.md, andcorpus/gfm/tables.mdlose these differences.Notes, logs, screenshots
corpus/commonmark/html.mdis the cheapest place to start: it has exactly one difference, this one, and fixing it moves a fifth file to byte identity.Implementation direction
serializeMarkdownRootin the handlers registered onremarkStringifyOptionsCtxalready assembles the document and resolves deferred decisions against the assembled text, which is the seam where the separator between two blocks is decidable — it needs both blocks, which no single node handler has.Interacts with #198: a blank-line run is already carried as a blank paragraph, so the fix must distinguish a separator the serializer adds from a blank line the author wrote, and must not reintroduce a blank paragraph where the author wrote none.
Out of scope