diff --git a/.vale.ini b/.vale.ini index 9753a3830e..d92e27abc6 100644 --- a/.vale.ini +++ b/.vale.ini @@ -2,7 +2,12 @@ StylesPath = "vale/styles" MinAlertLevel = suggestion -Packages = Google, Microsoft, alex +; Std is vendored (via `vale sync`) but not yet in BasedOnStyles below, so its +; rules don't run yet. It's Vale's new shared rule library (see +; https://vale.sh/blog/std) meant to de-duplicate rules Google/Microsoft both +; reimplement, e.g. Oxford comma, passive voice, sentence length. Adopting it +; to replace those overlapping rules is a deliberate follow-up, not done here. +Packages = Google, Microsoft, alex, Std Vocab = Temporal [*.{md,mdx}] diff --git a/AGENTS.md b/AGENTS.md index d59748f286..9aa7322d5c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -192,7 +192,8 @@ don't build in production at all, which 404s any inbound links). A page that's a belongs in `bin/orphan-pages-baseline.json` with a note, rather than being silently ignored. See [UTILITIES.md](./readme/UTILITIES.md) for details. -Vale linting (style): +Vale linting (style). Requires Vale 3.20+ (CI already runs 3.20.0; upgrade a local install with +`brew upgrade vale`) — `vale/styles/Std` needs it for its nested rule directories. ```bash yarn lint:py # Example: lint Python SDK docs diff --git a/vale/styles/Std/Abbreviations/Acronyms.yml b/vale/styles/Std/Abbreviations/Acronyms.yml new file mode 100644 index 0000000000..f7b200c0ff --- /dev/null +++ b/vale/styles/Std/Abbreviations/Acronyms.yml @@ -0,0 +1,76 @@ +# Extracted from errata-ai/Google (MIT). See NOTICE. +# +extends: conditional +message: "Spell out '%s' on first use." +level: suggestion +ignorecase: false +# Ensures that the existence of 'first' implies the existence of 'second'. +first: '\b([A-Z]{3,5})\b' +second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)' +# ... with the exception of these: +exceptions: + - API + - ASP + - CLI + - CPU + - CSS + - CSV + - DEBUG + - DOM + - DPI + - FAQ + - GCC + - GDB + - GET + - GPU + - GTK + - GUI + - HTML + - HTTP + - HTTPS + - IDE + - JAR + - JSON + - JSX + - LESS + - LLDB + - NET + - NOTE + - NVDA + - OSS + - PATH + - PDF + - PHP + - POST + - RAM + - REPL + - RSA + - SCM + - SCSS + - SDK + - SQL + - SSH + - SSL + - SVG + - TBD + - TCP + - TODO + - URI + - URL + - USB + - UTF + - XML + - XSS + - YAML + - ZIP +tests: + - name: fires + input: > + Configure the DNS record before provisioning the VM. + want: | + 1:15:Std.Abbreviations.Acronyms:Spell out 'DNS' on first use. + + - name: clean + input: > + Configure the Domain Name System (DNS) record first, then the DNS zone. + want: "" diff --git a/vale/styles/Std/Abbreviations/Latin.yml b/vale/styles/Std/Abbreviations/Latin.yml new file mode 100644 index 0000000000..854ccf3bea --- /dev/null +++ b/vale/styles/Std/Abbreviations/Latin.yml @@ -0,0 +1,30 @@ +# Extracted from errata-ai/Google and errata-ai/IBM (MIT). See NOTICE. +# +# Google's boundary style (the lookahead doesn't swallow the following comma +# or space, and `$` catches abbreviations ending a heading or table cell), +# extended over IBM's larger list. +extends: substitution +message: "Use '%s' instead of '%s'." +level: suggestion +ignorecase: true +nonword: true +action: + name: replace +swap: + '\b(?:eg|e\.g\.)(?=[\s,;]|$)': for example + '\b(?:ie|i\.e\.)(?=[\s,;]|$)': that is + '\betc\.(?=[\s,;]|$)': and so on + '\bvs\.(?=[\s,;]|$)': versus +tests: + - name: fires + input: > + Use a tunnel, e.g. SSH, for internal services, i.e. anything private, etc. + want: | + 1:15:Std.Abbreviations.Latin:Use 'for example' instead of 'e.g.'. + 1:48:Std.Abbreviations.Latin:Use 'that is' instead of 'i.e.'. + 1:71:Std.Abbreviations.Latin:Use 'and so on' instead of 'etc.'. + + - name: clean + input: > + Use a tunnel, for example SSH, for internal services. + want: "" diff --git a/vale/styles/Std/DateTime/DateFormat.yml b/vale/styles/Std/DateTime/DateFormat.yml new file mode 100644 index 0000000000..179deee208 --- /dev/null +++ b/vale/styles/Std/DateTime/DateFormat.yml @@ -0,0 +1,22 @@ +# Extracted from errata-ai/Google (MIT). See NOTICE. +# +extends: existence +message: "Ambiguous date format: '%s'." +level: suggestion +ignorecase: true +nonword: true +tokens: + - '\d{1,2}(?:\.|/)\d{1,2}(?:\.|/)\d{4}' + - '\d{1,2} (?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?) \d{4}' +tests: + - name: fires + input: > + Support ends on 12/31/2026, which was announced on 5 January 2026. + want: | + 1:17:Std.DateTime.DateFormat:Ambiguous date format: '12/31/2026'. + 1:52:Std.DateTime.DateFormat:Ambiguous date format: '5 January 2026'. + + - name: clean + input: > + Support ends on December 31, 2026. + want: "" diff --git a/vale/styles/Std/DateTime/TimeFormat.yml b/vale/styles/Std/DateTime/TimeFormat.yml new file mode 100644 index 0000000000..235b9c5368 --- /dev/null +++ b/vale/styles/Std/DateTime/TimeFormat.yml @@ -0,0 +1,23 @@ +# Extracted from errata-ai/Google (MIT). See NOTICE. +# +extends: existence +message: "Inconsistent time format: '%s'." +level: suggestion +nonword: true +tokens: + - '\d{1,2}[AP]M\b' + - '\d{1,2} ?[ap]m\b' + - '\d{1,2} ?[aApP]\.[mM]\.' +tests: + - name: fires + input: > + The job runs at 5PM and again at 6 am, then at 7 a.m. + want: | + 1:17:Std.DateTime.TimeFormat:Inconsistent time format: '5PM'. + 1:34:Std.DateTime.TimeFormat:Inconsistent time format: '6 am'. + 1:48:Std.DateTime.TimeFormat:Inconsistent time format: '7 a.m.'. + + - name: clean + input: > + The job runs at 5 PM and again at 6 AM. + want: "" diff --git a/vale/styles/Std/Grammar/Contractions.yml b/vale/styles/Std/Grammar/Contractions.yml new file mode 100644 index 0000000000..d885121645 --- /dev/null +++ b/vale/styles/Std/Grammar/Contractions.yml @@ -0,0 +1,64 @@ +# Extracted from errata-ai/Microsoft (MIT). See NOTICE. +# +extends: substitution +message: "Use '%s' instead of '%s'." +level: suggestion +ignorecase: true +action: + name: replace +swap: + are not: aren't + cannot: can't + could not: couldn't + did not: didn't + do not: don't + does not: doesn't + has not: hasn't + have not: haven't + how is: how's + is not: isn't + + 'it is(?!\.)': it's + 'it''s(?=\.)': it is + + should not: shouldn't + + "that is(?![.,])": that's + 'that''s(?=\.)': that is + + 'they are(?!\.)': they're + 'they''re(?=\.)': they are + + was not: wasn't + + 'we are(?!\.)': we're + 'we''re(?=\.)': we are + + 'we have(?!\.)': we've + 'we''ve(?=\.)': we have + + were not: weren't + + 'what is(?!\.)': what's + 'what''s(?=\.)': what is + + 'when is(?!\.)': when's + 'when''s(?=\.)': when is + + 'where is(?!\.)': where's + 'where''s(?=\.)': where is + + will not: won't +tests: + - name: fires + input: > + Do not restart the host. It is not safe, and you cannot undo it. + want: | + 1:1:Std.Grammar.Contractions:Use 'don't' instead of 'Do not'. + 1:26:Std.Grammar.Contractions:Use 'it's' instead of 'It is'. + 1:50:Std.Grammar.Contractions:Use 'can't' instead of 'cannot'. + + - name: clean + input: > + Don't restart the host. It isn't safe. + want: "" diff --git a/vale/styles/Std/Grammar/PassiveVoice.yml b/vale/styles/Std/Grammar/PassiveVoice.yml new file mode 100644 index 0000000000..5e8998737a --- /dev/null +++ b/vale/styles/Std/Grammar/PassiveVoice.yml @@ -0,0 +1,200 @@ +# Extracted from errata-ai/Google (MIT). See NOTICE. +# +# The `raw` prefix anchors on an auxiliary; the token list is every irregular +# past participle plus the regular `-ed` form. Rebuilding this list is the work +# this rule exists to save. +extends: existence +message: "'%s' looks like passive voice." +level: suggestion +ignorecase: true +raw: + - \b(am|are|were|being|is|been|was|be)\b\s* +tokens: + - '[\w]+ed' + - awoken + - beat + - become + - been + - begun + - bent + - beset + - bet + - bid + - bidden + - bitten + - bled + - blown + - born + - bought + - bound + - bred + - broadcast + - broken + - brought + - built + - burnt + - burst + - cast + - caught + - chosen + - clung + - come + - cost + - crept + - cut + - dealt + - dived + - done + - drawn + - dreamt + - driven + - drunk + - dug + - eaten + - fallen + - fed + - felt + - fit + - fled + - flown + - flung + - forbidden + - foregone + - forgiven + - forgotten + - forsaken + - fought + - found + - frozen + - given + - gone + - gotten + - ground + - grown + - heard + - held + - hidden + - hit + - hung + - hurt + - kept + - knelt + - knit + - known + - laid + - lain + - leapt + - learnt + - led + - left + - lent + - let + - lighted + - lost + - made + - meant + - met + - misspelt + - mistaken + - mown + - overcome + - overdone + - overtaken + - overthrown + - paid + - pled + - proven + - put + - quit + - read + - rid + - ridden + - risen + - run + - rung + - said + - sat + - sawn + - seen + - sent + - set + - sewn + - shaken + - shaven + - shed + - shod + - shone + - shorn + - shot + - shown + - shrunk + - shut + - slain + - slept + - slid + - slit + - slung + - smitten + - sold + - sought + - sown + - sped + - spent + - spilt + - spit + - split + - spoken + - spread + - sprung + - spun + - stolen + - stood + - stridden + - striven + - struck + - strung + - stuck + - stung + - stunk + - sung + - sunk + - swept + - swollen + - sworn + - swum + - swung + - taken + - taught + - thought + - thrived + - thrown + - thrust + - told + - torn + - trodden + - understood + - upheld + - upset + - wed + - wept + - withheld + - withstood + - woken + - won + - worn + - wound + - woven + - written + - wrung +tests: + - name: fires + input: > + The file was deleted by the installer. Mistakes were made. + want: | + 1:10:Std.Grammar.PassiveVoice:'was deleted' looks like passive voice. + 1:49:Std.Grammar.PassiveVoice:'were made' looks like passive voice. + + - name: clean + input: > + The installer deleted the file. + want: "" diff --git a/vale/styles/Std/LICENSE b/vale/styles/Std/LICENSE new file mode 100644 index 0000000000..b61c4e125f --- /dev/null +++ b/vale/styles/Std/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Joseph Kato + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vale/styles/Std/NOTICE b/vale/styles/Std/NOTICE new file mode 100644 index 0000000000..98d87fec3a --- /dev/null +++ b/vale/styles/Std/NOTICE @@ -0,0 +1,22 @@ +Std +Copyright (c) 2026 Joseph Kato and contributors + +Every rule in this package was extracted from an existing MIT-licensed Vale +style rather than written fresh; the point of the package is that these +patterns are already proven. Sources: + + - errata-ai/Google (MIT, Copyright (c) Joseph Kato): + Grammar.PassiveVoice, Usage.FirstPersonPlural, + Abbreviations.Acronyms, DateTime.TimeFormat, DateTime.DateFormat, + Usage.GenderedPronouns, Punctuation.OxfordComma, and the base of + Abbreviations.Latin, Punctuation.Ellipses, and Usage.GenderedTerms. + - errata-ai/Microsoft (MIT, Copyright (c) 2018-2019 Joseph Kato): + Usage.FirstPersonSingular, Grammar.Contractions, + Punctuation.Spacing, and entries in Usage.GenderedTerms. + - errata-ai/IBM (MIT): + Readability.SentenceLength, and entries in Abbreviations.Latin and + Punctuation.Ellipses. + +Messages and levels were neutralized; each file names its source in a header +comment. The Google and Microsoft styles are themselves implementations of +their respective public style guides. diff --git a/vale/styles/Std/Punctuation/Ellipses.yml b/vale/styles/Std/Punctuation/Ellipses.yml new file mode 100644 index 0000000000..160273a2bd --- /dev/null +++ b/vale/styles/Std/Punctuation/Ellipses.yml @@ -0,0 +1,24 @@ +# Extracted from errata-ai/Google and errata-ai/IBM (MIT). See NOTICE. +# +# The union: IBM adds the Unicode ellipsis, which everyone should catch. +extends: existence +message: "Ellipsis." +level: suggestion +nonword: true +action: + name: remove +tokens: + - '\.\.\.' + - '…' +tests: + - name: fires + input: > + Wait for the build to finish... it can take a while… really. + want: | + 1:29:Std.Punctuation.Ellipses:Ellipsis. + 1:52:Std.Punctuation.Ellipses:Ellipsis. + + - name: clean + input: > + Wait for the build to finish. It can take a while. + want: "" diff --git a/vale/styles/Std/Punctuation/OxfordComma.yml b/vale/styles/Std/Punctuation/OxfordComma.yml new file mode 100644 index 0000000000..79c2d17f5d --- /dev/null +++ b/vale/styles/Std/Punctuation/OxfordComma.yml @@ -0,0 +1,50 @@ +# Extracted from errata-ai/Google (MIT). See NOTICE. +# +extends: existence +message: "Missing serial comma before '%s'." +scope: sentence +level: suggestion +nonword: true +# List items may be several words long, not just one. Four guards keep the +# false-positive rate down: +# +# 1. The comma can't be the one closing a fronted subordinate clause +# ('When your alarm rings, you turn it off and tumble out of bed.') -- +# that comma separates clauses, not list items. Only the first comma of +# such a sentence is exempt, so 'When it rains, apples, pears or bananas +# get wet.' is still caught. +# 2. The item can't open with a clause-introducer (', which ...', +# ', specifically ...'). +# 3. The item can't open with a subject pronoun followed by a verb, which +# marks a compound predicate rather than a list ('..., you walk to the +# fridge and get a snack.'). A pronoun directly followed by 'and'/'or' +# is a real list item, so ', you and me.' still matches. +# 4. Neither item may contain an auxiliary verb, which is another compound +# predicate signal (', it has some downsides and is officially +# discouraged.'). +# +# The trailing anchor allows end-of-scope so list fragments ('Apples, pears +# or bananas') are still caught. +# +# Guard 4 alone would also silence a list serving as the sentence's subject +# ('Cats, dogs or birds have owners.'), since the predicate's auxiliary sits +# inside the would-be second item. The second token handles that shape: a +# sentence-initial list may end right before an auxiliary verb, provided the +# opener is not an adverbial or subordinator and the final item is short -- +# a subordinate clause needs conjunction plus subject before its verb, so a +# two-word cap keeps compound predicates ('restarts, retries or fails when +# limits are reached') out. +tokens: + - '(? + The installer copies binaries, styles and vocabularies. + want: | + 1:30:Std.Punctuation.OxfordComma:Missing serial comma before ', styles and vocabularies.'. + + - name: clean + input: > + The installer copies binaries, styles, and vocabularies. + want: "" diff --git a/vale/styles/Std/Punctuation/Spacing.yml b/vale/styles/Std/Punctuation/Spacing.yml new file mode 100644 index 0000000000..b8b61a20b2 --- /dev/null +++ b/vale/styles/Std/Punctuation/Spacing.yml @@ -0,0 +1,26 @@ +# Extracted from errata-ai/Microsoft (MIT). See NOTICE. +# +# Microsoft's token set: the period case requires a lowercase-initial word so +# dotted identifiers ('System.Text.Json') aren't flagged; '?' and '!' don't +# occur in identifiers, so they stay permissive. +extends: existence +message: "'%s' should have one space." +level: suggestion +nonword: true +tokens: + - '[a-z][.?!] {2,}[A-Z]' + - '\b[a-z]\w*\.[A-Z]' + - '\w[?!][A-Z]' +tests: + - name: fires + input: > + Restart the host.Then check the logs. Every time!Always. + want: | + 1:13:Std.Punctuation.Spacing:'host.T' should have one space. + 1:36:Std.Punctuation.Spacing:'s. E' should have one space. + 1:49:Std.Punctuation.Spacing:'e!A' should have one space. + + - name: clean + input: > + Restart the host. Then check the logs. + want: "" diff --git a/vale/styles/Std/Readability/SentenceLength.yml b/vale/styles/Std/Readability/SentenceLength.yml new file mode 100644 index 0000000000..1f64b0ac32 --- /dev/null +++ b/vale/styles/Std/Readability/SentenceLength.yml @@ -0,0 +1,21 @@ +# Extracted from errata-ai/IBM (MIT). See NOTICE. +# +# The message carries the count, not the threshold, so a child overriding +# `max` doesn't inherit a number that no longer matches its own condition. +extends: occurrence +message: "Long sentence: %d words." +level: suggestion +scope: sentence +max: 25 +token: \b(\w+)\b +tests: + - name: fires + input: > + This sentence keeps going and going with clause after clause after clause so that it sails far past the twenty-five word threshold the rule enforces by default here. + want: | + 1:1:Std.Readability.SentenceLength:Long sentence: 29 words. + + - name: clean + input: > + This sentence stays short. + want: "" diff --git a/vale/styles/Std/Usage/FirstPersonPlural.yml b/vale/styles/Std/Usage/FirstPersonPlural.yml new file mode 100644 index 0000000000..abba4aada1 --- /dev/null +++ b/vale/styles/Std/Usage/FirstPersonPlural.yml @@ -0,0 +1,25 @@ +# Extracted from errata-ai/Google (MIT). See NOTICE. +# +extends: existence +message: "First-person plural: '%s'." +level: suggestion +ignorecase: true +tokens: + - we + - we'(?:ve|re) + - ours? + - us + - let's +tests: + - name: fires + input: > + We recommend restarting. Let's begin, and the choice is ours. + want: | + 1:1:Std.Usage.FirstPersonPlural:First-person plural: 'We'. + 1:26:Std.Usage.FirstPersonPlural:First-person plural: 'Let's'. + 1:57:Std.Usage.FirstPersonPlural:First-person plural: 'ours'. + + - name: clean + input: > + Restarting is recommended. + want: "" diff --git a/vale/styles/Std/Usage/FirstPersonSingular.yml b/vale/styles/Std/Usage/FirstPersonSingular.yml new file mode 100644 index 0000000000..6495b7e190 --- /dev/null +++ b/vale/styles/Std/Usage/FirstPersonSingular.yml @@ -0,0 +1,31 @@ +# Extracted from errata-ai/Microsoft (MIT). See NOTICE. +# +# Microsoft's token set (the superset: I'd, I'll, I've) with the lookaround +# refinement both packages converged on -- consuming the space around 'I' made +# the alert span too wide in editors, and `nonword` would block project Vocabs. +extends: existence +message: "First-person singular: '%s'." +level: suggestion +ignorecase: true +tokens: + - '(?<=^|\s)I(?=[\s,])' + - "\\bI'd\\b" + - "\\bI'll\\b" + - "\\bI'm\\b" + - "\\bI've\\b" + - \bme\b + - \bmy\b + - \bmine\b +tests: + - name: fires + input: > + I think you should restart. My preference is TLS, and I'll explain why. + want: | + 1:1:Std.Usage.FirstPersonSingular:First-person singular: 'I'. + 1:29:Std.Usage.FirstPersonSingular:First-person singular: 'My'. + 1:55:Std.Usage.FirstPersonSingular:First-person singular: 'I'll'. + + - name: clean + input: > + You should restart. TLS is preferred. + want: "" diff --git a/vale/styles/Std/Usage/GenderedPronouns.yml b/vale/styles/Std/Usage/GenderedPronouns.yml new file mode 100644 index 0000000000..df43fb105b --- /dev/null +++ b/vale/styles/Std/Usage/GenderedPronouns.yml @@ -0,0 +1,21 @@ +# Extracted from errata-ai/Google (MIT). See NOTICE. +# +extends: existence +message: "'%s' is not a gender-neutral pronoun." +level: suggestion +ignorecase: true +tokens: + - he/she + - s/he + - \(s\)he +tests: + - name: fires + input: > + Each user should check his/her settings, or s/he can ask an admin. + want: | + 1:45:Std.Usage.GenderedPronouns:'s/he' is not a gender-neutral pronoun. + + - name: clean + input: > + Users should check their settings. + want: "" diff --git a/vale/styles/Std/Usage/GenderedTerms.yml b/vale/styles/Std/Usage/GenderedTerms.yml new file mode 100644 index 0000000000..64736851f3 --- /dev/null +++ b/vale/styles/Std/Usage/GenderedTerms.yml @@ -0,0 +1,65 @@ +# Extracted from errata-ai/Google and errata-ai/Microsoft (MIT). See NOTICE. +# +extends: substitution +message: "Consider '%s' instead of '%s'." +level: suggestion +ignorecase: true +action: + name: replace +swap: + (?:alumnae|alumni): graduates + (?:alumna|alumnus): graduate + air(?:m[ae]n|wom[ae]n): pilot(s) + anchor(?:m[ae]n|wom[ae]n): anchor(s) + authoress: author + camera(?:m[ae]n|wom[ae]n): camera operator(s) + chair(?:m[ae]n|wom[ae]n): chair + door(?:m[ae]|wom[ae]n): concierge(s) + draft(?:m[ae]n|wom[ae]n): drafter(s) + fire(?:m[ae]n|wom[ae]n): firefighter(s) + fisher(?:m[ae]n|wom[ae]n): fisher(s) + fresh(?:m[ae]n|wom[ae]n): first-year student(s) + garbage(?:m[ae]n|wom[ae]n): waste collector(s) + lady lawyer: lawyer + ladylike: courteous + mail(?:m[ae]n|wom[ae]n): mail carriers + man and wife: husband and wife + man enough: strong enough + mankind: humankind + manmade: manufactured + manpower: workforce + mans: operates + middle(?:m[ae]n|wom[ae]n): intermediary + news(?:m[ae]n|wom[ae]n): journalist(s) + ombuds(?:man|woman): ombuds + oneupmanship: upstaging + poetess: poet + police(?:m[ae]n|wom[ae]n): police officer(s) + repair(?:m[ae]n|wom[ae]n): technician(s) + sales(?:m[ae]n|wom[ae]n): salesperson or sales people + service(?:m[ae]n|wom[ae]n): soldier(s) + steward(?:ess)?: flight attendant + tribes(?:m[ae]n|wom[ae]n): tribe member(s) + waitress: waiter + woman doctor: doctor + woman scientist[s]?: scientist(s) + work(?:m[ae]n|wom[ae]n): worker(s) +tests: + - name: fires + input: > + The chairman asked the firemen about manpower for mankind. + want: | + 1:5:Std.Usage.GenderedTerms:Consider 'chair' instead of 'chairman'. + 1:24:Std.Usage.GenderedTerms:Consider 'firefighter(s)' instead of 'firemen'. + 1:38:Std.Usage.GenderedTerms:Consider 'workforce' instead of 'manpower'. + 1:51:Std.Usage.GenderedTerms:Consider 'humankind' instead of 'mankind'. + + - name: clean + input: > + The chair asked the firefighters about workforce needs. + want: "" + + - name: name is a word + input: > + Enter your name in the form. + want: "" diff --git a/vale/styles/Std/meta.json b/vale/styles/Std/meta.json new file mode 100644 index 0000000000..64f2b1afed --- /dev/null +++ b/vale/styles/Std/meta.json @@ -0,0 +1,4 @@ +{ + "feed": "https://github.com/vale-cli/Std/releases.atom", + "vale_version": ">=3.20.0" +}