├── .github
└── PULL_REQUEST_TEMPLATE.md
├── CONTRIBUTING.md
├── LICENSE.md
└── README.md
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Summary
2 |
3 | Proposed changes:
4 |
5 | * ..
6 | * ..
7 |
8 | Resolves # .
9 |
10 | ## Checklist
11 |
12 | * [ ] The changes only affect or contain one style guide rule or section.
13 | * [ ] The changes are in [style guide format](/CONTRIBUTING.md#format).
14 | * [ ] The new style guide section has an entry in the [Table of Contents](/README.md#table-of-contents) (only if changes introduce new section).
15 | * [ ] The changes can be merged into the target branch without conflicts.
16 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | For new additions or changes to the guide, create a branch and submit a Pull Request.
4 | Only add/change 1 style guide rule per Pull Request.
5 | The Pull Request serves as a place to discuss and refine the additions/changes.
6 |
7 | ## Format
8 |
9 | Use [Github Flavoured Markdown](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown).
10 |
11 | Use short and descriptive rule names as 2nd level heading:
12 |
13 | ```markdown
14 | ## Keep expressions simple
15 | ```
16 |
17 | Optionally add an short summary for the rule.
18 |
19 | Describe **why** the rule exists. What purpose does it serve?
20 |
21 | ```markdown
22 | ### Why?
23 |
24 | With nvm you can have multiple different versions available and switch to the one that suits better your project.
25 | ```
26 |
27 | Describe **how** (and how not) to apply the rule.
28 |
29 | ```markdown
30 | ### How?
31 |
32 | To install or update nvm, you can use the install script using cURL
33 | ```
34 |
35 | When using code snippets:
36 | * use `` and `/* recommended */` or `` and `/* avoid */` at the start of the snippet to indicate if it's a good or bad practice.
37 |
38 | When in need refer to npm in lowercase.
39 |
40 | Add a [↑ back to Table of Contents](README.md#table-of-contents) link at the end of each rule, so the reader can easily navigate back:
41 |
42 | ```markdown
43 | [↑ back to Table of Contents](#table-of-contents)
44 | ```
45 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # CC0 1.0 Universal
2 |
3 | ## Statement of Purpose
4 |
5 | The laws of most jurisdictions throughout the world automatically confer
6 | exclusive Copyright and Related Rights (defined below) upon the creator and
7 | subsequent owner(s) (each and all, an "owner") of an original work of
8 | authorship and/or a database (each, a "Work").
9 |
10 | Certain owners wish to permanently relinquish those rights to a Work for the
11 | purpose of contributing to a commons of creative, cultural and scientific
12 | works ("Commons") that the public can reliably and without fear of later
13 | claims of infringement build upon, modify, incorporate in other works, reuse
14 | and redistribute as freely as possible in any form whatsoever and for any
15 | purposes, including without limitation commercial purposes. These owners may
16 | contribute to the Commons to promote the ideal of a free culture and the
17 | further production of creative, cultural and scientific works, or to gain
18 | reputation or greater distribution for their Work in part through the use and
19 | efforts of others.
20 |
21 | For these and/or other purposes and motivations, and without any expectation
22 | of additional consideration or compensation, the person associating CC0 with a
23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
25 | and publicly distribute the Work under its terms, with knowledge of his or her
26 | Copyright and Related Rights in the Work and the meaning and intended legal
27 | effect of CC0 on those rights.
28 |
29 | **1. Copyright and Related Rights.** A Work made available under CC0 may be
30 | protected by copyright and related or neighboring rights ("Copyright and
31 | Related Rights"). Copyright and Related Rights include, but are not limited
32 | to, the following:
33 |
34 | i. the right to reproduce, adapt, distribute, perform, display, communicate,
35 | and translate a Work;
36 |
37 | ii. moral rights retained by the original author(s) and/or performer(s);
38 |
39 | iii. publicity and privacy rights pertaining to a person's image or likeness
40 | depicted in a Work;
41 |
42 | iv. rights protecting against unfair competition in regards to a Work,
43 | subject to the limitations in paragraph 4(a), below;
44 |
45 | v. rights protecting the extraction, dissemination, use and reuse of data in
46 | a Work;
47 |
48 | vi. database rights (such as those arising under Directive 96/9/EC of the
49 | European Parliament and of the Council of 11 March 1996 on the legal
50 | protection of databases, and under any national implementation thereof,
51 | including any amended or successor version of such directive); and
52 |
53 | vii. other similar, equivalent or corresponding rights throughout the world
54 | based on applicable law or treaty, and any national implementations thereof.
55 |
56 | **2. Waiver.** To the greatest extent permitted by, but not in contravention of,
57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
59 | and Related Rights and associated claims and causes of action, whether now
60 | known or unknown (including existing as well as future claims and causes of
61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum
62 | duration provided by applicable law or treaty (including future time
63 | extensions), (iii) in any current or future medium and for any number of
64 | copies, and (iv) for any purpose whatsoever, including without limitation
65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
66 | the Waiver for the benefit of each member of the public at large and to the
67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver
68 | shall not be subject to revocation, rescission, cancellation, termination, or
69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work
70 | by the public as contemplated by Affirmer's express Statement of Purpose.
71 |
72 | **3. Public License Fallback.** Should any part of the Waiver for any reason be
73 | judged legally invalid or ineffective under applicable law, then the Waiver
74 | shall be preserved to the maximum extent permitted taking into account
75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
76 | is so judged Affirmer hereby grants to each affected person a royalty-free,
77 | non transferable, non sublicensable, non exclusive, irrevocable and
78 | unconditional license to exercise Affirmer's Copyright and Related Rights in
79 | the Work (i) in all territories worldwide, (ii) for the maximum duration
80 | provided by applicable law or treaty (including future time extensions), (iii)
81 | in any current or future medium and for any number of copies, and (iv) for any
82 | purpose whatsoever, including without limitation commercial, advertising or
83 | promotional purposes (the "License"). The License shall be deemed effective as
84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the
85 | License for any reason be judged legally invalid or ineffective under
86 | applicable law, such partial invalidity or ineffectiveness shall not
87 | invalidate the remainder of the License, and in such case Affirmer hereby
88 | affirms that he or she will not (i) exercise any of his or her remaining
89 | Copyright and Related Rights in the Work or (ii) assert any associated claims
90 | and causes of action with respect to the Work, in either case contrary to
91 | Affirmer's express Statement of Purpose.
92 |
93 | **4. Limitations and Disclaimers.**
94 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
95 | surrendered, licensed or otherwise affected by this document.
96 |
97 | b. Affirmer offers the Work as-is and makes no representations or warranties
98 | of any kind concerning the Work, express, implied, statutory or otherwise,
99 | including without limitation warranties of title, merchantability, fitness
100 | for a particular purpose, non infringement, or the absence of latent or
101 | other defects, accuracy, or the present or absence of errors, whether or not
102 | discoverable, all to the greatest extent permissible under applicable law.
103 |
104 | c. Affirmer disclaims responsibility for clearing rights of other persons
105 | that may apply to the Work or any use thereof, including without limitation
106 | any person's Copyright and Related Rights in the Work. Further, Affirmer
107 | disclaims responsibility for obtaining any necessary consents, permissions
108 | or other rights required for any use of the Work.
109 |
110 | d. Affirmer understands and acknowledges that Creative Commons is not a
111 | party to this document and has no duty or obligation with respect to this
112 | CC0 or use of the Work.
113 |
114 | For more information, please see
115 |
116 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # npm Style Guide
2 |
3 | Opinionated *npm Style Guide* for teams by [De Voorhoede](https://twitter.com/devoorhoede).
4 |
5 | [](https://github.com/voorhoede/npm-style-guide)
6 |
7 | ## Purpose
8 |
9 | This guide provides a set of rules to better manage, test and build your [npm](https://npmjs.org) modules and project scripts. It should make them
10 |
11 | * easier for a new developer to pick up
12 | * reduce friction with different environment configurations
13 | * have a predictable api
14 | * easier to add new scripts
15 |
16 | ## Table of Contents
17 |
18 | * [Use nvm to manage node versions](#use-nvm-to-manage-node-versions)
19 | * [Configure your npm personal info](#configure-your-npm-personal-info)
20 | * [Use `save exact` option](#use-save-exact-option)
21 | * [Specify engines on `package.json`](#specify-engines-on-packagejson)
22 | * [Avoid installing modules globally](#avoid-installing-modules-globally)
23 | * [Use standard script names](#use-standard-script-names)
24 | * [Write atomic scripts](#write-atomic-scripts)
25 | * [Use npm modules for system tasks](#use-npm-modules-for-system-tasks)
26 | * [Avoid shorthand command flags](#avoid-shorthand-command-flags)
27 | * [Group related scripts by prefix](#group-related-scripts-by-prefix)
28 | * [Document your script API](#document-your-script-api)
29 |
30 |
31 | ## Use nvm to manage node versions
32 |
33 | ### Why?
34 |
35 | With [nvm](https://github.com/creationix/nvm) you can have multiple different versions available and switch to the one that suits better your project.
36 |
37 | ### How?
38 |
39 | To install or update nvm, you can use the install script using cURL:
40 |
41 | ```bash
42 | curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash
43 | ```
44 |
45 | For Windows check [nvm for windows](https://github.com/coreybutler/nvm-windows).
46 |
47 |
48 | If everything goes well, you can now install a specific node version.
49 |
50 | ```bash
51 | nvm install stable
52 | nvm install vX.Y.Z
53 | nvm alias default stable
54 | ```
55 |
56 | It’s also easy when updating a newer version, copying your existing global modules.
57 |
58 | ```bash
59 | nvm copy-packages
60 | ```
61 |
62 | [↑ back to Table of Contents](#table-of-contents)
63 |
64 |
65 | ## Configure your npm personal info
66 |
67 | ### Why?
68 |
69 | When creating a new package `npm init` your defaults will be already included on the scaffolding.
70 |
71 | ### How?
72 |
73 | ```bash
74 | npm config set init-author-name "{name}"
75 | npm config set init-author-email "{email}"
76 | ```
77 |
78 | Check [npm config](https://docs.npmjs.com/misc/config#init-module) docs, for more info.
79 |
80 | You can use `cat ~/.npmrc` to check your current definitions.
81 |
82 | [↑ back to Table of Contents](#table-of-contents)
83 |
84 |
85 | ## Use `save exact` option
86 |
87 | ### Why?
88 |
89 | By default, installing a package with the `--save` or `--save-dev` option, npm saves the package version with `^` prefix, meaning that will update minor versions if available. While this is a good idea as is, this makes it possible for different developers having different versions of the same package and making it harder to debug if there is inconsistency. Defining the `save-exact` option prevents this. More info [npm config](https://docs.npmjs.com/misc/config#save-exact) docs.
90 |
91 | ### How?
92 |
93 | ```bash
94 | npm config set save-exact
95 | ```
96 |
97 | [↑ back to Table of Contents](#table-of-contents)
98 |
99 |
100 | ## Specify engines on `package.json`
101 |
102 | ### Why?
103 |
104 | Specifying engine versions for your module, warns the user if he is not using a supported version. This is specially important for ensuring npm@3 flat tree dependency on Windows, or ES2015 features that your scripts require on node.
105 |
106 | ### How?
107 |
108 | In `package.json`:
109 | ```javascript
110 | "engines" : {
111 | "node" : "5.10.0",
112 | "npm" : "3.8.5"
113 | }
114 | ```
115 |
116 | Preventing the user from using your module is also possible with [check-pkg-engines](https://www.npmjs.com/package/check-pkg-engines).
117 |
118 | [↑ back to Table of Contents](#table-of-contents)
119 |
120 |
121 | ## Avoid installing modules globally
122 |
123 | NPM first tries globally installed modules before looking for local ones. Globally installed modules are shared between projects and might not match the required version for the project.
124 |
125 | ### Why?
126 |
127 | * Locally installed modules are custom and specific for the project.
128 | * Locally installed modules are directly accessible via [npm scripts](https://docs.npmjs.com/misc/scripts).
129 |
130 | ### How?
131 |
132 | ```bash
133 | # recommended: install locally
134 | npm install --save-dev grunt-cli grunt
135 | ```
136 | and use in `package.json`:
137 | ```json
138 | "scripts": {
139 | "icons": "grunt grunticon"
140 | }
141 | ```
142 | ```bash
143 | # avoid: don't install modules globally
144 | npm install -g grunt-cli grunt
145 | ```
146 |
147 | [↑ back to Table of Contents](#table-of-contents)
148 |
149 |
150 | ## Use npm modules for system tasks
151 |
152 | ### Why?
153 |
154 | When you use system specific commands like `rm -rf` or `&&`, you are locking your tasks to your current operating system. If you want to make your scripts work everywhere think about Windows developers also.
155 |
156 | ### How?
157 |
158 | Use npm modules with node that mimic the same tasks but are system agnostic. Some examples:
159 |
160 | * create directory (`mkdir` / `mkdir -p`) -> [`mkdirp`](https://www.npmjs.com/package/mkdirp)
161 | * remove files and directories (`rm ...`) -> [`rimraf`](https://www.npmjs.com/package/rimraf)
162 | * copy files (`cp ...`) -> [`ncp`](https://www.npmjs.com/package/ncp)
163 | * run multiple scripts in sequence (`... && ...`) or in parallel (`... & ...`) -> [`npm-run-all`](https://www.npmjs.com/package/npm-run-all)
164 | * set environment variable (`ENV_VAR = ...`) -> [`cross-env`](https://www.npmjs.com/package/cross-env)
165 |
166 | [↑ back to Table of Contents](#table-of-contents)
167 |
168 |
169 | ## Avoid shorthand command flags
170 |
171 | npm and npm modules with a command-line interface support different options using fully written out and / or shorthand flags. For instance, instead of `npm install --save-dev` you can use the shorter `npm i -D`. For `npm test` you can use simply `npm t`. But `npm start` is not the same as `npm s`, as that's an alias for `npm search`. So while you can use these shorthands in your daily routine, you should avoid them in scripts and documentation shared with other developers.
172 |
173 | ### Why?
174 |
175 | * Shorthand flags can only be understood by developers who know the modules and options well.
176 | * Fully written out command options help in writing self documented scripts.
177 | * Fully written out command options make scripts more accessible to other developers.
178 |
179 | ### How?
180 |
181 | Always prefer fully written command flags over shorthand. Example using [uglifyjs](https://www.npmjs.com/package/uglify-js):
182 |
183 | ```bash
184 | # recommended
185 | uglify index.js --compress --mangle --reserved '$' --output index.min.js
186 | ```
187 |
188 | ```bash
189 | # avoid
190 | uglifyjs index.js -c -m -r '$' -o index.min.js
191 | ```
192 |
193 | [↑ back to Table of Contents](#table-of-contents)
194 |
195 | ## Use standard script names
196 |
197 | npm lets you define custom scripts. You can give these scripts any name you like, but you should stick to standard names when you can.
198 |
199 | ### Why?
200 |
201 | Using standard script names creates a predictable script API, which makes your project easier to use by other developers. When used consistently between projects a user doesn't even need to read the documentation or `package.json` to know which scripts are available.
202 |
203 | ### How?
204 |
205 | `npm start` and `npm test` are predefined aliases for custom scripts. In addition use of `build`, `deploy` and `watch` are widely spread within the developer community. You should use these script names as follows:
206 |
207 | * **`npm run build`** to create a distribution of your project (mostly for production).
208 | * **`npm run deploy`** to put your project on a host environment.
209 | * **`npm start`** (alias for `npm run start`) to start a web server (defaults to `node server.js`).
210 | * **`npm test`** (alias for `npm run test`) to run project's entire test suite.
211 | * **`npm run watch`** to run other scripts on files changes.
212 |
213 | In `package.json`:
214 | ```javascript
215 | /* recommended: standard script names */
216 | {
217 | "scripts": {
218 | "build": "...",
219 | "deploy": "...",
220 | "start": "...",
221 | "test": "...",
222 | "watch": "..."
223 | }
224 | }
225 |
226 | /* avoid: */
227 | {
228 | "scripts": {
229 | "bundle": "...",
230 | "upload": "...",
231 | "serve": "...",
232 | "check": "...",
233 | "watcher": "..."
234 | }
235 | }
236 | ```
237 |
238 | [↑ back to Table of Contents](#table-of-contents)
239 |
240 |
241 | ## Write atomic scripts
242 |
243 | Each script should be only responsible for one action.
244 |
245 | ### Why?
246 |
247 | * Atomic scripts are easy to read and understand.
248 | * Atomic scripts are easy to reuse.
249 |
250 | ### How?
251 |
252 | Separate each step of the script to an individual script. For example a "generate icon" script can be split into atomic script like "clean directory", "optimize SVGs", "generate PNGs" and "generate data-uris for SVGs".
253 |
254 | [↑ back to Table of Contents](#table-of-contents)
255 |
256 | ## Group related scripts by prefix
257 |
258 | Bundle your scripts with a prefix so you can execute them all at once.
259 |
260 | ### Why?
261 |
262 | * Bundling helps keeping your scripts organized.
263 | * Tasks grouped by prefix can be easily executed with one command.
264 | * Your high-level script API remains unchanged when scripts are added, removed or renamed.
265 |
266 | ### How?
267 |
268 | In `package.json`:
269 | ```javascript
270 | /* recommended: group related scripts by prefix */
271 | scripts: {
272 | "test": "npm run test:eslint && npm run test:unit && npm run test:e2e",
273 | "test:eslint": "eslint src/**/*.js",
274 | "test:unit": "tape --require dist/index.js src/**/*.test.js",
275 | "test:e2e": "karma start test/config.js"
276 | }
277 |
278 | /* avoid */
279 | scripts: {
280 | "eslint": "eslint src/**/*.js",
281 | "tape": "tape --require dist/index.js src/**/*.test.js",
282 | "karma": "karma start test/config.js",
283 | }
284 | ```
285 |
286 | Bundled scripts can be executed (in parallel or in sequence) using [npm-run-all](https://www.npmjs.com/package/npm-run-all):
287 |
288 | ```javascript
289 | /* recommended: use `npm-run-all` to run all bundled scripts */
290 | scripts: {
291 | "test": "npm-run-all test:*",
292 | "test:eslint": "eslint src/**/*.js",
293 | "test:unit": "tape --require dist/index.js src/**/*.test.js",
294 | "test:e2e": "karma start test/config.js"
295 | }
296 | ```
297 |
298 | [↑ back to Table of Contents](#table-of-contents)
299 |
300 |
301 | ## Document your script API
302 |
303 | ### Why?
304 |
305 | * Documentation provides developers with a high level overview to the script, without the need to go through all its code. This makes a module more accessible and easier to use.
306 | * Documentation formalises the API.
307 |
308 | ### How?
309 |
310 | Document your script API in the project's README.md or CONTRIBUTING.md as those are the first places contributors will look.
311 | Describe what each task does using a simple table:
312 |
313 | ```markdown
314 | `npm run ...` | Description
315 | ---|---
316 | task | What it does as a plain human readable description.
317 | ```
318 |
319 | An example:
320 |
321 | `npm run ...` | Description
322 | ---|---
323 | `build` | Compile, bundle and minify all CSS and JS files..
324 | `build:css` | Compile, autoprefix and minify all CSS files to `dist/index.css`.
325 | `build:js` | Compile, bundle and minify all JS files to `dist/index.js`.
326 | `start` | Starts a server on `http://localhost:3000`.
327 | `test` | Run all unit and end-to-end tests.
328 |
329 | [↑ back to Table of Contents](#table-of-contents)
330 |
331 | ---
332 |
333 | ## License
334 |
335 | [](https://creativecommons.org/publicdomain/zero/1.0/)
336 |
337 | [De Voorhoede](https://twitter.com/devoorhoede) waives all rights to this work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law.
338 |
339 | You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission.
340 |
--------------------------------------------------------------------------------