Skip to content

Indented code is rewritten as a fenced block on save #321

Description

@Azganoth

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

  1. Open a document containing a code block indented by four spaces.
  2. Save it without editing.
  3. 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

  • An indented code block is written back as indented code, at top level, inside a list item, and inside a blockquote.
  • A block made in the editor still writes a defined default.
  • corpus/commonmark/code.md, corpus/commonmark/lists-and-blockquotes.md, and corpus/commonmark/text-and-breaks.md lose 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.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.

Metadata

Metadata

Assignees

Labels

BugSomething isn't working

Projects

  • Status
    Ready

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions