npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ghedev

v1.0.2

Published

Catch insensitive, inconsiderate writing

Downloads

17

Readme

📝 ghedev — Catch insensitive, inconsiderate writing.

Build Coverage First timers friendly

Whether your own or someone else’s writing, ghedev helps you find gender favoring, polarizing, race related, or other unequal phrasing in text.

For example, when We’ve confirmed his identity is given, ghedev will warn you and suggest using their instead of his.

Give ghedev a spin on the Online demo ».

Why

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

Install

Using npm (with Node.js):

$ npm install ghedev --global

Using yarn:

$ yarn global add ghedev

Or you can follow this step-by-step tutorial: [Setting up ghedev in your project][setup-tutorial]

Contents

Checks

ghedev checks things such as:

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

…and much more!

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

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

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

Integrations

next

Ignoring files

The CLI searches for files with a markdown or text extension when given directories (so $ ghedev . will find readme.md and path/to/file.txt). To prevent files from being found, create an .ghedevignore file.

.ghedevignore

The CLI will sometimes search for files. To prevent files from being found, add a file named .ghedevignore in one of the directories above the current working directory (the place you run ghedev 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 looks like this:

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

Control

Sometimes ghedev 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:

<!--ghedev 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:

<!--ghedev 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.

<!--ghedev 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:

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

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

<!--ghedev ignore-->

Configuration

You can control ghedev through .ghedevrc configuration files:

{
  "allow": ["boogeyman-boogeywoman"]
}

…you can use YAML if the file is named .ghedevrc.yml or .ghedevrc.yaml:

allow:
  - dad-mom

…you can also use JavaScript if the file is named .ghedevrc.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 ghedev field in package.json:

{
  …
  "ghedev": {
    "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):

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

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 ghedev on example.md:

$ ghedev 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 $ ghedev --help for more information.

When no input files are given to ghedev, 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 ghedev --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 ghedev from 'ghedev'

ghedev('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 ghedev.

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

VFile.

Example
import {mdx} from 'ghedev'

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 'ghedev'

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 'ghedev'

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 ghedev to package.json and to run it with your tests in Travis.

You can opt to ignore warnings through ghedevrc 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": "ghedev",
    "test": "npm run test-api && npm run test-doc"
  },
  "devDependencies": {
    "ghedev": "^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
+- ghedev --diff

Make sure to still install ghedev 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, ghedev isn’t very smart. People are much better at this. But people make mistakes, and ghedev is there to help.

ghedev didn’t check “X”!

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

Why is this named ghedev?

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 ghedev can be an invitation to learn more. These resources are a launch point for deepening your own understanding and editorial skills beyond what ghedev can offer:

  • 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 [http://github.com/ghepes/ghepes][health] for ways to get started. See [support.md][support] 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][iheany] for [raising the problem][tweet] and [@sindresorhus][sindre] for inspiring me ([@wooorm][wooorm]) to do something about it.

When ghedev launched, it got some traction on [twitter][] and [producthunt][]. Then there was a [lot][tnw] [of][dailydot] [press][vice] [coverage][bustle].

Acknowledgments

Preliminary work for ghedev was done [in 2015][preliminary]. The project was authored by [@wooorm][wooorm].

Lots of [people helped since][contributors]!

License

MIT © Ghepes