Catch insensitive, inconsiderate writing
📝 alex — Catch insensitive, inconsiderate writing.
Whether your own or someone else’s writing, alex helps you find gender favoring, polarizing, race related, religion inconsiderate, or other unequal phrasing in text.
For example, when
We’ve confirmed his identityis given, alex will warn you and suggest using
theirinstead of
his.
Give alex a spin on the Online demo ».
$ npm install alex --global
Using yarn:
$ yarn global add alex
Or you can follow this step-by-step tutorial: Setting up alex in your project
alex checks things such as:
garbagemanalex suggests
garbage collector; if you write
landlordalex suggests
proprietor)
like a manalex suggests
bravely; if you write
ladylikealex suggests
courteous)
learning disabledalex suggests
person with learning disabilities)
obviouslyor
everyone knowsalex warns about it)
masterand
slavealex suggests
primaryand
replica)
butt🍑 alex warns about it)
…and much more!
Note: alex assumes good intent: that you don’t mean to offend!
retext-equalityand
retext-profanitiesfor all rules.
alex ignores words meant literally, so
“he”,
He — ..., and the like are not warned about.
get-alex/atom-linter-alex
sindresorhus/SublimeLinter-contrib-alex
dustinspecker/gulp-alex
keoghpe/alex-slack
yohanmishkin/ember-cli-alex
swinton/linter-alex
brown-ccv/alex-recommends
reviewdog/action-alex
w0rp/ale
skn0tt/alex-browser-extension
stefanjudis/alex-js-contentful-ui-extension
nickradford/figma-plugin-alex
tlahmann/vscode-alex
The CLI searches for files with a markdown or text extension when given directories (so
$ alex .will find
readme.mdand
path/to/file.txt). To prevent files from being found, create an
.alexignorefile.
.alexignore
The CLI will sometimes search for files. To prevent files from being found, add a file named
.alexignorein one of the directories above the current working directory (the place you run
alexfrom). The format of these files is similar to
.eslintignore(which in turn is similar to
.gitignorefiles).
For example, when working in
~/path/to/place, the ignore file can be in
to,
place, or
~.
The ignore file for this project itself looks like this:
# `node_modules` is ignored by default. example.md
Sometimes alex makes mistakes:
A message for this sentence will pop up.
Yields:
readme.md 1:15-1:18 warning `pop` may be insensitive, use `parent` instead dad-mom retext-equality⚠ 1 warning
HTML comments in Markdown can be used to ignore them:
A message for this sentence will not pop up.
Yields:
readme.md: no issues found
ignoreturns off messages for the thing after the comment (in this case, the paragraph). It’s also possible to turn off messages after a comment by using
disable, and, turn those messages back on using
enable:
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:
readme.md 9:15-9:18 warning `pop` may be insensitive, use `parent` instead dad-mom retext-equality⚠ 1 warning
Multiple messages can be controlled in one go:
…and all messages can be controlled by omitting all rule identifiers:
You can control alex through
.alexrcconfiguration files:
{ "allow": ["boogeyman-boogeywoman"] }
…you can use YAML if the file is named
.alexrc.ymlor
.alexrc.yaml:
allow: - dad-mom
…you can also use JavaScript if the file is named
.alexrc.js:
// But making it random like this is a bad idea! exports.profanitySureness = Math.floor(Math.random() * 3)
…and finally it is possible to use an
alexfield in
package.json:
{ … "alex": { "noBinary": true }, … }
The
allowfield should be an array of rules or
undefined(the default is
undefined). When provided, the rules specified are skipped and not reported.
The
denyfield should be an array of rules or
undefined(the default is
undefined). When provided, only the rules specified are reported.
You cannot use both
allowand
denyat the same time.
The
noBinaryfield should be a boolean (the default is
false). When turned on (
true), pairs such as
he and sheand
garbageman or garbagewomanare seen as errors. When turned off (
false, the default), such pairs are okay.
The
profanitySurenessfield is a number (the default is
0). We use
cuss, which has a dictionary of words that have a rating between 0 and 2 of how likely it is that a word or phrase is a profanity (not how “bad” it is):
| Rating | Use as a profanity | Use in clean text | Example | | ------ | ------------------ | ----------------- | ------- | | 2 | likely | unlikely | asshat | | 1 | maybe | maybe | addict | | 0 | unlikely | likely | beaver |
The
profanitySurenessfield is the minimum rating (including) that you want to check for. If you set it to
1(maybe) then it will warn for level
1and
2(likely) profanities, but not for level
0(unlikely).
Let’s say
example.mdlooks as follows:
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 alex on
example.md:
$ alex example.md
Yields:
example.md 1:5-1:14 warning `boogeyman` may be insensitive, use `boogeymonster` instead boogeyman-boogeywoman retext-equality 1:42-1:48 warning `master` / `slaves` may be insensitive, use `primary` / `replica` instead master-slave retext-equality 1:69-1:75 warning Don’t use `slaves`, it’s profane slaves retext-profanities 2:52-2:54 warning `he` may be insensitive, use `they`, `it` instead he-she retext-equality 2:61-2:68 warning `cripple` may be insensitive, use `person with a limp` instead gimp retext-equality⚠ 5 warnings
See
$ alex --helpfor more information.
When no input files are given to alex, it searches for files in the current directory,
doc, anddocs. If--mdxis given, it searches formdxextensions. If--htmlis given, it searches forhtmandhtmlextensions. Otherwise, it searches fortxt,text,md,mkd,mkdn,mkdown,ron, andmarkdownextensions.
npm:
$ npm install alex --save
alex is also available as an AMD, CommonJS, and globals module, uncompressed and compressed.
alex(value, config)
alex.markdown(value, config)
Check Markdown (ignoring syntax).
value(
VFileor
string) — Markdown document
config(
Object, optional) — See the Configuration section
VFile. You are probably interested in its
messagesproperty, as shown in the example below, because it holds the possible violations.
alex('We’ve confirmed his identity.').messages
Yields:
[ [1:17-1:20: `his` may be insensitive, when referring to a person, use `their`, `theirs`, `them` instead] { message: '`his` may be insensitive, when referring to a ' + 'person, use `their`, `theirs`, `them` instead', name: '1:17-1:20', reason: '`his` may be insensitive, when referring to a ' + 'person, use `their`, `theirs`, `them` instead', line: 1, column: 17, location: { start: [Object], end: [Object] }, source: 'retext-equality', ruleId: 'her-him', fatal: false, actual: 'his', expected: [ 'their', 'theirs', 'them' ] } ]
alex.mdx(value, config)
Check MDX (ignoring syntax).
Note: the syntax for [email protected], while currently in beta, is used in alex.
value(
VFileor
string) — MDX document
config(
Object, optional) — See the Configuration section
VFile.
alex.mdx('He walked to class.').messages
Yields:
[ [1:12-1:14: `He` may be insensitive, use `They`, `It` instead] { reason: '`He` may be insensitive, use `They`, `It` instead', line: 1, column: 12, location: { start: [Object], end: [Object] }, source: 'retext-equality', ruleId: 'he-she', fatal: false, actual: 'He', expected: [ 'They', 'It' ] } ]
alex.html(value, config)
Check HTML (ignoring syntax).
value(
VFileor
string) — HTML document
config(
Object, optional) — See the Configuration section
VFile.
alex.html('He walked to class.
').messages
Yields:
[ [1:18-1:20: `He` may be insensitive, use `They`, `It` instead] { message: '`He` may be insensitive, use `They`, `It` instead', name: '1:18-1:20', reason: '`He` may be insensitive, use `They`, `It` instead', line: 1, column: 18, location: { start: [Object], end: [Object] }, source: 'retext-equality', ruleId: 'he-she', fatal: false, actual: 'He', expected: [ 'They', 'It' ] } ]
alex.text(value, config)
Check plain text (as in, syntax is checked).
value(
VFileor
string) — Text document
config(
Object, optional) — See the Configuration section
VFile.
alex('The `boogeyman`.').messages // => []alex.text('The
boogeyman
.').messages
Yields:
[ [1:6-1:15: `boogeyman` may be insensitive, use `boogeymonster` instead] { message: '`boogeyman` may be insensitive, use `boogeymonster` instead', name: '1:6-1:15', reason: '`boogeyman` may be insensitive, use `boogeymonster` instead', line: 1, column: 6, location: Position { start: [Object], end: [Object] }, source: 'retext-equality', ruleId: 'boogeyman-boogeywoman', fatal: false, actual: 'boogeyman', expected: [ 'boogeymonster' ] } ]
The recommended workflow is to add alex to
package.jsonand to run it with your tests in Travis.
You can opt to ignore warnings through alexrc files and control comments.
A
package.jsonfile with npm scripts, and additionally using AVA for unit tests, could look like so:
{ "scripts": { "test-api": "ava", "test-doc": "alex", "test": "npm run test-api && npm run test-doc" }, "devDependencies": { "alex": "^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:
script: - npm test +- alex --diff
Make sure to still install alex though!
If the
--diffflag 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!
Not a question. And yeah, alex isn’t very smart. People are much better at this. But people make mistakes, and alex is there to help.
contributing.mdon how to get “X” checked by alex.
It’s a nice unisex name, it was free on npm, I like it! :smile:
No automated tool can replace studying inclusive communication and listening to the lived experiences of others. An error from
alexcan be an invitation to learn more. These resources are a launch point for deepening your own understanding and editorial skills beyond what
alexcan offer:
alex, but it is not inclusive. A good human editor can step up to the challenge and find a better way to phrase things.
Unconsious bias is present in daily decisions and conversations and can show up in writing. Textio
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.
contributing.mdin
get-alex/.githubfor ways to get started. See
support.mdfor ways to get help.
This project has a Code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.
Thanks to @iheanyi for raising the problem and @sindresorhus for inspiring me (@wooorm) to do something about it.
When alex launched, it got some traction on twitter and producthunt. Then there was a lot of press coverage.
Preliminary work for alex was done in 2015. The project was authored by @wooorm.
Lots of people helped since!