Inline parser: apostrophe after a code span trips Q-2-7 (Unclosed Single Quote)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 255
- Forks
- 17
- Avg merge
- 6h 20m
- Merged PRs (30d)
- 109
Description
Claude kept hitting Q-2-7 when writing items in the hub-client changelog. Apostrophe seems to be a special case that works in Pandoc.
Summary
The inline grammar's smart-quote rule treats ' immediately after a closing backtick (code-span boundary) as an opening single quote, even when followed by letters as in a possessive. Pandoc treats the same construct as a possessive and emits no error. As a result, common technical-writing patterns like `setAst`'s callback trip Q-2-7 (Unclosed Single Quote).
Reproducer
printf "x \`code\`'s gate\n" | cargo run --bin pampa -- -t json -i -
Output:
Error: [Q-2-7] Unclosed Single Quote
1 │ x `code`'s gate
│ ┬
│ ╰── This is the opening quote. If you need an apostrophe, escape it with a backslash.
Pandoc reads the same input as a possessive without complaint.
Scope
| Pattern | Result | Why |
|---|---|---|
`code`'s gate |
FAIL | post-codespan ' promoted to opening |
`code`'foo bar |
FAIL | same |
`code` 's gate |
FAIL | whitespace between doesn't help |
`code`\'s gate |
PASS | escaped apostrophe |
word's gate |
PASS | letter-letter → possessive |
`code`'s and `other`'s pair |
PASS | two opens form a balanced pair |
`code`'s and word's pair |
FAIL | only one promoted-to-opening |
The angle brackets in patterns like `<AssetManifestContext>`'s are a red herring — backticks alone are the trigger.
Real-world incidents
This has tripped the hub-client changelog at least twice:
0c78b1a4(2026-05-08) — diagnosis blamed<Tag>HTML-like content; the angle brackets were coincidental.d7d7e063(2026-05-10) — same pattern in plan changelog entries; rewritten in plain prose to clear the parse.
Proposed fix
In tree-sitter-markdown-inline's grammar, extend the rule for opening single quote so a ' immediately after a closing backtick — more generally, after any inline-end token — is treated as a possessive when the next character is a letter. This is the same heuristic that already handles word's. Pandoc's smart-quote algorithm is "an apostrophe between letters, or after a markup boundary that resolves to letters, is a possessive."
After regenerate + build, add a test case to the inline grammar's corpus and a passing case to resources/error-corpus showing that `code`'s no longer fires Q-2-7.
Workarounds available today
- Pair them deliberately in the same block (two close-backtick apostrophes form a smart-quote pair).
- Backslash-escape:
`code`\'s. - Rephrase so the apostrophe is inside a word (e.g. "the setAst callback's behavior").
Related
- Internal: bd-1qk5 (this issue's origin), bd-kk0a (writer-side escape for unbalanced apostrophes — a parser fix here would obviate part of bd-kk0a's scope).
crates/pampa/snapshots/error-corpus/text/006.snap,009.snap— current Q-2-7 examples.resources/error-corpus/_autogen-table.json:18686— parser-state mapping table.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the opening-single-quote rule in tree-sitter-markdown-inline and reproduce the code's case from the issue. Regenerate and build the grammar, then add the inline grammar corpus case and a passing case to resources/error-corpus. Done means the possessive no longer emits Q-2-7 while the existing quote behavior remains covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- markdown, rust
- Domain
- testing-qa, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100