Ban text in a document
When some text must never appear, list a regular expression for it under prohibited-patterns, with a message that states the rule. Such text might be a TODO left in a finished document, or a vague word in a changelog. Each line that matches the expression then fails, and its error quotes the matched text and gives the message. The scaffold of a new document shows the message too, so that its writer reads the rule before writing.
You can set the key at three levels. A ban on the schema applies to every line of the body. A ban on a rule applies to the text of each unit that the rule checks. A ban on a format applies to every line bound to the format.
Before you begin
- A schema with a list, as in Your first schema.
- To ban text in a format, a format that you defined, as in Share line formats across schemas.
Steps
-
To ban text anywhere in the body, list it under
prohibited-patternson the schema. Each entry has apatternand amessage. Thepatternis an unanchored regular expression in the Rust dialect. Themessageis one sentence that states the rule as a fact about the document. Use\bto match whole words, and(?i)to ignore case. -
To ban text in one kind of unit, put
prohibited-patternson the rule that checks it. -
To ban text in every line of a format, put
prohibited-patternson the format. The command checks the shape of a line first, then the bans of its rule and of its format.This changelog schema bans
TODOeverywhere, the wordvariousin a list item, and...in every line of the formatchange:
changelog.yaml
line-limit: 0
prohibited-patterns:
- pattern: '\bTODO\b'
message: 'A finished changelog contains no TODO.'
types:
change: [Added, Changed, Fixed, Removed]
formats:
change:
template: '${:change}: ${}'
example: 'Fixed: the parser reads a tab as four spaces.'
prohibited-patterns: [{pattern: '\.\.\.', message: 'A change ends with a full stop, not with an ellipsis.'}]
sections:
- heading: Changelog
level: 1
blocks:
- kind: bullet-list
each:
format: change
prohibited-patterns: [{pattern: '(?i)\bvarious\b', message: 'An item names its change rather than calling it various.'}]
- kind: code
lang: text
optional: true
example: tramlines validate --schema list.yaml groceries.md
- Check a document. The command applies no ban inside fenced blocks or code spans, so text that you quote as code passes:
changelog.md
# Changelog
- Added: the `--formats` option. TODO document it
- Fixed: various bugs.
- Changed: the `TODO` marker in a code span is fine...
```text
TODO in a fence is fine
```
$ tramlines validate --schema changelog.yaml changelog.md
changelog.md:3: error[TL_75]: `TODO` is refused: A finished changelog contains no TODO. (schema changelog)
changelog.md:4: error[TL_75]: `various` is refused: An item names its change rather than calling it various. An item of this kind reads Fixed: the parser reads a tab as four spaces. (schema changelog, section "Changelog" block 1)
changelog.md:5: error[TL_75]: `...` is refused: A change ends with a full stop, not with an ellipsis. An item of this kind reads Fixed: the parser reads a tab as four spaces. (schema changelog, section "Changelog" block 1)
3 errors, 0 warnings
[exit 1]
Each finding quotes the span that the pattern matched, and gives the message of the ban, not its pattern. When the ban is on a rule or a format, the finding also shows the example of that rule or format, so that you see a line that passes. The scaffold of the schema writes the message of each ban after the guidance of the part that the ban governs. It writes the message of a ban on the schema in its opening line.
Troubleshooting
TL_75: a line of the document matches a banned pattern. Rewrite the span that the message quotes. If the span is a name, not prose, quote it as code instead. See TL_75.TL_118: a pattern isn’t a valid regular expression in the Rust dialect. For example, the dialect has no lookarounds and no backreferences. See TL_118.