Convert Figma logo to code with AI

get-alex logoalex

Catch insensitive, inconsiderate writing

4,811
207
4,811
22

Top Related Projects

4,461

:pencil: A markup-aware linter for prose built with speed and extensibility in mind.

Naive linter for English prose

The pluggable natural language linter for text and markdown.

2,355

natural language processor powered by plugins part of the @unifiedjs collective

4,399

☔️ interface for parsing, inspecting, transforming, and serializing content through syntax trees

Quick Overview

Alex is an open-source linter tool designed to catch insensitive, inconsiderate writing in text. It helps writers identify language that may be polarizing, biased, or offensive, promoting more inclusive communication. Alex can be used as a command-line tool, a JavaScript library, or integrated into various text editors and CI/CD pipelines.

Pros

  • Promotes inclusive and considerate writing
  • Highly customizable with support for custom rules and dictionaries
  • Integrates well with various text editors and development workflows
  • Supports multiple languages and file formats

Cons

  • May produce false positives in certain contexts
  • Requires careful configuration to avoid over-flagging
  • Some users may find it overly prescriptive
  • Limited support for non-English languages

Code Examples

  1. Basic usage as a Node.js module:
import alex from 'alex';

const text = 'The chairman should be careful with his remarks.';
console.log(alex(text).messages);
  1. Using Alex with specific rules:
import alex from 'alex';

const text = 'We'll be working on this for a few days.';
console.log(alex(text, { allow: ['working-days'] }).messages);
  1. Checking a file with Alex:
import fs from 'fs';
import alex from 'alex';

const text = fs.readFileSync('example.md', 'utf8');
console.log(alex(text).messages);

Getting Started

To use Alex in your project, follow these steps:

  1. Install Alex using npm:

    npm install alex --save-dev
    
  2. Add a script to your package.json:

    {
      "scripts": {
        "lint:text": "alex"
      }
    }
    
  3. Run Alex on your files:

    npm run lint:text
    

For more advanced usage and configuration options, refer to the Alex documentation.

Competitor Comparisons

4,461

:pencil: A markup-aware linter for prose built with speed and extensibility in mind.

Pros of Vale

  • More extensive rule set and customization options
  • Supports multiple markup formats (Markdown, AsciiDoc, reStructuredText)
  • Integrates with various text editors and CI/CD pipelines

Cons of Vale

  • Steeper learning curve due to more complex configuration
  • Requires more setup and maintenance compared to Alex
  • May be overkill for simple writing tasks or small projects

Code Comparison

Alex:

const alex = require('alex');
const report = alex('The chairman should be careful.');
console.log(report);

Vale:

StylesPath = styles
MinAlertLevel = suggestion

[*.md]
BasedOnStyles = Vale, proselint

Summary

Vale offers more advanced features and customization options, making it suitable for larger projects or organizations with specific style requirements. Alex, on the other hand, is simpler to use and focuses primarily on inclusive language. Vale supports multiple markup formats and integrates well with various tools, but it requires more setup and maintenance. Alex is more straightforward but may lack some advanced features for complex writing tasks.

Naive linter for English prose

Pros of write-good

  • Focuses on general writing style and clarity
  • Provides suggestions for passive voice, weasel words, and redundancies
  • Lightweight and easy to integrate into various workflows

Cons of write-good

  • Less comprehensive in terms of inclusive language checks
  • Fewer customization options for specific writing styles or preferences
  • Limited support for non-English languages

Code Comparison

write-good:

var writeGood = require('write-good');
var suggestions = writeGood('So the cat was stolen.');
console.log(suggestions);

alex:

