Summary
Saving rewrites every indented code block as a fenced block. The code survives, but the block changes shape, and the change is not confined to the block: fencing content that itself contains a backtick fence forces a longer outer fence, which rewrites the surrounding lines as well.
It happens at top level, inside a list item, and inside a blockquote.
Steps to reproduce
- Open a document containing a code block indented by four spaces.
- Save it without editing.
- Read the file.
Expected behavior
The block is written back as indented code.
Actual behavior
Measured against 83e12b19 by driving the editor mount used by the plugin tests.
Top level, in corpus/commonmark/code.md:
four spaces open the block
two further spaces stay in the content
saves as a ``` fenced block holding four spaces open the block and two further spaces stay in the content.
Inside a list item, in corpus/commonmark/lists-and-blockquotes.md, - five spaces changes the content indentation boundary saves as a bullet item whose content is a fenced block. Inside a blockquote, in corpus/commonmark/text-and-breaks.md, > followed by tab-stop content saves as a quoted fenced block.
Under Three leading spaces open a fence while four create indented code in corpus/commonmark/code.md, the indented block's content is itself a ``` fence, so fencing it raises the outer fence to ```` and moves the closing fence to end of file. The document round-trips — the corpus guard's document assertion passes — but the file's remaining lines are rewritten around a construct the author never wrote.
Related context
Done when
Notes, logs, screenshots
Diagnosis
Not established beyond the observation that the parse produces a code node with no fence information and the serializer writes every code node fenced. Whether the authored form is recoverable from node.position for an indented block, whose content offsets sit inside the indentation, is the first thing to check.
Implementation direction
remarkStringifyOptionsCtx in src/features/editor/utils/createMilkdownEditor.ts takes the code handler, so the seam is the same one the fence-form class uses; the two should be decided together rather than in sequence, since both answer the question of how a code block records the form it was written in.
An indented block cannot carry an info string, so a block that has one is fenced regardless of what was recorded.
Out of scope
- Fence character, length, and info-string form, which belong to the fenced-code class.
Four spaces do not interrupt an existing paragraph., whose indentation is stripped at parse because indented code cannot interrupt a paragraph. That is a read-time difference no serializer change reaches.
Summary
Saving rewrites every indented code block as a fenced block. The code survives, but the block changes shape, and the change is not confined to the block: fencing content that itself contains a backtick fence forces a longer outer fence, which rewrites the surrounding lines as well.
It happens at top level, inside a list item, and inside a blockquote.
Steps to reproduce
Expected behavior
The block is written back as indented code.
Actual behavior
Measured against
83e12b19by driving the editor mount used by the plugin tests.Top level, in
corpus/commonmark/code.md:saves as a
```fenced block holdingfour spaces open the blockandtwo further spaces stay in the content.Inside a list item, in
corpus/commonmark/lists-and-blockquotes.md,- five spaces changes the content indentation boundarysaves as a bullet item whose content is a fenced block. Inside a blockquote, incorpus/commonmark/text-and-breaks.md,>followed by tab-stop content saves as a quoted fenced block.Under
Three leading spaces open a fence while four create indented codeincorpus/commonmark/code.md, the indented block's content is itself a```fence, so fencing it raises the outer fence to````and moves the closing fence to end of file. The document round-trips — the corpus guard's document assertion passes — but the file's remaining lines are rewritten around a construct the author never wrote.Related context
Scope.Done when
corpus/commonmark/code.md,corpus/commonmark/lists-and-blockquotes.md, andcorpus/commonmark/text-and-breaks.mdlose these differences, or the reason they cannot is recorded.Notes, logs, screenshots
Diagnosis
Not established beyond the observation that the parse produces a code node with no fence information and the serializer writes every code node fenced. Whether the authored form is recoverable from
node.positionfor an indented block, whose content offsets sit inside the indentation, is the first thing to check.Implementation direction
remarkStringifyOptionsCtxinsrc/features/editor/utils/createMilkdownEditor.tstakes thecodehandler, so the seam is the same one the fence-form class uses; the two should be decided together rather than in sequence, since both answer the question of how a code block records the form it was written in.An indented block cannot carry an info string, so a block that has one is fenced regardless of what was recorded.
Out of scope
Four spaces do not interrupt an existing paragraph., whose indentation is stripped at parse because indented code cannot interrupt a paragraph. That is a read-time difference no serializer change reaches.