Fix qmd writer escape for apostrophes in non-word contexts (#201)#204
Merged
Conversation
…ophe (bd-8lcm) Round-trip qmd → AST → qmd produces output the reader re-rejects with Q-2-10. Triage doc records the trigger boundary (letter on left AND whitespace on right — confirmed by probes), code localization in crates/pampa/src/writers/qmd.rs, and a TDD-first fix scope handed off to bd-8lcm. Includes the minimal repro fixture from the issue. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…issue #201) The reader accepts a bare `'` between alphanumeric characters as an apostrophe (`don't`, `it's`, `ab'9`), but rejects it at any non-alnum boundary: `reveal.js' jump-to-slide.`, `ab'.cd`, `*hi'*`, `"hi'"`, and even `ab'` at end-of-block all fail with Q-2-7 / Q-2-10. The writer previously emitted bare `'` everywhere, so `qmd → AST → qmd → AST` was not a fixed point for inputs that originally required `\'`. `escape_markdown` now tracks `prev_char` and peeks at `next_char` so a single `'` arm can decide locally — no cross-inline lookahead is needed because the reader's rule itself is local to two characters around the apostrophe. Adds two roundtrip fixtures (`apostrophe_before_space.qmd`, `apostrophe_before_punct.qmd`) that exercised the bug and now lock in the fix. Triage: claude-notes/issue-reports/201/triage.md Plan: claude-notes/plans/2026-05-15-issue-201-apostrophe-escape.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
\'for apostrophes that the reader would otherwise reject as quote opens #201. The qmd writer dropped the\'escape on apostrophes whose source form required it (reveal.js\' jump-to-slide.), soqmd → AST → qmd → ASTwas not a fixed point: the regenerated output failed to re-parse with Q-2-7 or Q-2-10.escape_markdownwith a single'\''arm: escape when the previous char in theStrbody is Unicode alphanumeric AND the next char is either absent or non-alphanumeric. Otherwise leave bare (preservesdon't,it's,ab'9).crates/pampa/tests/roundtrip_tests/qmd-json-qmd/exercising the two distinct trigger shapes (apostrophe before whitespace, apostrophe before punctuation within the sameStr).The fix is purely local to
escape_markdown— noQmdWriterContextfield, no cross-inline lookahead, no signature changes. The reader's apostrophe rule turned out to be local to the two characters around', so the writer's rule mirrors that.Triage record:
claude-notes/issue-reports/201/triage.md(commit f9a45a7).Plan + end-to-end record:
claude-notes/plans/2026-05-15-issue-201-apostrophe-escape.md.Beads: bd-8lcm (closed in the sync commit on
main).Test plan
cargo nextest run -p pampa test_qmd_roundtrip_consistency— passes (the suite now includes the two new fixtures, which fail at HEAD before the fix).cargo nextest run -p pampa --no-fail-fast— 3686 / 3686 passed.cargo nextest run --workspace --no-fail-fast— 8863 / 8863 passed.cargo xtask verify --skip-hub-build --skip-hub-tests— all 9 steps green (lint, fmt, build with-D warnings, tree-sitter, Rust tests, trace-viewer build + tests).reveal.js\' jump-to-slide.(issue's case) →\'emitted, re-parse identical.ab\'.cd(within-Str punctuation) →\'emitted, re-parse identical.*hi\'*(apostrophe before Emph close*) →\'emitted."hi\'"(apostrophe before Quoted close") →\'emitted.don't,it's(letter-apostrophe-letter) → bare'preserved.ab'9(letter-apostrophe-digit) → bare'preserved.🤖 Generated with Claude Code