Skip to content

[Super Editor] - Markdown: Preserve code fence language and serialize fence content literally (Resolves #3006) - #3081

Closed
donaldheppner wants to merge 3 commits into
Flutter-Bounty-Hunters:mainfrom
donaldheppner:md-codec-3-code-fence-language
Closed

[Super Editor] - Markdown: Preserve code fence language and serialize fence content literally (Resolves #3006)#3081
donaldheppner wants to merge 3 commits into
Flutter-Bounty-Hunters:mainfrom
donaldheppner:md-codec-3-code-fence-language

Conversation

@donaldheppner

Copy link
Copy Markdown

What this does

Fixes fenced code blocks corrupting on every serialize/parse round trip (Resolves #3006):

Tests

New serialization and deserialization cases in super_editor_markdown_test.dart: language preservation both directions, literal (unescaped) fence content, and codeLanguage metadata absent for bare fences.

PR 3 of the Markdown codec series — stacked on #3079 and #3080; review the last commit. Extracted from MemNote's super_editor fork.

🤖 Generated with Claude Code

donaldheppner and others added 3 commits July 5, 2026 17:42
… re-parses to the same styled text

Rewrites AttributedTextMarkdownSerializer so its output re-parses to the
same styled text:

- Trim whitespace at the edges of bold/italic/strikethrough/code spans
  outside the style markers ("**bold **" -> "**bold** "); whitespace-
  bounded markers are not valid CommonMark emphasis, so the styling
  silently vanished on the next parse (Flutter-Bounty-Hunters#2424, Flutter-Bounty-Hunters#2650).
- Preserve backslash escapes: parsing "3\*4" records a markdownEscape
  attribution on the "*" and serialization re-emits the backslash.
- Serialize overlapping (non-nested) spans by closing and re-opening
  styles so markers nest properly; open same-offset styles longest-span
  first; merge adjacent same-style spans instead of emitting "**a****b**".
- Safety net: re-parse the output and compare; if styles don't survive,
  escape markdown-significant characters (protects "3*4 and 5*6" from
  gaining emphasis).
- Escape block-level triggers at plain-paragraph line starts ("# ", "> ",
  "- ", "1. ", fences, thematic breaks) so paragraphs don't change block
  type on the next parse.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…derline as "<u>" (parse legacy forms)

- Strikethrough serializes as GFM "~~text~~" instead of the non-standard
  single "~". The parser still accepts the legacy single-tilde form,
  which heals to "~~" on the next serialization.
- Underline serializes as "<u>text</u>" instead of the proprietary
  "¬text¬" marker; inline HTML tags are the only widely supported way to
  express underline in Markdown. The parser accepts both, so legacy "¬"
  content heals to "<u>" on the next save.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… fence content literally (Resolves Flutter-Bounty-Hunters#3006)

- Parse the fence info string ("```dart") into the code node's
  codeLanguage metadata and re-emit it on serialization. Previously the
  language was silently dropped on the first round trip.
- Serialize fence content as literal plain text instead of routing it
  through the inline markdown serializer, which appended two-space
  hard-break markers to every line (compounding on every round trip) and
  backslash-escaped code content.
- Strip the single trailing newline the parser stores for fenced code so
  the fence doesn't grow a blank line on every round trip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@donaldheppner

Copy link
Copy Markdown
Author

Closing — opened prematurely from our fork's staging branches. Apologies for the noise.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] - [Markdown] - Fenced code blocks accumulate trailing whitespace on every parse → serialize round-trip

1 participant