|
1 | | -# Topic: create-vale-rule (CLI v%(CLI_VERSION)s / topic v5) |
| 1 | +# Topic: create-vale-rule (CLI v%(CLI_VERSION)s / topic v6) |
2 | 2 |
|
3 | 3 | ## You are here |
4 | 4 | This is `create-vale-rule`. It helps you write a Vale rule: a check over |
@@ -220,44 +220,49 @@ it. |
220 | 220 | the cause is in that rule's own `scope` and glob, never in a |
221 | 221 | neighbour's. |
222 | 222 |
|
223 | | - **A `raw`-scoped rule cannot be turned off in a document.** Vale's |
224 | | - `<!-- vale <id>.<id> = NO -->` directive is applied to the *parsed* |
225 | | - document, and `raw` reads the unparsed one. Measured: a `text`-scoped |
226 | | - rule is silenced by the directive; the same rule at `raw` fires |
227 | | - through it. So a rule about a shell command, a flag, or a package name |
228 | | - needs `raw`, commands live in fenced blocks, which nothing else |
229 | | - reaches, and takes that trade: it can no longer be exempted case by |
230 | | - case, only removed. |
231 | | - |
232 | | - **An exception zone is the size of a top-level block, and no smaller.** |
233 | | - A pair of directives turns a rule off for a region and back on: |
234 | | - `= NO` opens it and `= YES` closes it. Both lines have to start at |
235 | | - column 0, because Vale reads them as HTML blocks and an HTML block |
236 | | - begins at the left margin. |
237 | | - |
238 | | - That constraint decides where a zone can go, and it is easy to get |
239 | | - wrong twice. Measured on Vale 3.19.0, in this file: |
240 | | - |
241 | | - - At a list item's continuation indent the directive is not |
242 | | - recognised at all. The words stay reported and nothing says the |
243 | | - marker was ignored. |
244 | | - - At column 0 in the middle of a list, the directive is recognised |
245 | | - and it ends the list. The blocks after it reparse as indented code, |
246 | | - which are already outside a prose rule's reach, so coverage moves |
247 | | - rather than being restored where you meant to restore it. |
248 | | - |
249 | | - So a zone wraps a whole numbered step, a whole section, or a whole |
250 | | - paragraph at the margin. Price it before reaching for one: exempting |
251 | | - the two steps of this recipe that quote hedging words would have put |
252 | | - 176 lines of prose out of reach to keep two words of an example. Those |
253 | | - two examples were rewritten to use words the rule does not carry, |
254 | | - which cost three words and no coverage at all. |
255 | | - |
256 | | - **Write a documented example indented, never at the margin.** A |
257 | | - directive at column 0 in a recipe takes effect on the recipe, and the |
258 | | - CLI strips it before serving so a reader never sees it. That is why |
259 | | - every directive quoted in this file sits inside a sentence or an |
260 | | - indented block: it is being shown, not run. |
| 223 | + **A directive turns any rule off, `raw` included, as of Vale 3.20.0.** |
| 224 | + `<!-- vale <id>.<id> = NO -->` opens a zone and `= YES` closes it. |
| 225 | + Vale records the region each directive covers and suppresses any |
| 226 | + alert located inside it, which reaches a `raw`-scoped rule too. |
| 227 | + Through 3.19.0 a directive was applied to the *parsed* document and |
| 228 | + `raw` reads the unparsed one, so a `raw` rule fired straight through |
| 229 | + every zone: a rule about a shell command, a flag, or a package name |
| 230 | + was exempt-or-remove with nothing in between. It is not any more. |
| 231 | + |
| 232 | + One thing to know before writing one over a `raw` rule: at `raw` |
| 233 | + scope the directive line is itself linted text. A rule whose token |
| 234 | + appears in its own id matches the marker that silences it, and |
| 235 | + reports a finding on the directive. Name the rule so its own id does |
| 236 | + not contain the word it looks for. |
| 237 | + |
| 238 | + **A zone is two lines, and no blank line may separate it from the |
| 239 | + prose it wraps.** Measured on Vale 3.20.0: |
| 240 | + |
| 241 | + - Inline at a list item's continuation indent works, and this is the |
| 242 | + form to reach for. The pair covers the lines between it and |
| 243 | + nothing else. |
| 244 | + - At column 0 it works too, and it ends any list it interrupts. |
| 245 | + Blocks that then reparse as indented code are already outside a |
| 246 | + prose rule's reach, so a zone placed there can move coverage |
| 247 | + rather than restore it. |
| 248 | + - A pair separated from its prose by blank lines, at an indent past |
| 249 | + the code-block threshold, suppresses nothing: what it wraps is not |
| 250 | + prose any more. Nothing reports that, either. |
| 251 | + |
| 252 | + Through 3.19.0 the first of those did nothing at all. An inline pair |
| 253 | + was read once per block, so the `NO` and the `YES` cancelled out |
| 254 | + before the paragraph was linted and the words stayed reported with |
| 255 | + no error and no warning. A zone had to wrap a whole step or a whole |
| 256 | + section at the margin, and exempting the two steps of this recipe |
| 257 | + that quote hedging words would have put 176 lines of prose out of |
| 258 | + reach to keep two words of an example. That price is gone. |
| 259 | + |
| 260 | + **A shown directive has to be inline or fenced, never a bare line.** |
| 261 | + A directive on a line of its own now takes effect on the recipe at |
| 262 | + any indent, and the CLI strips it before serving so a reader never |
| 263 | + sees it. Measured: a directive inside backticks and a directive |
| 264 | + inside a fenced block are both inert, which is why every directive |
| 265 | + quoted in this file is one or the other. |
261 | 266 |
|
262 | 267 | **Then the fields the extension point adds**. This is where the rule |
263 | 268 | actually lives, and each check reads only its own: |
|
274 | 279 | | `metric` | `formula`, `condition` | |
275 | 280 | | `readability` | `metrics` (a list of formula names), `grade` | |
276 | 281 | | `spelling` | `aff`, `dic`, `custom`, `filters`, `ignore`, `threshold` | |
277 | | -| `sequence` | `tokens` (each a `pattern`/`tag` map); `ignorecase` | |
| 282 | +| `sequence` | `tokens` (each a `pattern`/`tag` map); `ignorecase`, `exceptions` | |
278 | 283 | | `script` | `script` (Tengo source) | |
279 | 284 |
|
280 | 285 | The list above is measured, not transcribed: every entry was added to |
|
437 | 442 | needs `nonword: true`. |
438 | 443 |
|
439 | 444 | - **A bare word finds senses you did not mean.** `landed on` in a rule |
440 | | - about jargon also matches "the plane landed on time"; `clearly` in a |
441 | | - rule about hedging also matches "clearly labelled" in a spec. |
| 445 | + <!-- vale no-hedging.no-hedging = NO --> |
| 446 | + about jargon also matches "the plane landed on time"; `simply` in a |
| 447 | + rule about hedging also matches "simply connected" in a maths doc. |
| 448 | + <!-- vale no-hedging.no-hedging = YES --> |
442 | 449 | Narrow the token to the **collocation** you actually object to |
443 | 450 | (`landed on a decision`, not `landed on`), and check that you got it |
444 | 451 | right by writing the `pass/` fixture from the literal sense *first*: |
|
535 | 542 | assumes; `scope: heading` has nothing to find outside it: |
536 | 543 | %(VALE_MARKUP_FORMATS)s |
537 | 544 | - **comment text only**: the comments are linted and the code body |
| 545 | + <!-- vale no-hedging.no-hedging = NO --> |
538 | 546 | is invisible, which is exactly right for "comments must not say |
539 | | - 'TBD'": |
| 547 | + 'obviously'": |
| 548 | + <!-- vale no-hedging.no-hedging = YES --> |
540 | 549 | %(VALE_COMMENT_FORMATS)s |
541 | 550 | - **plaintext fallback**: everything else, `.yml` `.toml` `.sh` |
542 | 551 | `.sql` and every extension not named above included. There is no |
|
0 commit comments