fix: toggle a code block off whatever language it names - #368
Merged
Conversation
Azganoth
enabled auto-merge (squash)
September 2, 2026 17:08
Azganoth
disabled auto-merge
September 2, 2026 17:15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Code blockrun on a fenced block carrying an info string deleted the info string instead of toggling the block off. A block opened by three backticks andtscame back opened by a bare fence, and the language was gone from the file on the next save. The language selects the highlighting the block renders with and Leafdown exposes no control for setting one, so a language lost this way cannot be typed back. The same gesture on a fence with no info string toggled the block off, as the specification already describes.toggleTextBlockTypedecides between removing the format and applying it by testing every attribute the call names, andtoggleCodeBlocknamed{ language: "" }. A block whose language was anything else failed that test, was treated as not yet a code block, and was rebuilt from the named attributes.code_blockcarrieslanguageas its only attribute and the schema already defaults it to"", so that argument named nothing the command asks for while doing two jobs it should not have: deciding which blocks the toggle reads as already being code blocks, and overwriting the language of any block that already was one. Removing it settles both. The recognition test then reads the node type alone, and the per-block resolver added under #359 keeps every attribute a command does not name, so an existing block passes through untouched while one that becomes a code block still opens without a language.Related Issue
Closes #365
Verification
blocks.test.tsgains three tests in its block-formatting group. Two run the toggle over a block opened withtsand a block opened bare, asserting the paragraph the command leaves behind beside the saved bytes, because a toggle that only deleted the info string left a file the language alone tells from the one a working toggle writes. Two of the three fail on the pre-change source; the bare-fence row passes, which is what makes it the guard rather than the fix.The third covers a path the issue's table does not reach.
Code blockover a selection holding a paragraph beside a code block wrapped the paragraph and cleared the existing block'stsat the same time. That is the issue's secondDone whenitem and a distinct path from the toggle, and the same argument removal answers it, because the language stops being an attribute the change writes over.pnpm check:frontendpasses, including the corpus round trip. The backend is untouched, sopnpm check:backendwas not run.Not verified: the manual pass over
corpus/in the running application, which covers rendering, interaction, and navigator behavior beyond the automated round trip. The desktop E2E suite was not run locally; its fixtures hold no code block command.Notes
insertCodeBlockalso names{ language: "" }and is left as it is. There the attribute names what a created block is given, which is the one job it legitimately has.docs/specification.mdrecords that a code block's language is content the block carries rather than a format a command asks for.Toggling the same block command removes the marker when applicableneeded no change: the specification already described the behavior and the code disagreed with it.