{"id":13394473,"url":"https://github.com/btford/write-good","last_synced_at":"2025-05-13T16:04:55.245Z","repository":{"id":16378067,"uuid":"19128505","full_name":"btford/write-good","owner":"btford","description":"Naive linter for English prose","archived":false,"fork":false,"pushed_at":"2025-03-10T04:04:12.000Z","size":190,"stargazers_count":5000,"open_issues_count":24,"forks_count":190,"subscribers_count":81,"default_branch":"master","last_synced_at":"2025-04-22T11:36:32.803Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/btford.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-04-25T00:15:20.000Z","updated_at":"2025-04-20T07:22:32.000Z","dependencies_parsed_at":"2024-12-24T06:00:28.396Z","dependency_job_id":"832b9ea2-e3da-44cb-a074-e4defb2ac6bb","html_url":"https://github.com/btford/write-good","commit_stats":{"total_commits":132,"total_committers":40,"mean_commits":3.3,"dds":0.6742424242424243,"last_synced_commit":"a602ebb3c178e1c844d44c1acdc9e382c5fd4dc5"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btford%2Fwrite-good","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btford%2Fwrite-good/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btford%2Fwrite-good/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btford%2Fwrite-good/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/btford","download_url":"https://codeload.github.com/btford/write-good/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252590509,"owners_count":21772934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T17:01:20.844Z","updated_at":"2025-05-05T22:46:37.793Z","avatar_url":"https://github.com/btford.png","language":"JavaScript","readme":"# write good [![Build Status](https://travis-ci.org/btford/write-good.svg?branch=master)](https://travis-ci.org/btford/write-good)\n\nNaive linter for English prose for developers who can't write good and wanna learn to do other stuff good too.\n\n\n## Use\n\n```shell\nnpm install write-good\n```\n\n**Important:** Do not use this tool to be a jerk to other people about their writing.\n\n\n## API\n\n`writeGood` is a function that takes a string and returns an array of suggestions.\n\n```javascript\nvar writeGood = require('write-good');\n\nvar suggestions = writeGood('So the cat was stolen.');\n\n// suggestions:\n//\n// [{\n//   reason: \"omit 'So' from the beginning of sentences\",\n//   index: 0, offset: 2\n// }, {\n//   reason: \"'was stolen' is passive voice\",\n//   index: 11, offset: 10\n// }]\n```\n\n`writeGood` takes an optional second argument that allows you to disable certain checks.\n\nYou can disable checking for passive voice like this:\n\n```javascript\nvar writeGood = require('write-good');\n\nvar suggestions = writeGood('So the cat was stolen', { passive: false });\n// suggestions: []\n```\n\nYou can use the second argument's `checks` property to pass in custom checks instead of `write-good`'s default linting configuration.\nLike this, you can check non-English documents, for example with the linter extension for German, [schreib-gut](https://github.com/TimKam/schreib-gut):\n\n\n```javascript\nvar schreibGut = require('schreib-gut');\n\nwriteGood('Aller Wahrscheinlichkeit nach können Entwickler nicht gut schreiben', { weasel-words: false, checks: schreibGut });\n\n// suggestions\n// [{index : 0, offset : 29, reason : '\"Aller Wahrscheinlichkeit nach\" is wordy or unneeded' }]\n```\n\nYou can use the second argument's `whitelist` property to pass in a list of strings to whitelist from suggestions.\nFor example, normally `only` would be picked up as a bad word to use, but you might want to exempt `read-only` from that:\n\n```javascript\nvar writeGood = require('write-good');\n\nvar suggestions = writeGood('Never write read-only sentences.');\n// suggestions: [{ index: 17, offset: 4, reason: '\"only\" can weaken meaning' }]\n\nvar filtered = writeGood('Never write read-only sentences.', { whitelist: ['read-only'] });\n// filtered: []\n\n```\n\n## CLI\n\nYou can use `write-good` as a command-line tool by installing it globally:\n\n```shell\nnpm install -g write-good\n```\n\nIf you have npm version 5.2.0 or later installed, you can use npx to run write-good without installing it:\n\n```shell\nnpx write-good *.md\n```\n\n`write-good` takes a [glob](https://github.com/isaacs/node-glob) and prints suggestions to stdout:\n\n```shell\n$ write-good *.md\n\nIn README.md\n=============\n = writeGood('So the cat was stolen.');\n                         ^^^^^^^^^^\n\"was stolen\" is passive voice on line 20 at column 40\n-------------\n//   suggestion: \"'was stolen' is passive voice\",\n                   ^^^^^^^^^^\n\"was stolen\" is passive voice on line 28 at column 19\n```\n\nYou can run just specific checks like this:\n\n```shell\nwrite-good *.md --weasel --so\n```\n\nOr exclude checks like this:\n\n```shell\nwrite-good *.md --no-passive\n```\n\nOr include checks like this:\n\n```shell\n# E-Prime is disabled by default.\nwrite-good *.md --yes-eprime\n```\n\n**Note:** The ``--yes`` prefix only works for *E-Prime*, because the other checks are included by default, anyway.\n\nYou can run just with text without supplying files:\n\n```shell\nwrite-good --text=\"It should have been defined there.\"\n```\n\nYou can even supply multi-line text:\n\n```shell\nwrite-good --text=\"I can't see a problem there that's not been defined yet.\nShould be defined again.\"\n```\n\nYou can also pass other arguments:\n\n```shell\nwrite-good --text=\"It should have been defined there.\" --no-passive\n```\n\nYou can even fetch output from a remote file:\n\n```shell\nwrite-good --text=\"$(curl https://raw.githubusercontent.com/btford/write-good/master/README.md)\"\n```\n\nUse the ``--parse`` option to activate parse-happy output and a more conventional Unix exit code:\n\n```shell\nwrite-good *.md --parse\n```\n\nTo specify a custom checks extension, for example [schreib-gut](https://github.com/TimKam/schreib-gut), run:\n\n```shell\nnpm install -g schreib-gut\nwrite-good *.md --checks=schreib-gut\n```\n\nTo view all available options use the ``--help`` option:\n\n```shell\nwrite-good --help\n```\n\n## Checks\n\nYou can disable any combination of the following by providing a key with value `false` as the second argument to `writeGood`.\n\n### `passive`\nChecks for passive voice.\n\n### `illusion`\nChecks for lexical illusions – cases where a word is repeated.\n\n### `so`\nChecks for `so` at the beginning of the sentence.\n\n### `thereIs`\nChecks for `there is` or `there are` at the beginning of the sentence.\n\n### `weasel`\nChecks for \"weasel words.\"\n\n### `adverb`\nChecks for adverbs that can weaken meaning: really, very, extremely, etc.\n\n### `tooWordy`\nChecks for wordy phrases and unnecessary words.\n\n### `cliches`\nChecks for common cliches.\n\n### `eprime`\nChecks for [\"to-be\"](https://en.wikipedia.org/wiki/E-Prime) verbs. _Disabled by default_\n\n## Extensions\nUsers can create their own `write-good` language checks. As described above,\nyou can specify such extensions when running `write-good` on the command line\nor calling it in your JavaScript code.\n\nThe following 3rd-party `write-good` extensions are available:\n\n* [schreib-gut](https://github.com/timkam/schreib-gut): A basic extension for\n  the German language\n\nIf you know of any `write-good` extensions that are not in this list, please open a pull request!\n\n### Interface\nAn extension is a Node.js module that exposes an object containing a check\nfunction (``fn``) and an ``explanation`` string for each new check:\n\n```javascript\nmodule.exports = {\n  check1: {\n    fn: function(text) {\n      …\n    },\n    explanation: '…'\n  },\n  check2: {\n    fn: function(text) {\n      …\n    },\n    explanation: '…'\n  }\n}\n```\n\nEach check function takes a string input and determines a list of style\nviolation objects, each with an ``index`` and an ``offset``:\n\n```javascript\n/**\n* @param {text} text  Input text\n* @return {{index:number, offset:number}[]}  List of all violations\n*/\n```\n\nThe ``index`` defines the position of the match in the input text, whereas the\n``offset`` specifies the length of the match.\n\nThe following example extension provides a check that determines if the input\ntext contains a set of forbidden terms (*Tom Riddle* and *Voldemort*):\n\n```javascript\nmodule.exports = {\n  voldemort: {\n    fn: function (text) {\n      var positives = ['Tom Riddle', 'Voldemort']\n      var re = new RegExp('\\\\b(' + positives.join('|') + ')\\\\b', 'gi');\n      var suggestions = [];\n      while (match = re.exec(text)) {\n        suggestions.push({\n          index: match.index,\n          offset: match[0].length,\n        });\n      }\n      return suggestions;\n    },\n    explanation: 'You must not name Him-Who-Must-Not-Be-Named'\n  }\n}\n```\n\n## Docker\n\n### From Dockerhub\n\nYou can also run this application in [Docker](https://www.docker.com). Using a pre-built [image from Dockerhub](https://hub.docker.com/r/hochzehn/write-good/), the write-good can be run with this command:\n\n`docker run --rm --volume $PWD:/app hochzehn/write-good *.md`\n\n### Building locally\n\nOr you can first build the image locally:\n\n`docker build -t btford/write-good .`\n\nAnd then run using:\n\n`docker run -it --rm -v \"$(pwd)\":/srv/app -w /srv/app btford/write-good:latest *.md`\n\n## See also\n\nI came across these resources while doing research to make this module.\nThey might be helpful.\n\n### Code\n\n* [shell script for avoiding \"weasel words\"](http://matt.might.net/articles/shell-scripts-for-passive-voice-weasel-words-duplicates/) – I based my initial implementation on this\n* [Academic Writing Check](https://github.com/devd/Academic-Writing-Check) – a perl script similar to above\n* [writegood mode](https://github.com/bnbeckwith/writegood-mode) for emacs\n* [natural](https://github.com/NaturalNode/natural) – general purpose NLP toolkit in JavaScript\n* [WordNet](http://wordnet.princeton.edu/) – lexical database of the English language\n* [LanguageTool](https://languagetool.org/) – style and grammar checker implemented in Java\n\n### Prose\n\n* [Elements of Style](http://www.bartleby.com/141/)\n* [Flesch–Kincaid readability](http://en.wikipedia.org/wiki/Flesch%E2%80%93Kincaid_readability_test)\n* [Fear and Loathing of the English passive](http://www.lel.ed.ac.uk/~gpullum/passive_loathing.pdf)\n* [Words to Avoid in Educational Writing](http://css-tricks.com/words-avoid-educational-writing/)\n\n### Apps\n\nThis is not an endorsement.\nThese apps have similar functionality that you may find useful.\n\n* [Hemingway App](http://www.hemingwayapp.com/)\n* [Grammarly](https://app.grammarly.com)\n\n## Other projects using write good\n\n* [linter-write-good](https://github.com/gepoch/linter-write-good) for [Atom](https://atom.io/)\n* [Write Good action](https://actions.getdrafts.com/a/1RA) for [Drafts](https://getdrafts.com) iOS App\n* [Write Good](https://github.com/markahesketh/write-good-obsidian/) for [Obsidian](https://obsidian.md/)\n* [Write Good Linter](https://marketplace.visualstudio.com/items?itemName=travisthetechie.write-good-linter) for [Visual Studio Code](https://code.visualstudio.com)\n* [Write Good Linter](https://github.com/Freed-Wu/coc-write-good) for Vim by\n  [coc.nvim](https://github.com/neoclide/coc.nvim)\n* [Vim ALE](https://github.com/w0rp/ale) realtime linter for [Vim](http://www.vim.org/) with included support for write-good.\n* [Write Better](https://github.com/justiceo/write-better) A [Chrome extension](https://chrome.google.com/webstore/detail/write-better/nnnnnpmcdcloafmfkiihafnjidjkfmek) for Google Docs.\n* [Statick](https://github.com/sscpac/statick-md) plugin to combine results with other linters.\n\n## License\nMIT\n","funding_links":[],"categories":["JavaScript","Publishing and Sharing","Other","English ##","\u003ca name=\"writing\"\u003e\u003c/a\u003eWriting","Web development tools","Spell Checking and Linting","Tools \u0026 Services","Uncategorized"],"sub_categories":["Writing","Chess :chess_pawn:","Individual Episodes","Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbtford%2Fwrite-good","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbtford%2Fwrite-good","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbtford%2Fwrite-good/lists"}