• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

bin/H03-May-2022-

lib/H03-May-2022-

node_modules/H01-Jan-1970-338,577287,416

test/H03-May-2022-4024

.dockerignoreH A D16-Feb-202180 98

.eslintrcH A D16-Feb-2021133 109

.gitignoreH A D16-Feb-2021229 1914

.npmignoreH A D16-Feb-202123 21

.pre-commit-hooks.yamlH A D16-Feb-2021181 87

.travis.ymlH A D16-Feb-202152 65

DockerfileH A D16-Feb-2021154 76

LICENSEH A D16-Feb-20211.1 KiB2217

README.mdH A D16-Feb-20219.2 KiB326228

package-lock.jsonH A D16-Feb-2021130.6 KiB3,6293,628

package.jsonH A D16-Feb-20211.6 KiB7574

README.md

1# write good [![Build Status](https://travis-ci.org/btford/write-good.svg?branch=master)](https://travis-ci.org/btford/write-good)
2
3Naive linter for English prose for developers who can't write good and wanna learn to do other stuff good too.
4
5
6## Use
7
8```shell
9npm install write-good
10```
11
12**Important:** Do not use this tool to be a jerk to other people about their writing.
13
14
15## API
16
17`writeGood` is a function that takes a string and returns an array of suggestions.
18
19```javascript
20var writeGood = require('write-good');
21
22var suggestions = writeGood('So the cat was stolen.');
23
24// suggestions:
25//
26// [{
27//   reason: "omit 'So' from the beginning of sentences",
28//   index: 0, offset: 2
29// }, {
30//   reason: "'was stolen' is passive voice",
31//   index: 11, offset: 10
32// }]
33```
34
35`writeGood` takes an optional second argument that allows you to disable certain checks.
36
37You can disable checking for passive voice like this:
38
39```javascript
40var writeGood = require('write-good');
41
42var suggestions = writeGood('So the cat was stolen', { passive: false});
43// suggestions: []
44```
45
46You can use the second argument's `checks` property to pass in custom checks instead of `write-good`'s default linting configuration.
47Like this, you can check non-English documents, for example with the linter extension for German, [schreib-gut](https://github.com/TimKam/schreib-gut):
48
49
50```javascript
51var schreibGut = require('schreib-gut');
52
53writeGood('Aller Wahrscheinlichkeit nach können Entwickler nicht gut schreiben', { weasel-words: false, checks: schreibGut});
54
55// suggestions
56// [{index : 0, offset : 29, reason : '"Aller Wahrscheinlichkeit nach" is wordy or unneeded' }]
57```
58
59You can use the second argument's `whitelist` property to pass in a list of strings to whitelist from suggestions.
60For example, normally `only` would be picked up as a bad word to use, but you might want to exempt `read-only` from that:
61
62```javascript
63var writeGood = require('write-good');
64
65var suggestions = writeGood('Never write read-only sentences.');
66// suggestions: [{ index: 17, offset: 4, reason: '"only" can weaken meaning' }]
67
68var filtered = writeGood('Never write read-only sentences.', { whitelist: ['read-only'] });
69// filtered: []
70
71```
72
73## CLI
74
75You can use `write-good` as a command-line tool by installing it globally:
76
77```shell
78npm install -g write-good
79```
80
81If you have npm version 5.2.0 or later installed, you can use npx to run write-good without installing it:
82
83```shell
84npx write-good *.md
85```
86
87`write-good` takes a [glob](https://github.com/isaacs/node-glob) and prints suggestions to stdout:
88
89```shell
90$ write-good *.md
91
92In README.md
93=============
94 = writeGood('So the cat was stolen.');
95                         ^^^^^^^^^^
96"was stolen" is passive voice on line 20 at column 40
97-------------
98//   suggestion: "'was stolen' is passive voice",
99                   ^^^^^^^^^^
100"was stolen" is passive voice on line 28 at column 19
101```
102
103You can run just specific checks like this:
104
105```shell
106write-good *.md --weasel --so
107```
108
109Or exclude checks like this:
110
111```shell
112write-good *.md --no-passive
113```
114
115Or include checks like this:
116
117```shell
118# E-Prime is disabled by default.
119write-good *.md --yes-eprime
120```
121
122**Note:** The ``--yes`` prefix only works for *E-Prime*, because the other checks are included by default, anyway.
123
124You can run just with text without supplying files:
125
126```shell
127write-good --text="It should have been defined there."
128```
129
130You can even supply multi-line text:
131
132```shell
133write-good --text="I can't see a problem there that's not been defined yet.
134Should be defined again."
135```
136
137You can also pass other arguments:
138
139```shell
140write-good --text="It should have been defined there." --no-passive
141```
142
143You can even fetch output from a remote file:
144
145```shell
146write-good --text="$(curl https://raw.githubusercontent.com/btford/write-good/master/README.md)"
147```
148
149Use the ``--parse`` option to activate parse-happy output and a more conventional Unix exit code:
150
151```shell
152write-good *.md --parse
153```
154
155To specify a custom checks extension, for example [schreib-gut](https://github.com/TimKam/schreib-gut), run:
156
157```shell
158npm install -g schreib-gut
159write-good *.md --checks=schreib-gut
160```
161
162To view all available options use the ``--help`` option:
163
164```shell
165write-good --help
166```
167
168## Checks
169
170You can disable any combination of the following by providing a key with value `false` as the second argument to `writeGood`.
171
172### `passive`
173Checks for passive voice.
174
175### `illusion`
176Checks for lexical illusions – cases where a word is repeated.
177
178### `so`
179Checks for `so` at the beginning of the sentence.
180
181### `thereIs`
182Checks for `there is` or `there are` at the beginning of the sentence.
183
184### `weasel`
185Checks for "weasel words."
186
187### `adverb`
188Checks for adverbs that can weaken meaning: really, very, extremely, etc.
189
190### `tooWordy`
191Checks for wordy phrases and unnecessary words.
192
193### `cliches`
194Checks for common cliches.
195
196### `eprime`
197Checks for ["to-be"](https://en.wikipedia.org/wiki/E-Prime) verbs. _Disabled by default_
198
199## Extensions
200Users can create their own `write-good` language checks. As described above,
201you can specify such extensions when running `write-good` on the command line
202or calling it in your JavaScript code.
203
204The following 3rd-party `write-good` extensions are available:
205
206* [schreib-gut](https://github.com/timkam/schreib-gut): A basic extension for
207  the German language
208
209If you know of any `write-good` extensions that are not in this list, please open a pull request!
210
211### Interface
212An extension is a Node.js module that exposes an object containing a check
213function (``fn``) and an ``explanation`` string for each new check:
214
215```javascript
216module.exports = {
217  check1: {
218    fn: function(text) {
219220    },
221    explanation: '…'
222  },
223  check2: {
224    fn: function(text) {
225226    },
227    explanation: '…'
228  }
229}
230```
231
232Each check function takes a string input and determines a list of style
233violation objects, each with an ``index`` and an ``offset``:
234
235```javascript
236/**
237* @param {text} text  Input text
238* @return {{index:number, offset:number}[]}  List of all violations
239*/
240```
241
242The ``index`` defines the position of the match in the input text, whereas the
243``offset`` specifies the length of the match.
244
245The following example extension provides a check that determines if the input
246text contains a set of forbidden terms (*Tom Riddle* and *Voldemort*):
247
248```javascript
249module.exports = {
250  voldemort: {
251    fn: function (text) {
252      var positives = ['Tom Riddle', 'Voldemort']
253      var re = new RegExp('\\b(' + positives.join('|') + ')\\b', 'gi');
254      var suggestions = [];
255      while (match = re.exec(text)) {
256        suggestions.push({
257          index: match.index,
258          offset: match[0].length,
259        });
260      }
261      return suggestions;
262    },
263    explanation: 'You must not name Him-Who-Must-Not-Be-Named'
264  }
265}
266```
267
268## Docker
269
270### From Dockerhub
271
272You 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:
273
274`docker run --rm --volume $PWD:/app hochzehn/write-good *.md`
275
276### Building locally
277
278Or you can first build the image locally:
279
280`docker build -t btford/write-good .`
281
282And then run using:
283
284`docker run -it --rm -v "$(pwd)":/srv/app -w /srv/app btford/write-good:latest *.md`
285
286## See also
287
288I came across these resources while doing research to make this module.
289They might be helpful.
290
291### Code
292
293* [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
294* [Academic Writing Check](https://github.com/devd/Academic-Writing-Check) – a perl script similar to above
295* [writegood mode](https://github.com/bnbeckwith/writegood-mode) for emacs
296* [natural](https://github.com/NaturalNode/natural) – general purpose NLP toolkit in JavaScript
297* [WordNet](http://wordnet.princeton.edu/) – lexical database of the English language
298* [LanguageTool](https://languagetool.org/) – style and grammar checker implemented in Java
299
300### Prose
301
302* [Elements of Style](http://www.bartleby.com/141/)
303* [Flesch–Kincaid readability](http://en.wikipedia.org/wiki/Flesch%E2%80%93Kincaid_readability_test)
304* [Fear and Loathing of the English passive](http://www.lel.ed.ac.uk/~gpullum/passive_loathing.pdf)
305* [Words to Avoid in Educational Writing](http://css-tricks.com/words-avoid-educational-writing/)
306
307### Apps
308
309This is not an endorsement.
310These apps have similar functionality that you may find useful.
311
312* [Hemingway App](http://www.hemingwayapp.com/)
313* [Nitpicker](http://nitpickertool.com)
314* [Grammarly](https://app.grammarly.com)
315
316## Other projects using write good
317
318* [linter-write-good](https://github.com/gepoch/linter-write-good) for [Atom](https://atom.io/)
319* [Write Good action](https://actions.getdrafts.com/a/1RA) for [Drafts](https://getdrafts.com) iOS App
320* [Write Good Linter](https://marketplace.visualstudio.com/items?itemName=travisthetechie.write-good-linter) for [Visual Studio Code](https://code.visualstudio.com)
321* [Vim ALE](https://github.com/w0rp/ale) realtime linter for [Vim](http://www.vim.org/) with included support for write-good.
322* [Write Better](https://github.com/justiceo/write-better) A [Chrome extension](https://chrome.google.com/webstore/detail/write-better/nnnnnpmcdcloafmfkiihafnjidjkfmek) for Google Docs.
323
324## License
325MIT
326