📝 alex — Catch insensitive, inconsiderate writing.
[![Build][build-badge]][build] [![Coverage][coverage-badge]][coverage] [![First timers friendly][first-timers-badge]][first-timers]
Whether your own or someone else’s writing, alex helps you find gender favoring, polarizing, race related, or other unequal phrasing in text.
For example, when We’ve confirmed his identity is given, alex will warn
you and suggest using their instead of his.
Give alex a spin on the [Online demo »][demo].
Using [npm][] (with [Node.js][node]):
$ 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][setup-tutorial]
alex checks things such as:
garbageman alex suggests garbage
collector; if you write landlord alex suggests proprietor)like a man alex suggests bravely; if you
write ladylike alex suggests courteous)learning disabled alex suggests person
with learning disabilities)obviously or everyone knows alex
warns about it)master and slave alex suggests
primary and replica)butt 🍑 alex warns about it)…and much more!
Note: alex assumes good intent: that you don’t mean to offend!
See [retext-equality][equality] and [retext-profanities][profanities] for
all rules.
alex ignores words meant literally, so “he”, He — ..., and [the
like][literals] are not warned about.
sindresorhus/SublimeLinter-contrib-alexdustinspecker/gulp-alexkeoghpe/alex-slackyohanmishkin/ember-cli-alexswinton/linter-alexbrown-ccv/alex-recommendsreviewdog/action-alexw0rp/aleskn0tt/alex-browser-extensionstefanjudis/alex-js-contentful-ui-extensionnickradford/figma-plugin-alextlahmann/vscode-alexThe CLI searches for files with a markdown or text extension when given
directories (so $ alex . will find readme.md and path/to/file.txt).
To prevent files from being found, create an [.alexignore][alexignore] file.
.alexignoreThe CLI will sometimes [search for files][ignoring-files].
To prevent files from being found, add a file named .alexignore in one of the
directories above the current working directory (the place you run alex from).
The format of these files is similar to [.eslintignore][eslintignore] (which
in turn is similar to .gitignore files).
For example, when working in ~/path/to/place, the ignore file can be in
to, place, or ~.
The ignore file for [this project itself][.alexignore] 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
ignore turns 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 .alexrc configuration files:
{
"allow": ["boogeyman-boogeywoman"]
}
…you can use YAML if the file is named .alexrc.yml or .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 alex field in package.json:
{
…
"alex": {
"noBinary": true
},
…
}
The allow field should be an array of rules or undefined (the default is
undefined). When provided, the rules specified are skipped and not reported.
The deny field should be an array of rules or undefined (the default is
undefined). When provided, only the rules specified are reported.
You cannot use both allow and deny at the same time.
The noBinary field should be a boolean (the default is false).
When turned on (true), pairs such as he and she and garbageman or
garbagewoman are seen as errors.
When turned off (false, the default), such pairs are okay.
The profanitySureness field is a number (the default is 0).
We use [cuss][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 profanitySureness field is the minimum rating (including) that you want to
check for.
If you set it to 1 (maybe) then it will warn for level 1 and 2 (likely)
profanities, but not for level 0 (unlikely).
![][screenshot]
Let’s say example.md looks 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 --help for 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.
This package is ESM only:
Node 14+ is needed to use it and it must be imported instead of required.
[npm][]:
$ npm install alex --save
This package exports the identifiers markdown, mdx, html, and text.
The default export is markdown.
markdown(value, config)Check Markdown (ignoring syntax).
value ([VFile][vfile] or string) — Markdown documentconfig (Object, optional) — See the [Configuration][] section[VFile][vfile].
You are probably interested in its [messages][vfile-message] property, as
shown in the example below, because it holds the possible violations.
import alex from 'alex'
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' ]
}
]
mdx(value, config)Check [MDX][] (ignoring syntax).
Note: the syntax for [MDX@2][mdx-next], while currently in beta, is used in alex.
value ([VFile][vfile] or string) — MDX documentconfig (Object, optional) — See the [Configuration][] section[VFile][vfile].
import {mdx} from 'alex'
mdx('<Component>He walked to class.</Component>').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' ]
}
]
html(value, config)Check HTML (ignoring syntax).
value ([VFile][vfile] or string) — HTML documentconfig (Object, optional) — See the [Configuration][] section[VFile][vfile].
import {html} from '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' ]
}
]
text(value, config)Check plain text (as in, syntax is checked).
value ([VFile][vfile] or string) — Text documentconfig (Object, optional) — See the [Configuration][] section[VFile][vfile].
import {markdown, text} from 'alex'
markdown('The `boogeyman`.').messages // => []
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.json and to run it with
your tests in Travis.
You can opt to ignore warnings through [alexrc][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