import alex from 'alex';
const report = alex('He's pretty set in his ways.');
console.log(report);

Key Differences

  • alex focuses on inclusive and respectful language, while write-good emphasizes general writing improvement
  • alex offers more extensive customization options and supports multiple languages
  • write-good is more lightweight and easier to integrate into simple workflows
  • alex provides more detailed explanations and suggestions for improvements

Use Cases

  • Use write-good for general writing improvement and style checks
  • Choose alex for ensuring inclusive language and addressing potential biases in content
  • Consider using both tools in combination for comprehensive writing analysis

The pluggable natural language linter for text and markdown.

Pros of textlint

  • More flexible and customizable with a plugin system
  • Supports multiple languages beyond English
  • Can be used as a command-line tool, Node.js library, or text editor plugin

Cons of textlint

  • Steeper learning curve due to its extensive configuration options
  • Requires more setup and configuration to achieve similar results to alex
  • May be overkill for simple writing tasks or small projects

Code Comparison

alex:

const alex = require('alex');

alex('He\'s very cranky.').messages;

textlint:

const { TextLintEngine } = require("textlint");
const engine = new TextLintEngine();

engine.executeOnText("He's very cranky.").then(results => {
  console.log(results[0].messages);
});

Both tools aim to improve writing quality, but they differ in approach and scope. Alex focuses specifically on catching insensitive and inconsiderate writing, while textlint is a more general-purpose linting tool for natural language.

Alex is easier to set up and use out of the box, making it ideal for quick checks and smaller projects. It's particularly strong in identifying potentially offensive or exclusive language.

Textlint, on the other hand, offers greater flexibility and customization. Its plugin system allows users to tailor the tool to their specific needs, supporting various writing styles and languages. This makes it more suitable for larger projects or teams with specific style requirements.

2,355

natural language processor powered by plugins part of the @unifiedjs collective

Pros of retext

  • More flexible and extensible ecosystem with various plugins
  • Supports a wider range of text processing tasks beyond just linting
  • Can be used as a foundation for building custom natural language processing tools

Cons of retext

  • Steeper learning curve due to its modular nature
  • Requires more setup and configuration for specific use cases
  • May be overkill for simple text linting tasks

Code comparison

alex:

import alex from 'alex';

console.log(alex('He's pretty set in his ways.').messages);

retext:

import { retext } from 'retext';
import retextEquality from 'retext-equality';

retext()
  .use(retextEquality)
  .process('He's pretty set in his ways.')
  .then((file) => console.log(file.messages));

Summary

Alex is a specialized tool focused on catching insensitive, inconsiderate writing. It's easy to use and provides quick results for identifying potentially offensive language. Retext, on the other hand, is a more comprehensive text processing system that can be customized with various plugins to perform a wide range of natural language processing tasks, including but not limited to linting for inclusive language. While Alex is simpler to set up and use, retext offers greater flexibility and extensibility for more complex text processing needs.

4,399

☔️ interface for parsing, inspecting, transforming, and serializing content through syntax trees

Pros of unified

  • More versatile and extensible ecosystem for processing various content types (Markdown, HTML, natural language)
  • Supports a wider range of plugins and transformations
  • Better suited for complex document processing pipelines

Cons of unified

  • Steeper learning curve due to its more comprehensive nature
  • May be overkill for simpler text analysis tasks
  • Requires more setup and configuration for basic use cases

Code comparison

alex:

import alex from 'alex';

const text = 'The chairman should be careful.';
console.log(alex(text).messages);

unified:

import {unified} from 'unified';
import remarkParse from 'remark-parse';
import remarkRetext from 'remark-retext';
import retextEnglish from 'retext-english';
import retextEquality from 'retext-equality';
import {reporter} from 'vfile-reporter';

unified()
  .use(remarkParse)
  .use(remarkRetext, unified().use(retextEnglish).use(retextEquality))
  .process('The chairman should be careful.')
  .then((file) => {
    console.error(reporter(file));
  });

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

alex

📝 alex — Catch insensitive, inconsiderate writing.

Build Coverage First timers friendly

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 ».

Why

  • Helps to get better at considerate writing
  • Catches many possible offences
  • Suggests helpful alternatives
  • Reads plain text, HTML, MDX, or markdown as input
  • Stylish

Install

Using npm (with Node.js):

$ 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

Contents

Checks

alex checks things such as:

  • Gendered work-titles (if you write garbageman alex suggests garbage collector; if you write landlord alex suggests proprietor)
  • Gendered proverbs (if you write like a man alex suggests bravely; if you write ladylike alex suggests courteous)
  • Ableist language (if you write learning disabled alex suggests person with learning disabilities)
  • Condescending language (if you write obviously or everyone knows alex warns about it)
  • Intolerant phrasing (if you write master and slave alex suggests primary and replica)
  • Profanities (if you write butt 🍑 alex warns about it)

…and much more!

Note: alex assumes good intent: that you don’t mean to offend!

See retext-equality and retext-profanities for all rules.

alex ignores words meant literally, so “he”, He — ..., and the like are not warned about.

Integrations

Ignoring files

The 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 file.

.alexignore

The CLI will sometimes search for 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 (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 looks like this:

# `node_modules` is ignored by default.
example.md

Control

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:

<!--alex ignore dad-mom-->

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:

<!--alex disable dad-mom-->

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.

<!--alex enable dad-mom-->

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:

<!--alex disable he-her his-hers dad-mom-->

…and all messages can be controlled by omitting all rule identifiers:

<!--alex ignore-->

Configuration

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, 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):

RatingUse as a profanityUse in clean textExample
2likelyunlikelyasshat
1maybemaybeaddict
0unlikelylikelybeaver

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).

CLI

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, and docs. If --mdx is given, it searches for mdx extensions. If --html is given, it searches for htm and html extensions. Otherwise, it searches for txt, text, md, mkd, mkdn, mkdown, ron, and markdown extensions.

API

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).

Parameters
  • value (VFile or string) — Markdown document
  • config (Object, optional) — See the Configuration section
Returns

VFile. You are probably interested in its messages property, as shown in the example below, because it holds the possible violations.

Example
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, while currently in beta, is used in alex.

Parameters
  • value (VFile or string) — MDX document
  • config (Object, optional) — See the Configuration section
Returns

VFile.

Example
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).

Parameters
  • value (VFile or string) — HTML document
  • config (Object, optional) — See the Configuration section
Returns

VFile.

Example
import {html} from 'alex'

html('<p class="black">He walked to class.</p>').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).

Parameters
  • value (VFile or string) — Text document
  • config (Object, optional) — See the Configuration section
Returns

VFile.

Example
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' ]
  }
]

Workflow

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 files and control comments.

A package.json file 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 --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!

FAQ

This is stupid!

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.

alex didn’t check “X”!

See contributing.md on how to get “X” checked by alex.

Why is this named alex?

It’s a nice unisex name, it was free on npm, I like it! :smile:

Further reading

No automated tool can replace studying inclusive communication and listening to the lived experiences of others. An error from alex can be an invitation to learn more. These resources are a launch point for deepening your own understanding and editorial skills beyond what alex can offer:

  • 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 alex, but it is not inclusive. A good human editor can step up to the challenge and find a better way to phrase things.

  • Sometimes, the only way to know what is inclusive is to ask. In Disability is a nuanced thing, Nicolas Steenhout writes about how person-first language, such as “a person with a disability,” is not always the right choice.

  • Language is always evolving. A term that is neutral one year ago can be problematic today. Projects like the Self-Defined Dictionary aim to collect the words that we use to define ourselves and others, and connect them with the history and some helpful advice.

  • Unconscious 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.

Contribute

See contributing.md in get-alex/.github for ways to get started. See support.md for 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.

Origin story

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.

Acknowledgments

Preliminary work for alex was done in 2015. The project was authored by @wooorm.

Lots of people helped since!

License

MIT © Titus Wormer

NPM DownloadsLast 30 Days