Repository navigation
Vale in-file directives need a [formats] mapping before they work in .txt recipes #291
Description
Vale's in-file directives (vale off / vale on, and the per-rule form) would let a recipe exclude the regions where it QUOTES a word rather than uses it, instead of excluding whole files. That is worth having: it would bring create-vale-rule.txt and verify-rule.txt back into scope, which are currently excluded wholesale from no-hedging.
It does not work today, and the reason is precise.
Measured
Vale 3.19.0, the binary this repo ships, one sample containing three hedging words with the middle one wrapped in a disable region:
| config | hits | directive honoured? |
|---|---|---|
.txt as plain text, CommentDelimiters = {/*, */} |
3 | no |
.txt with [formats] txt = md, same delimiters |
2 | yes |
native .md with <!-- vale off --> (control) |
2 | yes |
CommentDelimiters is accepted into the assembled config and silently does nothing for plain text. The docs explain why:
The key applies to the formats that take
BlockIgnores.
Plain text has no blocks. So the delimiters translate to HTML comments that nothing then interprets.
What it would take
A [formats] mapping in the assembled Vale config. This is a GLOBAL section, and the assembler currently emits per-rule matcher sections only. packages/cli/src/rules/vale/formats.ts is about which formats this build of Vale can parse, which is a different question from how an extension is mapped to a parser.
A strip step when a recipe is served. The markers are configuration, not content, and must never reach an agent reading taskless agent <topic>. That belongs wherever the recipe is rendered rather than at build time, so there is one place it can be wrong.
Why it is worth doing
no-hedging currently excludes two of the largest recipes entirely, worth 33 findings of lost coverage measured by lifting the exclusion. The reasoning is sound and recorded in the rule's config:
create-vale-ruleandverify-ruleteach rule authoring THROUGH a worked example calledno-simply... rewording the example to dodge its own subject would make the recipe worse.
Region markers make that a scalpel instead of a hammer: the worked example is excluded, the rest of the file is checked.
It also addresses a root complaint already written in the same config:
These are
.txt, which Vale treats as PLAIN TEXT: there is no markdown parser, so fenced blocks and code spans are not skipped the way they are in a.mdfile. Everything in the file is prose as far as the rule is concerned, including command examples.
Mapping txt = md fixes that for every rule at once.
The risk to weigh first
Mapping txt = md changes what every Vale rule sees in these files, not just no-hedging. Fenced blocks and code spans become invisible to any rule with the default text scope, so a finding that currently fires inside a fence would stop firing. docs-npx-cli is unaffected, since scope: [raw, ...] still sees the unparsed markup, but the others need checking one by one before this lands.
That is the actual work here: not the mapping, but deciding per rule whether losing fenced content is a fix or a regression.
Found while clearing the last house-style findings for a clean 0.11.1 self-check (#290), which took the narrower route of rewording four incidental examples.
Activity
theCodeDrift commentedon Sep 7, 2026
Closed by #290, though not the way this issue proposed, which is worth recording for anyone who finds this later.
The suggestion here was a global
[formats]mapping (txt = md) plusCommentDelimiters, which needed a CLI change because the config assembler emits per-rule matcher sections only. What landed instead was renaming the recipes to.md, since that is what they already were:routealone carries 69 headings, tables, fenced blocks and emphases. As markdown, Vale parses them natively,<!-- vale ... -->works withoutCommentDelimiters, and no assembler change is needed.The measured win was larger than expected. Lifting the
no-hedgingexclusion cost 33 findings as.txtand 2 as.md, because the other 31 sat inside fences and code spans a markdown parser skips. Both previously-excluded recipes are back in scope.Two findings from that work that this issue did not anticipate:
create-vale-rulenow documents this..prettierignoreexcludes them now; their line breaks are content.— AI Coding Agent