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.
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 callbacktrip Q-2-7 (Unclosed Single Quote).Reproducer
Output:
Pandoc reads the same input as a possessive without complaint.
Scope
`code`'s gate'promoted to opening`code`'foo bar`code` 's gate`code`\'s gateword's gate`code`'s and `other`'s pair`code`'s and word's pairThe angle brackets in patterns like
`<AssetManifestContext>`'sare 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 handlesword'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-corpusshowing that`code`'sno longer fires Q-2-7.Workarounds available today
`code`\'s.Related
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.