Skip to content

fix(MD049,MD037): Preserve inline code inside emphasis during auto-fix#652

Merged
rvben merged 1 commit into
rvben:mainfrom
thegeorgeliu:thegeorgeliu/fix/emphasis-inline-code-mask-leak
Jun 2, 2026
Merged

fix(MD049,MD037): Preserve inline code inside emphasis during auto-fix#652
rvben merged 1 commit into
rvben:mainfrom
thegeorgeliu:thegeorgeliu/fix/emphasis-inline-code-mask-leak

Conversation

@thegeorgeliu

Copy link
Copy Markdown
Contributor

Description

To detect emphasis markers reliably, MD049 and MD037 first build a throwaway copy of each line with every inline code span replaced by an equal-length sequence of X characters (and inline math by M). This prevents backtick or dollar contents from being misread as emphasis markers. The auto-fix, however, reused the emphasis text taken from that masked copy, so the X/M placeholders leaked into the written file and permanently replaced the original inline code.

The fix takes the replacement text from the original line at the span's byte offsets instead. Because masking replaces each span with a sequence of the same byte length, those offsets remain valid against the original line.

Example before this fix (rumdl fmt with MD049 style = "asterisk"):

  • input: - _An item with inline code inside._
  • output: - *An item with XXXXXXXXXXXXX inside.*

After the fix the inline code is preserved: - *An item with inline code inside.*. Only fmt/--fix was affected; check does not modify files. MD050 (strong style) was not affected.

Type of Change

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing functionality to change)
  • Documentation update

Testing

  • Tests added/updated (regression tests in both rules)
  • All tests passing: cargo nextest for md049/md037/emphasis/reflow/md013/formatter_idempotency, and full cargo test --lib (5810 passed)
  • Manual testing performed: rumdl fmt on the repro is now lossless and idempotent

Checklist

  • Code follows project style (cargo fmt --check clean; CI clippy gate -D warnings -D clippy::uninlined_format_args clean)
  • Conventional commit messages used
  • Documentation updated (not needed)
  • CHANGELOG.md updated (maintainer-generated at release via git-cliff)

Closes #651

Both rules detect emphasis on a copy of the line where inline code spans are
masked with equal-length runs of 'X' (and inline math with 'M'), so backtick or
dollar contents are not mistaken for emphasis markers. The auto-fix then reused
the emphasis content taken from that masked copy, so the placeholder characters
leaked into the written file and permanently replaced the original inline code.
This corrupts content and affects fix/fmt only, not check.

Slice the replacement content from the original line at the span's byte offsets
instead. Masking is length-preserving, so the offsets stay valid.

- MD049: build emphasis content from the original line in
  collect_emphasis_from_line rather than the masked copy.
- MD037: slice the trimmed content from the original line when building the
  space-fixed replacement.
- Add regression tests for inline code inside emphasized spans in both rules
  (both directions for MD049), asserting no placeholder leakage.
@rvben

rvben commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Thanks @thegeorgeliu, for both the clear bug report in #651 and the fix. Nicely scoped, with good regression tests. Merging now; it'll ship in the next patch release.

@rvben rvben merged commit a1b1055 into rvben:main Jun 2, 2026
6 checks passed
@thegeorgeliu

Copy link
Copy Markdown
Contributor Author

Happy to contribute @rvben! Thanks for all your great work on rumdl, I've been using it for a while now throughout all my personal and work projects!

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(MD049/MD037): rumdl fmt replaces inline code inside emphasis with X placeholders

2 participants