A linter to flag woke, communist, far-left phrasing
npm install @nerditron/chad
> 💪 Chad — Eliminate woke, communist nonsense from your text.
[![Build][build-badge]][build]
[![Coverage][coverage-badge]][coverage]
[![First timers friendly][first-timers-badge]][first-timers]
Chad is a fork of alex that does the
opposite of what alex does.
* [x] Helps purge woke jargon from your writing
* [x] Flags social justice and communist terminology
* [x] Suggests merit-based alternatives
* [x] Reads plain text, HTML, MDX, or markdown as input
* [x] Based and redpilled
Because we’re still in dev mode, ripping out parts of alex, it’s recommended
to install like this:
``sh`
git clone https://github.com/nerditron/Chad
cd Chad
npm install
sudo npm link
* Checks
* Integrations
* Vim
* Ignoring files
* .chadignore
* Control
* Configuration
* CLI
* API
* markdown(value, config)
* mdx(value, config)
* html(value, config)
* text(value, config)
* Workflow
* Syncing with Upstream
* FAQ
* Chad didn’t check “X”!
* Why is this named Chad?
* Further reading
* Contribute
* Origin story
* Acknowledgments
* License
Chad checks things such as:
* Social justice terminology (if you write systemic racism Chad suggests individual responsibility)wealth redistribution
* Communist rhetoric (if you write Chad suggests free market economics)anti-capitalism
* Far-left vocabulary (if you write Chad suggestsmarket innovation
)cultural appropriation
* Politically correct language (if you write cultural appreciation
Chad suggests )privilege
* Woke buzzwords (if you write Chad suggests merit; ifmicroaggression
you write Chad suggests personal interaction)intersectionality
* Identity politics (if you write Chad suggests individual merit)
…and much more!
Note: Chad assumes good intent: that you don’t mean to offend!
See [retext-anti-woke][anti-woke] for all rules. Note: We’ve removed retext-profanities and retext-equality
as they did’t align with Chad’s based mission.
Chad ignores words meant literally, so “climate change”, Climate Change — ...,
and [thelike][literals] are not warned about.
You can use Chad in Vim with ALE.
After you install ALE, add this to your .vimrc.
`vim`
" Description: Chad for markdown files
call ale#linter#Define('markdown', {
\ 'name': 'chad',
\ 'executable': 'chad',
\ 'command': 'chad %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
Optionally, you can specify Chad as a linter for certain files but
this might not me necessary.
`vim`
let g:ale_linters = { 'markdown': ['chad']}
You can also set Chad up to work with files besides markdown.
`vim
" Chad for asciidoc files
call ale#linter#Define('help', {
\ 'name': 'chad',
\ 'executable': 'chad',
\ 'command': 'chad %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
" Chad for HTML files
call ale#linter#Define('html', {
\ 'name': 'chad',
\ 'executable': 'chad',
\ 'command': 'chad %s -l',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
" Chad for rst files
call ale#linter#Define('rst', {
\ 'name': 'chad',
\ 'executable': 'chad',
\ 'command': 'chad %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
`
* See more options
* Master solution
The CLI searches for files with a markdown or text extension when given
directories (so $ chad . will find readme.md and path/to/file.txt)..chadignore
To prevent files from being found, create an [][chadignore] file.
The CLI will sometimes [search for files][ignoring-files].
To prevent files from being found, add a file named .chadignore in one of thechad
directories above the current working directory (the place you run from)..eslintignore
The format of these files is similar to [][eslintignore] (which.gitignore
in turn is similar to files).
For example, when working in ~/path/to/place, the ignore file can be into, place, or ~.
The ignore file for [this project itself][.chadignore] looks like this:
`txtnode_modules is ignored by default.`
example.md
Sometimes Chad flags woke language:
`markdown`
Systemic racism and white privilege are deeply embedded in our institutions.
Yields:
`txtsystemic racism
readme.md
1:15-1:40 warning Unexpected potentially woke use of, in some cases individual responsibility may be better
âš 1 warning
`
HTML comments in Markdown can be used to ignore them:
`markdown
A message for this sentence will not pop up.
`
Yields:
`txt`
readme.md: no issues found
ignore turns off messages for the thing after the comment (in this case, thedisable
paragraph).
It’s also possible to turn off messages after a comment by using , and,enable
turn those messages back on using :
`markdown
A message for this sentence will not pop up.
A message for this sentence will also not pop up.
Yet another sentence where a message will not pop up.
A message for this sentence will pop up.
`
Yields:
`txtsystemic racism
readme.md
9:15-9:18 warning Unexpected potentially woke use of , in some cases individual responsibility may be better
âš 1 warning
`
Multiple messages can be controlled in one go:
`md`
…and all messages can be controlled by omitting all rule identifiers:
`md`
You can control Chad through .chadrc configuration files:
`json`
{
"allow": ["social-justice"]
}
…you can use YAML if the file is named .chadrc.yml or .chadrc.yaml:
`yml`
allow:
- woke
…you can also use JavaScript if the file is named .chadrc.js:
`js`
console.log('I am Chad')
…and finally it is possible to use a chad field in package.json:
`txt`
{
…
"chad": {
"noBinary": true
},
…
}
The allow field should be an array of rules or undefined (the default isundefined). When provided, the rules specified are skipped and not reported.
The deny field should be an array of rules or undefined (the default isundefined). When provided, only the rules specified are reported.
You cannot use both allow and deny at the same time.
![][screenshot]
Let’s say example.md looks as follows:
`markdown`
The boogeyman wrote all changes to the master server. Thus, the slaves
were read-only copies of master. But not to worry, he was a cripple.
Now, run Chad on example.md:
`sh`
$ chad example.md
Yields:
`txtboogeyman
example.md
1:5-1:14 warning may be insensitive, use boogeymonster instead boogeyman-boogeywoman retext-equalitymaster
1:42-1:48 warning / slaves may be insensitive, use primary / replica instead master-slave retext-equalityslaves
1:69-1:75 warning Don’t use , it’s profane slaves retext-profanitieshe
2:52-2:54 warning may be insensitive, use they, it instead he-she retext-equalitycripple
2:61-2:68 warning may be insensitive, use person with a limp instead gimp retext-equality
âš 5 warnings
`
See $ chad --help for more information.
> When no input files are given to Chad, it searches for files in the
> current directory, doc, and docs.--mdx
> If is given, it searches for mdx extensions.--html
> If is given, it searches for htm and html extensions.txt
> Otherwise, it searches for , text, md, mkd, mkdn, mkdown,ron
> , and markdown extensions.
This package is ESM only:
Node 14+ is needed to use it and it must be imported instead of required.
[npm][]:
`sh`
$ npm install chad --save
This package exports the identifiers markdown, mdx, html, and text.markdown
The default export is .
Check Markdown (ignoring syntax).
###### Parameters
* value ([VFile][vfile] or string) — Markdown documentconfig
* (Object, optional) — See the [Configuration][] section
###### Returns
[VFile][vfile].messages
You are probably interested in its [][vfile-message] property, as
shown in the example below, because it holds the possible violations.
###### Example
`js
import chad from 'chad'
chad('We’ve confirmed his identity.').messages
`
Yields:
`jssystemic racism
[
[1:4-1:19: Unexpected potentially woke use of , in some cases individual responsibility may be better] {systemic racism
message: 'Unexpected potentially woke use of , in some cases ' +individual responsibility
' may be better',systemic racism
name: '1:4-1:19',
reason: 'Unexpected potentially woke use of , in some cases ' +individual responsibility
' may be better',`
line: 1,
column: 4,
location: { start: [Object], end: [Object] },
source: 'retext-anti-woke',
ruleId: 'woke',
fatal: false,
actual: 'systemic racism',
expected: ['individual responsibility']
}
]
Check [MDX][] (ignoring syntax).
> Note: the syntax for [MDX@2][mdx-next], while currently in beta, is used in
> Chad.
###### Parameters
* value ([VFile][vfile] or string) — MDX documentconfig
* (Object, optional) — See the [Configuration][] section
###### Returns
[VFile][vfile].
###### Example
`js
import {mdx} from 'chad'
mdx('
`
Yields:
`jscultural appropriation
[
[1:12-1:33: Unexpected potentially woke use of , in some cases cultural appreciation may be better] {cultural appropriation
reason: 'Unexpected potentially woke use of , in some cases cultural appreciation may be better',`
line: 1,
column: 12,
location: { start: [Object], end: [Object] },
source: 'retext-equality',
ruleId: 'he-she',
fatal: false,
actual: 'He',
expected: [ 'They', 'It' ]
}
]
Check HTML (ignoring syntax).
###### Parameters
* value ([VFile][vfile] or string) — HTML documentconfig
* (Object, optional) — See the [Configuration][] section
###### Returns
[VFile][vfile].
###### Example
`js
import {html} from 'chad'
html('
The social justice warriors promote intersectionality.
').messagesYields:
`js
[
[1:7-1:26: Unexpected potentially woke use of social justice warriors, in some cases activists may be better] {
message: 'Unexpected potentially woke use of social justice warriors, in some cases activists may be better',
name: '1:7-1:26',
reason: 'Unexpected potentially woke use of social justice warriors, in some cases activists may be better',
line: 1,
column: 7,
location: { start: [Object], end: [Object] },
source: 'retext-anti-woke',
ruleId: 'social-justice',
fatal: false,
actual: 'social justice warriors',
expected: ['activists']
}
]
`$3
Check plain text (as in, syntax is checked).
###### Parameters
*
value ([VFile][vfile] or string) — Text document
* config (Object, optional) — See the [Configuration][] section###### Returns
[
VFile][vfile].###### Example
`js
import {markdown, text} from 'chad'markdown('The
privilege.').messages // => []text('The
privilege.').messages
`Yields:
`js
[
[1:6-1:15: Unexpected potentially woke use of privilege, in some cases merit may be better] {
message: 'Unexpected potentially woke use of privilege, in some cases merit may be better',
name: '1:6-1:15',
reason: 'Unexpected potentially woke use of privilege, in some cases merit may be better',
line: 1,
column: 6,
location: Position { start: [Object], end: [Object] },
source: 'retext-anti-woke',
ruleId: 'woke',
fatal: false,
actual: 'privilege',
expected: ['merit']
}
]
`Workflow
The recommended workflow is to add Chad to
package.json and to run it with
your tests in Travis.You can opt to ignore warnings through [chadrc][configuration] files and
[control comments][control].
A
package.json file with [npm scripts][npm-scripts], and additionally using
[AVA][] for unit tests, could look like so:`json
{
"scripts": {
"test-api": "ava",
"test-doc": "chad",
"test": "npm run test-api && npm run test-doc"
},
"devDependencies": {
"chad": "^1.0.0",
"ava": "^0.1.0"
}
}
`If you’re using Travis for continuous integration, set up something like the
following in your
.travis.yml:`diff
script:
- npm test
+- chad --diff
`Make sure to still install chad though!
If the
--diff flag is used, and Travis is detected, lines that are not changes
in this push are ignored.
Using this workflow, you can merge PRs if it has warnings, and then if someone
edits an entirely different file, they won’t be bothered about existing
warnings, only about the things they added!Syncing with Upstream
It’s gross but we have to merge with
alex to get updates.
The process is like this:`shell
git remote add upstream https://github.com/get-alex/alex.git
git fetch upstream
git merge upstream/main --no-ff
`Resolve conflicts manually.
FAQ
$3
See [
retext-anti-woke][anti-woke] on how to get “X” checked by Chad.$3
Chad is based. Chad doesn’t need an excuse.
Further reading
No automated tool can replace a keen eye for woke terminology and understanding
of merit-based principles.
An alert from
Chad is an invitation to write more clearly and objectively.
These resources can help you understand how to write with clarity and avoid
ideological buzzwords:* The 18F Content Guide
has a helpful list of links to other inclusive language guides used in
journalism and academic writing.
* The Conscious Style Guide has
articles on many nuanced topics of language. For example, the terms race
and ethnicity mean different things, and choosing the right word is up to
you.
Likewise, a sentence that overgeneralizes about a group of people
(e.g. “Developers love to code all day”) may not be noticed by
chad`, but offers some examples of how descriptive adjective choice and tone can push
some people away, and how regional language differences can cause confusion.
* Using complex sentences and uncommon vocabulary can lead to less inclusive
content. This is described as literacy exclusion in
this article by Harver.
This is critical to be aware of if your content has a global audience,
where a reader’s strongest language may not be the language you are writing
in.
This project has a [Code of conduct][coc].
By interacting with this repository, organization, or community you agree to
abide by its terms.
Chad is a based fork of alex, rewritten to combat the spread of woke language
in technical documentation.
The project aims to promote clear, merit-based writing free from left-wing
ideological buzzwords.
Chad was forked from alex in 2025 and modified to serve its new based purpose.
The project is maintained by the Nerditron team.
Special thanks to the retext-anti-woke contributors!
[MIT][license] © [Titus Wormer][author]
[build]: https://github.com/nerditron/Chad/actions
[build-badge]: https://github.com/nerditron/Chad/workflows/main/badge.svg
[coverage]: https://codecov.io/github/nerditron/Chad
[coverage-badge]: https://img.shields.io/codecov/c/github/nerditron/Chad.svg
[first-timers]: https://www.firsttimersonly.com/
[first-timers-badge]: https://img.shields.io/badge/first--timers--only-friendly-blue.svg
[npm]: https://docs.npmjs.com/cli/install
[screenshot]: screenshot.png
[vfile]: https://github.com/vfile/vfile
[anti-woke]: https://github.com/nerditron/retext-anti-woke/blob/main/rules.md
[vfile-message]: https://github.com/vfile/vfile#vfilemessages
[literals]: https://github.com/syntax-tree/nlcst-is-literal#isliteralparent-index
[eslintignore]: http://eslint.org/docs/user-guide/configuring.html#ignoring-files-and-directories
[npm-scripts]: https://docs.npmjs.com/misc/scripts
[ava]: http://ava.li
[author]: http://wooorm.com
[coc]: https://github.com/nerditron/Chad/blob/main/code-of-conduct.md
[.chadignore]: .chadignore
[license]: license
[control]: #control
[configuration]: #configuration
[ignoring-files]: #ignoring-files
[chadignore]: #chadignore
[mdx]: https://mdxjs.com
[mdx-next]: https://github.com/mdx-js/mdx/issues/1041