4 |
5 | ***Module consumers!*** Frustrated by each module having its own wildly
6 | unique README format? Annoyed by modules that omit critical sections like
7 | **API** or **Examples**? Stuck scrolling through API docs before you *even know
8 | what the module does*?
9 |
10 | ***Module authors!*** Tired of making up your readme format every time you
11 | write it? Do you just want consistent readmes pre-populated with your module's
12 | name, description and license without worrying about the structure every time?
13 |
14 | ---
15 |
16 | What if there was a common format for the benefit of producers and consumers?
17 |
18 | A *common readme* for node modules.
19 |
20 | This can save everybody time by adhering to 4 principles:
21 |
22 | 1. **No lock in.** No special formats or tooling; run `common-readme` once for
23 | pure vanilla markdown.
24 | 2. **No surprises.** Pull as many details out of `package.json` -- like name,
25 | description, and license -- as possible. No time wasted on configuration.
26 | 3. **Cognitive funnelling.** Start with the most general information at the top
27 | (Name, Description, Examples) and if the reader maintains interest, narrow
28 | down to specifics (API, Installation). This makes it easy for readers to
29 | "short circuit" and continue the hunt for the right module elsewhere without
30 | wasting time delving into unnecessary details.
31 | 4. **Consistency.** Your brain can scan a document much faster when it can
32 | anticipate its structure.
33 |
34 | ## Common format
35 |
36 | common-readme operates on the principle of *cognitive funneling*.
37 |
38 | > Ideally, someone who's slightly familiar with your module should be able to
39 | > refresh their memory without hitting "page down". As your reader continues
40 | > through the document, they should receive a progressively greater amount of
41 | > knowledge. -- `perlmodstyle`
42 |
43 | Here are some READMEs generated using common-readme:
44 |
45 | - [`collide-2d-aabb-aabb`](https://github.com/noffle/collide-2d-aabb-aabb)
46 | - [`goertzel`](https://github.com/noffle/goertzel)
47 | - [`twitter-kv`](https://github.com/noffle/twitter-kv)
48 |
49 | *([Submit a pull request](https://github.com/noffle/common-readme/pulls) and add
50 | yours here!)*
51 |
52 | ## Usage
53 |
54 | With [npm](https://npmjs.org/) installed, run
55 |
56 | $ npm install -g common-readme
57 |
58 | `common-readme` is a command line program. You run it when you've started a new
59 | module that has a `package.json` set up.
60 |
61 | When run, a brand new README is generated and written to your terminal. You can
62 | redirect this to `README.md` and use it as a basis for your new module.
63 |
64 | $ common-readme > README.md
65 |
66 | This brand new readme will be automatically populated with values from
67 | `package.json` such as `name`, `description`, and `license`. Stub sections will
68 | be created for everything else (Usage, API, etc), ready for you to fill in.
69 |
70 | ## Why?
71 |
72 | This isn't a crazy new idea. Other ecosystems like [Perl's
73 | CPAN](http://perldoc.perl.org/perlmodstyle.html) have been benefiting from a
74 | common readme format for years. Furthermore:
75 |
76 | 1. The node community is powered by us people and the modules we share. It's our
77 | documentation that links us together. Our README is the first thing
78 | developers see and it should be maximally effective at communicating its
79 | purpose and function.
80 |
81 | 2. There is much wisdom to be found from the many developers who have written
82 | many many modules. Common readme aims to distill that experience into a
83 | common format that stands to benefit us all; especially newer developers!
84 |
85 | 3. Writing the same boilerplate is a waste of every author's time -- we might as
86 | well generate the common pieces and let the author focus on the content.
87 |
88 | 4. Scanning through modules on npm is a part of every node developer's regular
89 | development cycle. Having a consistent format lets the brain focus on content
90 | instead of structure.
91 |
92 | ## The Art of README
93 |
94 | For even more background, wisdom, and ideas, take a look at the article that
95 | inspired common-readme:
96 |
97 | - [*Art of README*](https://github.com/noffle/art-of-readme).
98 |
99 | ## Install
100 |
101 | With [npm](https://npmjs.org/) installed, run
102 |
103 | ```shell
104 | npm install -g common-readme
105 | ```
106 |
107 | You can now execute the `common-readme` command.
108 |
109 | ## Acknowledgments
110 |
111 | A standard readme format for the Node community isn't a new idea. Inspiration
112 | came from many conversations and unrealized efforts in the community:
113 |
114 | -
115 | - [richardlitt/standard-readme](https://github.com/RichardLitt/readme-standard)
116 | - [zwei/standard-readme](https://github.com/zcei/standard-readme)
117 |
118 | This, in addition to my own experiences evaluating hundreds of node modules and
119 | their READMEs.
120 |
121 | I was partly inspired by the audacity of the honey-badger-don't-care efforts of
122 | [standard](https://github.com/feross/standard).
123 |
124 | I also did a great deal of Perl archaeology -- it turns out the monks of the
125 | Perl community already did much of the hard work of [figuring out great
126 | READMEs](http://perldoc.perl.org/perlmodstyle.html) and the wisdom around small
127 | module development well over a decade ago.
128 |
129 | Thanks to @mafintosh, @andrewosh, and @feross for many long conversations about
130 | readmes and Node.
131 |
132 | ## See Also
133 |
134 | READMEs love [`readme`](https://www.npmjs.com/package/readme)!
135 |
136 | ## License
137 |
138 | ISC
139 |
--------------------------------------------------------------------------------
/api_formatting.md:
--------------------------------------------------------------------------------
1 | # api formatting
2 |
3 | there's no one style for expressing a node api, but here are some common
4 | patterns with explanations:
5 |
6 | ## var r = repo(name, opts={})
7 |
8 | Produces a new REPO with name `name`. Valid `opts` keys include
9 |
10 | - `db` (required) - uses the levelup instance `db`
11 | - `count` (optional) - does the thing `count` times
12 |
13 | > Shows how to create an instance of an object. `opts` is indicated to be the
14 | > empty object by default, and its required and optional parameters are
15 | > detailed.
16 |
17 | ## r.work(hard, cb(err, res))
18 |
19 | Puts `r` to work. If `hard` is `true`, it'll even work pretty hard at it. `cb`
20 | will be called with the result of the work.
21 |
22 | > A method on the object. More importantly the indicator that it accepts a
23 | > callback function (`cb` or `callback` are both popular names). The callback's
24 | > parameters are named in `work`'s signature.
25 |
26 | ## r.pipe(stream), stream.pipe(r)
27 |
28 | `r` implements a readable stream or writeable stream, respectively.
29 |
30 | > `r` inherits `Readable` or `Writeable`, or both.
31 |
32 | ## r.on('foo', cb(bar))
33 |
34 | `r` can raise an event named `'foo'` with the argument `bar`.
35 |
36 | > `r` is an EventEmitter, and is known to emit an event with the given name. The
37 | > callback that is ultimately called has the expected parameter `bar`.
38 |
--------------------------------------------------------------------------------
/cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var fs = require('fs')
4 | var path = require('path')
5 | var camel = require('camelcase')
6 | var args = require('minimist')(process.argv)
7 |
8 | if (args.h || args.help) {
9 | usage()
10 | console.error()
11 | console.error('Generate a readme for your node module.')
12 | process.exit(1)
13 | }
14 |
15 | function usage () {
16 | console.error()
17 | console.log('USAGE: common-readme [-r|--repo REPO-NAME] [-l|--license LICENSE]')
18 | }
19 |
20 | var checkPkg = fs.existsSync(path.join(process.cwd(), 'package.json')) || args.l || args.license || args.r || args.repo || null
21 |
22 | if (!checkPkg) {
23 | console.error('no package.json found and no license and repo name set!')
24 | usage()
25 | process.exit(1)
26 | }
27 |
28 | var pkg = require(path.join(process.cwd(), 'package.json'))
29 |
30 | // one liner
31 | var oneliner = pkg.description || 'one-liner description of the module'
32 |
33 | // license
34 | var license = args.l || args.license || pkg.license || null
35 | if (!license) {
36 | console.error('no license set or found in package.json!')
37 | usage()
38 | process.exit(1)
39 | }
40 |
41 | // repo name
42 | var repo = args.r || args.repo || pkg.name || null
43 | if (!repo) {
44 | console.error('no repo name set or found in package.json!')
45 | usage()
46 | process.exit(1)
47 | }
48 | var repoCamel = camel(repo)
49 |
50 | // example.js
51 | var example = getExampleJs()
52 | function getExampleJs () {
53 | try {
54 | return fs.readFileSync(path.join(__dirname, 'example.js'))
55 | } catch (e) {
56 | return "var $$$rePo = require('$$$REPO')\n\nconsole.log('hello world') // => hello world"
57 | }
58 | }
59 |
60 | // read the template and regex match templated vars
61 | fs.readFileSync(path.join(__dirname, 'template.md')).toString().split('\n')
62 | .forEach(function (line) {
63 | console.log(processLine(line))
64 | })
65 |
66 | function processLine (line) {
67 | line = line.replace(/\$\$EXAMPLE/, example)
68 | line = line.replace(/\$\$REPO/, repo)
69 | line = line.replace(/\$\$rePo/, repoCamel)
70 | line = line.replace(/\$\$1LINER/, oneliner)
71 | line = line.replace(/\$\$ZEE_LICENSE/, license)
72 | line = line.replace(/\$\$r/, repo.charAt(0).toLowerCase())
73 | return line
74 | }
75 |
--------------------------------------------------------------------------------
/common-readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackergrrl/common-readme/4379d47deb0ee6c0cc522dfc150f94c94688022b/common-readme.png
--------------------------------------------------------------------------------
/common-readme.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
93 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "common-readme",
3 | "description": "Generates a readme for your node modules.",
4 | "version": "1.1.0",
5 | "repository": {
6 | "url": "git://github.com/noffle/common-readme.git"
7 | },
8 | "bin": {
9 | "common-readme": "cli.js"
10 | },
11 | "dependencies": {
12 | "camelcase": "^5.0.0",
13 | "minimist": "^1.2.0"
14 | },
15 | "license": "ISC"
16 | }
17 |
--------------------------------------------------------------------------------
/template.md:
--------------------------------------------------------------------------------
1 | # $$REPO
2 |
3 | > $$1LINER
4 |
5 | background details relevant to understanding what this module does
6 |
7 | ## Usage
8 |
9 | ```javascript
10 | $$EXAMPLE
11 | ```
12 |
13 | ## API
14 |
15 | ```js
16 | const $$rePo = require('$$REPO')
17 | ```
18 |
19 | See [api_formatting.md](api_formatting.md) for tips.
20 |
21 | ## Installation
22 |
23 | With [npm](https://npmjs.org/):
24 |
25 | ```shell
26 | npm install $$REPO
27 | ```
28 |
29 | With [yarn](https://yarnpkg.com/en/):
30 |
31 | ```shell
32 | yarn add $$REPO
33 | ```
34 |
35 | ## Acknowledgments
36 |
37 | $$REPO was inspired by...
38 |
39 | ## See Also
40 |
41 | - [`noffle/common-readme`](https://github.com/noffle/common-readme)
42 | - ...
43 |
44 | ## License
45 |
46 | $$ZEE_LICENSE
47 |
--------------------------------------------------------------------------------