Skip to content

fix: inconsistent markdown conversion - #336

Merged
vitonsky merged 17 commits into
masterfrom
334-inconsistent-markdown-conversion
Jun 29, 2026
Merged

fix: inconsistent markdown conversion#336
vitonsky merged 17 commits into
masterfrom
334-inconsistent-markdown-conversion

Conversation

@vitonsky

@vitonsky vitonsky commented Jun 27, 2026

Copy link
Copy Markdown
Member

Fix #334

Summary by CodeRabbit

  • New Features
    • Expanded Markdown import/export to support additional rich elements such as tables, thematic breaks, headings, nested quotes, links/images, and both inline and block code.
  • Bug Fixes
    • Improved Markdown round-tripping consistency, with better structural preservation for lists/checklists, table cells, and spacing/blank-line handling between converted formats.
  • Tests
    • Added broader round-trip validation with more Markdown fixtures and shared editor/test utilities to confirm serialized output stays stable.

@vitonsky vitonsky linked an issue Jun 27, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 94dfd53b-3448-43a3-9c65-30b47dddd40a

📥 Commits

Reviewing files that changed from the base of the PR and between 6570b19 and e5d24fd.

⛔ Files ignored due to path filters (1)
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/__snapshots__/markdown-roundtrips-consistency.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/markdown-roundtrips-consistency.test.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/utils.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/convertLexicalNodeToMarkdownNode.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/markdownParser.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/tests/markdown-roundtrips-consistency.test.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/tests/utils.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/markdownParser.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/convertLexicalNodeToMarkdownNode.ts

📝 Walkthrough

Walkthrough

Refactors Markdown parsing and serialization into exported helpers, moves Lexical-to-mdast conversion into a standalone module, and adds round-trip consistency tests with expanded fixtures.

Changes

Markdown AST conversion refactor and tests

Layer / File(s) Summary
Lexical to mdast conversion
packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/convertLexicalNodeToMarkdownNode.ts
Defines conversion for paragraphs, images, text, inline code, code blocks, formatting, rules, lists, list items, links, blockquotes, tables, line breaks, headings, and the html fallback.
Markdown parsing and serialization helpers
packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/markdownParser.ts
Exports markdownProcessor, adds parseMarkdownToAST, adds paragraph wrapping helpers, updates list and table conversion paths, simplifies node conversion, and routes $convertToMarkdownString through $serializeAsMarkdownAST.
Round-trip test helpers and fixtures
packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/utils.ts, packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/markdown-samples/index.ts, packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/markdown-roundtrips-consistency.test.ts
Adds Markdown AST normalization and Lexical editor test helpers, expands sample fixtures, and adds a consistency suite that compares parsed and serialized Markdown ASTs and snapshots the output string.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hop through nodes with tidy feet,
and markdown sings in rounds so neat.
Lists, quotes, code all line up true,
the AST says “yes” to what you do.
Hoppity-hop, the tests all glow ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing inconsistent markdown conversion.
Linked Issues check ✅ Passed The markdown parser and list-item handling changes address the reported checklist corruption in issue #334.
Out of Scope Changes check ✅ Passed The edits stay focused on markdown conversion logic, round-trip tests, and supporting fixtures.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 334-inconsistent-markdown-conversion

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/markdown-roundtrips-consistency.test.ts`:
- Around line 21-72: The Markdown round-trip test cases use the wrong task-list
syntax and never cover the mutation path that reproduces the bug. Update the
fixtures in markdown-roundtrips-consistency.test.ts to use GFM task-list markup
with spaced checkboxes, and extend the test around createLexicalEditorInstance,
updateEditorState, and $convertFromMarkdownString so it also performs the editor
edit sequence that triggers the nested checklist regression before asserting the
Markdown AST round-trip.

In
`@packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/utils.ts`:
- Around line 71-80: The test helper’s cleanup in the Markdown editor setup
leaves the appended root element in document.body, so update the destroy() logic
in the create test utility to fully remove the rootElement after calling
editor.setRootElement(null). Use the unique symbols createEditor/create test
helper and destroy() to locate the cleanup path, and ensure each test detaches
the Lexical root and then removes the DOM node from jsdom to avoid leaking state
between tests.

In
`@packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/convertLexicalNodeToMarkdownNode.ts`:
- Around line 133-146: The list item conversion in
convertLexicalNodeToMarkdownNode currently wraps each inline child from
$isListItemNode into its own paragraph, which breaks mixed inline content into
multiple blocks. Update the listItem handling to buffer consecutive inline
markdown nodes into a single paragraph and only flush/start a new block when a
non-inline child appears, so mixed content like text plus links stays in one
paragraph while nested lists still become separate blocks.
- Around line 150-157: The Link conversion in convertLexicalNodeToMarkdownNode
is using the wrong mdast field for the link title, so update the
$isLinkNode(node) branch to pass title from node.getTitle() instead of alt, and
make sure it uses a null fallback with title: node.getTitle() ?? null. Keep the
rest of the u('link', ...) mapping unchanged so the link children and URL
handling remain intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 53bac22c-e859-42e0-80a7-161cfdecee30

📥 Commits

Reviewing files that changed from the base of the PR and between ab40e4a and 628e3f6.

⛔ Files ignored due to path filters (1)
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/__snapshots__/markdown-roundtrips-consistency.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (5)
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/markdown-roundtrips-consistency.test.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/markdown-samples/index.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/utils.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/convertLexicalNodeToMarkdownNode.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/markdownParser.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/markdownParser.ts`:
- Around line 35-82: Do not inject blank-line paragraph nodes into list children
in remarkPreserveBlankLines, since the tree walk also visits list parents and
can turn list.children into an invalid mix of listItem and paragraph nodes.
Update the plugin to skip list nodes (or preserve spacing via
spread/listItem.spread instead) so markdownParser.ts keeps the mdast/Lexical
list shape intact during $convertFromMarkdownString.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 745bd7d4-ff17-43e9-aaea-bed0f550e36c

📥 Commits

Reviewing files that changed from the base of the PR and between 628e3f6 and 42861e3.

⛔ Files ignored due to path filters (1)
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/__snapshots__/markdown-roundtrips-consistency.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/markdown-roundtrips-consistency.test.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/__tests__/markdown-samples/index.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/convertLexicalNodeToMarkdownNode.ts
  • packages/app/src/features/NoteEditor/RichEditor/plugins/Markdown/markdownParser.ts

@vitonsky

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@vitonsky
vitonsky merged commit e1de085 into master Jun 29, 2026
6 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jul 9, 2026
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.

Inconsistent markdown conversion

1 participant