1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
|
.\" Generated with Ronnjs/v0.1
.\" http://github.com/kapouer/ronnjs/
.
.TH "NPM\-CODING\-STYLE" "1" "January 2011" "" ""
.
.SH "NAME"
\fBnpm-coding-style\fR \-\- npm\'s "funny" coding style
.
.SH "DESCRIPTION"
npm\'s coding style is a bit unconventional\. It is not different for
difference\'s sake, but rather a carefully crafted style that is
designed to reduce visual clutter and make bugs more apparent\.
.
.P
If you want to contribute to npm (which is very encouraged), you should
make your code conform to npm\'s style\.
.
.SH "Line Length"
Keep lines shorter than 80 characters\. It\'s better for lines to be
too short than to be too long\. Break up long lists, objects, and other
statements onto multiple lines\.
.
.SH "Indentation"
Two\-spaces\. Tabs are better, but they look like hell in web browsers
(and on github), and node uses 2 spaces, so that\'s that\.
.
.P
Configure your editor appropriately\.
.
.SH "Curly braces"
Curly braces belong on the same line as the thing that necessitates them\.
.
.P
Bad:
.
.IP "" 4
.
.nf
function ()
{
.
.fi
.
.IP "" 0
.
.P
Good:
.
.IP "" 4
.
.nf
function () {
.
.fi
.
.IP "" 0
.
.P
If a block needs to wrap to the next line, use a curly brace\. Don\'t
use it if it doesn\'t\.
.
.P
Bad:
.
.IP "" 4
.
.nf
if (foo) { bar() }
while (foo)
bar()
.
.fi
.
.IP "" 0
.
.P
Good:
.
.IP "" 4
.
.nf
if (foo) bar()
while (foo) {
bar()
}
.
.fi
.
.IP "" 0
.
.SH "Semicolons"
Don\'t use them except in four situations:
.
.IP "\(bu" 4
\fBfor (;;)\fR loops\. They\'re actually required\.
.
.IP "\(bu" 4
null loops like: \fBwhile (something) ;\fR (But you\'d better have a good
reason for doing that\.)
.
.IP "\(bu" 4
case "foo": doSomething(); break
.
.IP "\(bu" 4
In front of a leading ( or [ at the start of the line\.
This prevents the expression from being interpreted
as a function call or property access, respectively\.
.
.IP "" 0
.
.P
Some examples of good semicolon usage:
.
.IP "" 4
.
.nf
;(x || y)\.doSomething()
;[a, b, c]\.forEach(doSomething)
for (var i = 0; i < 10; i ++) {
switch (state) {
case "begin": start(); continue
case "end": finish(); break
default: throw new Error("unknown state")
}
end()
}
.
.fi
.
.IP "" 0
.
.P
Note that starting lines with \fB\-\fR and \fB+\fR also should be prefixed
with a semicolon, but this is much less common\.
.
.SH "Comma First"
If there is a list of things separated by commas, and it wraps
across multiple lines, put the comma at the start of the next
line, directly below the token that starts the list\. Put the
final token in the list on a line by itself\. For example:
.
.IP "" 4
.
.nf
var magicWords = [ "abracadabra"
, "gesundheit"
, "ventrilo"
]
, spells = { "fireball" : function () { setOnFire() }
, "water" : function () { putOut() }
}
, a = 1
, b = "abc"
, etc
, somethingElse
.
.fi
.
.IP "" 0
.
.SH "Whitespace"
Put a single space in front of ( for anything other than a function call\.
Also use a single space wherever it makes things more readable\.
.
.P
Don\'t leave trailing whitespace at the end of lines\. Don\'t indent empty
lines\. Don\'t use more spaces than are helpful\.
.
.SH "Functions"
Use named functions\. They make stack traces a lot easier to read\.
.
.SH "Callbacks, Sync/async Style"
Use the asynchronous/non\-blocking versions of things as much as possible\.
It might make more sense for npm to use the synchronous fs APIs, but this
way, the fs and http and child process stuff all uses the same callback\-passing
methodology\.
.
.P
The callback should always be the last argument in the list\. Its first
argument is the Error or null\.
.
.P
Be very careful never to ever ever throw anything\. It\'s worse than useless\.
Just send the error message back as the first argument to the callback\.
.
.SH "Errors"
Always create a new Error object with your message\. Don\'t just return a
string message to the callback\. Stack traces are handy\.
.
.P
Use the \fBrequire("\./utils/log")\.er\fR function\. It takes a callback and an
error message, and returns an object that will report the message in the
event of a failure\. It\'s quite handy\.
.
.IP "" 4
.
.nf
function myThing (args, cb) {
getData(args, function (er, data) {
if (er) return log\.er(cb, "Couldn\'t get data")(er)
doSomethingElse(data, cb)
})
}
function justHasToWork (cb) {
doSomething(log\.er(cb, "the doSomething failed\."))
}
.
.fi
.
.IP "" 0
.
.SH "Logging"
Please clean up logs when they are no longer helpful\. In particular,
logging the same object over and over again is not helpful\. Logs should
report what\'s happening so that it\'s easier to track down where a fault
occurs\.
.
.P
Use appropriate log levels\. The default log() function logs at the
"info" level\. See \fBnpm help config\fR and search for "loglevel"\.
.
.SH "Case, naming, etc\."
Use lowerCamelCase for multiword identifiers when they refer to objects,
functions, methods, members, or anything not specified in this section\.
.
.P
Use UpperCamelCase for class names (things that you\'d pass to "new")\.
.
.P
Use all\-lower\-hyphen\-css\-case for multiword filenames and config keys\.
.
.P
Use named functions\. They make stack traces easier to follow\.
.
.P
Use CAPS\fISNAKE\fRCASE for constants, things that should never change
and are rarely used\.
.
.P
Use a single uppercase letter for function names where the function
would normally be anonymous, but needs to call itself recursively\. It
makes it clear that it\'s a "throwaway" function\.
|