Comparing version 0.2.3 to 0.3.0
@@ -6,2 +6,7 @@ # Change Log | ||
## v0.3.0 - 2015-10-05 | ||
### Add | ||
* Necessary methods to add support for `customize-watch` | ||
## v0.2.3 - 2015-07-17 | ||
@@ -8,0 +13,0 @@ |
@@ -1,35 +0,55 @@ | ||
# Contributing Guidelines | ||
## Contributing | ||
Contributions are always welcome! | ||
Contributions and feedback are always welcome. The expected procedure is the following: | ||
**Before spending lots of time on something, ask for feedback on your idea first!** | ||
### Bugs, Features and Feedback | ||
Please search issues and pull requests before adding something new to avoid duplicating | ||
efforts and conversations. | ||
* Please, create github issues for **feature-requests**, **bug reports**. | ||
* Feel free to open issues for **questions and problems you have**, even if they are not bugs | ||
or feature requests. | ||
* You may even open an issue just to say you like the project. | ||
* For small changes, such as **typo and formatting corrections**, you can immediately | ||
create a pull-request. You can use the github web-interface, but keep in mind that most of the documentation | ||
is created with Thought, so you should change the template in the `.thought` directory or change the default | ||
templates in [the thought project](https://github.com/nknapp/thought/tree/master/handlebars). | ||
* If you have an idea for a **new feature** that you would like to implement, please **open an issue** first and ask | ||
for feedback. Maybe someone else has a similar problem and different ideas. | ||
* If you encounter a bug you can submit a **pull-request for a failing unit test**, you should then also open an issue | ||
for the bug. | ||
* Before making a pull-request, make sure that you commit corresponds to the coding-style. You can do this by | ||
running `npm test`. | ||
**People submitting relevant contributions will be granted commit access to the repository.** | ||
## Installing | ||
Fork and clone the repo, then `npm install` to install all dependencies and `npm test` to | ||
ensure all is okay before you start anything. | ||
### Coding style | ||
[![standard][standard-image]][standard-url] | ||
## Testing | ||
This repository uses [`standard`][standard-url] to maintain code style and consistency, | ||
and to avoid style arguments. You can run `npm run format` to apply the coding-style, but | ||
you may need to fix some things manually. Make sure to use the latest version of `standard`. | ||
Tests are run with `npm test`. Please ensure all tests are passing before submitting | ||
a pull request (unless you're creating a failing test to increase test coverage or show a problem). | ||
## Code Style | ||
### Installing & Testing | ||
[![standard][standard-image]][standard-url] | ||
You can fork and clone the repo from github. Run | ||
This repository uses [`standard`][standard-url] to maintain code style and consistency, | ||
and to avoid style arguments. | ||
``` | ||
npm i standard -g | ||
``` | ||
* Run `npm install` to install all the dependencies needed to build and run the project. | ||
* Run `npm test` to run unit tests and validate the `standard` coding-style. | ||
* Run `npm run thought` to generate the README.md and other markdown files in the repository. | ||
It is intentional to don't have `standard`, `istanbul` and `coveralls` in the devDependencies. Travis will handle all that stuffs. That approach will save bandwidth also installing and development time. | ||
It is intentional to don't have `standard`, `thought`, `istanbul` and `coveralls` in the devDependencies. | ||
`standard` is a rather large package which you would not want to have copied into the `node_modules`-folder | ||
of each of your projects. | ||
Instead, the `pretest`- and `preformat`-scripts ensure that `standard` and `thought` are installed globally. | ||
If you are not allowed to install packages globally, please raise an issue, so that we can try to find a solution. | ||
### About this text | ||
This text is part of the [Thought](https://github.com/nknapp/thought)-project. If you have any suggestions or wishes | ||
to change the text, please raise an issue there for discussion. | ||
[standard-image]: https://cdn.rawgit.com/feross/standard/master/badge.svg | ||
[standard-url]: https://github.com/feross/standard | ||
[standard-url]: https://github.com/feross/standard |
145
index.js
@@ -10,3 +10,3 @@ /*! | ||
/** | ||
/* | ||
* Use the `debug`-module to provide debug output if needed | ||
@@ -22,6 +22,12 @@ */ | ||
* Create a new Customize object with an empty configuration | ||
* | ||
* @module customize | ||
*/ | ||
module.exports = customize | ||
/** | ||
* @returns {Customize} | ||
* @api public | ||
*/ | ||
module.exports = function () { | ||
function customize () { | ||
return new Customize({}, {}, {}) | ||
@@ -31,10 +37,14 @@ } | ||
/** | ||
* The main class. The heart of Customize | ||
* This class does the actual work. When calling | ||
* `require('customize')()` a new instance of this | ||
* class is returned with an empty configuration, so | ||
* `new Customize(...)` should never be called outside | ||
* this module | ||
* `config` and `parentConfig` are of the form | ||
* | ||
* ```js | ||
* { engine: { config: ..., watched: [ ... ] } } | ||
* ``` | ||
* | ||
* @param config | ||
* @param parentConfig | ||
* @param {object<function>} engines | ||
* @constructor | ||
* @api private | ||
*/ | ||
@@ -48,6 +58,9 @@ function Customize (config, parentConfig, engines) { | ||
/** | ||
* Register an engine with a default config | ||
* @param {string} id the identifier of the engine (also within the config) | ||
* @param {function} engine | ||
* @api public | ||
* Register an engine an engine | ||
* @param {string} id the identifier of the engine. This identifier is also used | ||
* within the config as key within the configuration object to identify the | ||
* sub-configuration stored for this engine. | ||
* @param {{defaultConfig: object, preprocessConfig: function, run: function}} engine | ||
* a customize engine that is registered | ||
* @public | ||
*/ | ||
@@ -77,3 +90,6 @@ this.registerEngine = function (id, engine) { | ||
var _defaultConfig = {} | ||
_defaultConfig[id] = engine.defaultConfig | ||
_defaultConfig[id] = { | ||
config: engine.defaultConfig || {}, | ||
watched: engine.defaultWatched || [] | ||
} | ||
return new Customize(_defaultConfig, _config, _engines) | ||
@@ -84,6 +100,6 @@ | ||
/** | ||
* Creates a new instance of Customize. The config of the current Customize | ||
* are used as default values and are overridden by the config provided as parameter. | ||
* @param {object} config config overriding the config of this builder | ||
* @return {Customize} new Builder instance | ||
* Creates a new instance of Customize. The configuration values of the current Customize | ||
* are used as default values and are overridden by the configuration provided as parameter. | ||
* @param {object} config configuration overriding the current configuration | ||
* @return {Customize} the new Customize instance | ||
* @api public | ||
@@ -100,3 +116,3 @@ */ | ||
// Apply engine preprocessor to each config | ||
var preprocessedConfig = _.mapValues(config, function (value, key) { | ||
var preprocessedConfig = _.mapValues(config, function (engineConf, key) { | ||
var engine = engines[key] | ||
@@ -108,3 +124,10 @@ if (_.isUndefined(engine)) { | ||
var preprocessor = engine.preprocessConfig || _.identity | ||
return Q(value).then(preprocessor).then(function (config) { | ||
// Watch no files by default (constant []) | ||
var watched = engine.watched || _.constant([]) | ||
return Q(engineConf).then(function(engineConf) { | ||
return { | ||
config: preprocessor(engineConf), | ||
watched: watched(engineConf) | ||
} | ||
}).then(function (config) { | ||
debug('Merging preprocessed config', config) | ||
@@ -114,2 +137,7 @@ return config | ||
}) | ||
// Gather to-be-watched files and dirs from each engine | ||
var _watched = _.mapValues(config, function(value, key) { | ||
}) | ||
return new Customize(preprocessedConfig, _config, engines) | ||
@@ -120,25 +148,31 @@ } | ||
* Inherit configuration config from another module. | ||
* `require("Customize-modulename")` usually return a function(builder) | ||
* and this functions needs to be passed in here. | ||
* A new Customize will be returned that overrides the current config | ||
* with config from the builderFunction's result. | ||
* @param {function} builderFunction that receives a Customize as paramater | ||
* a Customizer-module usually exports a `function(Customize):Customize` | ||
* which in tern calls `Customize.merge` to create a new Customize instance. | ||
* This function needs to be passed in here. | ||
* | ||
* A new Customize will be returned that overrides the current configuration | ||
* with the configuration of the module. | ||
* @param {function(Customize):Customize} customizeModule that receives a Customize as paramater | ||
* and returns a Customize with changed configuration. | ||
* @return {Customize} the result of the builderFunction | ||
* @api public | ||
* @return {Customize} the Customize instance returned by the module | ||
* @public | ||
*/ | ||
this.load = function (builderFunction) { | ||
if (builderFunction.package) { | ||
console.log('Loading', builderFunction.package.name, builderFunction.package.version) | ||
this.load = function (customizeModule) { | ||
if (customizeModule.package) { | ||
console.log('Loading', customizeModule.package.name, customizeModule.package.version) | ||
} | ||
return builderFunction(this) | ||
return customizeModule(this) | ||
} | ||
/** | ||
* Build the configured Bootprint-instance. | ||
* Return a promise for the merged configuration. | ||
* This functions is only needed to inspect intermediate configuration results | ||
* (i.e. for testing and documentation purposes) | ||
* @return {Promise<object>} a promise for the whole configuration | ||
* @api public | ||
* @public | ||
*/ | ||
this.build = function () { | ||
return deep(_config).then(function (config) { | ||
return _.mapValues(config,_.property("config")) | ||
}).then(function (config) { | ||
debug('Building', config) | ||
@@ -150,9 +184,36 @@ return config | ||
/** | ||
* Return a promise for the files needing to be watched in watch-mode, | ||
* indexed by engine. | ||
* @return {Promise<object<string[]>>} a promise for the files to be watched. | ||
* | ||
* @public | ||
*/ | ||
this.watched = function () { | ||
return deep(_config).then(function (config) { | ||
return _.mapValues(config,_.property("watched")) | ||
}).then(function (watchedFileds) { | ||
debug('Watched files', watchedFileds) | ||
return watchedFileds | ||
}) | ||
} | ||
/** | ||
* Run each engine with its part of the config. | ||
* @api public | ||
* | ||
* @param {object=} options optional paramters | ||
* @param {string=} options.onlyEngine optionally the name of an engine, if only a single engine should | ||
* be executed | ||
* @return {Promise<object>} an object containing on property per registered engine | ||
* (the key is the engine-id) containing the result of each engine | ||
* @public | ||
*/ | ||
this.run = function () { | ||
this.run = function (options) { | ||
var onlyEngine = options && options.onlyEngine; | ||
return this.build().then(function (resolvedConfig) { | ||
var result = _.mapValues(engines, function (engine, key) { | ||
return engine.run(resolvedConfig[key]) | ||
// if "onlyEngine" is set to a value, execute on the engine with the same name | ||
if (!onlyEngine || onlyEngine === key) { | ||
return engine.run(resolvedConfig[key]) | ||
} | ||
}) | ||
@@ -163,2 +224,5 @@ return deep(result) | ||
this.watch = function() { | ||
return require("./lib/watcher.js")(this, _config); | ||
} | ||
} | ||
@@ -181,3 +245,3 @@ | ||
* @returns {Promise} | ||
* @api public | ||
* @public | ||
* @readonly | ||
@@ -191,3 +255,3 @@ */ | ||
* * If the overriding object has a `_customize_custom_overrider` function-property, | ||
* it is called to perform the merger. | ||
* it isk called to perform the merger. | ||
* * Arrays are concatenated | ||
@@ -201,2 +265,4 @@ * * Promises are resolved and the results are merged | ||
* @returns {*} the merged value | ||
* @private | ||
* @readonly | ||
*/ | ||
@@ -232,8 +298,1 @@ function customOverrider (a, b, propertyName) { | ||
} | ||
/** | ||
* The custom-overrider used by Customize | ||
* @readonly | ||
* @type {customOverrider} | ||
*/ | ||
module.exports.overrider = customOverrider |
@@ -26,3 +26,5 @@ var _ = require('lodash') | ||
return [ | ||
// key | ||
path.relative(directoryPath, filePath), | ||
// value | ||
customize.leaf(lazy(function () { | ||
@@ -29,0 +31,0 @@ return { |
{ | ||
"name": "customize", | ||
"version": "0.2.3", | ||
"version": "0.3.0", | ||
"description": "A simple framework to create customizable engines", | ||
@@ -41,2 +41,5 @@ "repository": { | ||
}, | ||
"peerDependencies": { | ||
"chokidar": "^1.1.0" | ||
}, | ||
"standard": { | ||
@@ -43,0 +46,0 @@ "ignore": [ |
312
README.md
@@ -53,2 +53,5 @@ # customize | ||
// Files/Dirs to-be-watched with the default configuration | ||
defaultWatched: [], | ||
// This function is called for any `.merge` input. | ||
@@ -60,2 +63,11 @@ // It converts the input into its mergable form | ||
// This function is called to determine the files and directories | ||
// to watch in developmentMode | ||
watched: function(config) { | ||
return [ | ||
// The config itself is the directory-path | ||
config | ||
] | ||
}, | ||
// Runs the engine with a resolved configuration. | ||
@@ -152,4 +164,19 @@ // The config contains no Promises anymore. | ||
We can do this, by merging another configuration: | ||
We can do this, by merging another configuration, but let's have a look at the directory | ||
tree before doing this: | ||
<pre><code>file-example/ | ||
├── dir1/ | ||
│ ├── a.md | ||
│ └── b.md | ||
├── dir2/ | ||
│ └── a.md | ||
├── engine-concat-files.js | ||
├── example-build.js | ||
├── example1.js | ||
└── example2.js</code></pre> | ||
You can see that the second directory contains a file `a.md`. We will use this file to | ||
replace the file of the first directory. | ||
```js | ||
@@ -168,11 +195,11 @@ var customize = require('customize') | ||
.run() | ||
.get("files") | ||
.get('files') | ||
.done(console.log) | ||
``` | ||
Notice the additional `.merge()`-call? Its input is also passed to the engine's preprocessor, | ||
so now we get two objects containing files and their contents and those are merged by the | ||
[`.merge`-function of the lodash library](https://lodash.com/docs#merge), so that in the above | ||
example, the property `a.md` is replace by the value in the second configuration. So the output | ||
of this example is | ||
There is an additional call to `.merge` in this code. Its input is also passed to the | ||
engine's preprocessor, so now we get two objects containing files and their contents | ||
and those are merged by the [`.merge`-function of the lodash library](https://lodash.com/docs#merge), | ||
so that in the above example, the property `a.md` is replace by the value in the | ||
second configuration. So the output of this example is | ||
@@ -221,147 +248,176 @@ ``` | ||
### Global | ||
<a name="module_customize"></a> | ||
#### customize | ||
Create a new Customize object with an empty configuration | ||
* [customize](#module_customize) | ||
* _static_ | ||
* [.withParent](#module_customize.withParent) | ||
* [.leaf](#module_customize.leaf) ⇒ <code>Promise</code> | ||
* _inner_ | ||
* [~Customize](#module_customize..Customize) | ||
* [new Customize()](#new_module_customize..Customize_new) | ||
* [.registerEngine(id, engine)](#module_customize..Customize+registerEngine) | ||
* [.merge(config)](#module_customize..Customize+merge) ⇒ <code>Customize</code> | ||
* [.load(customizeModule)](#module_customize..Customize+load) ⇒ <code>Customize</code> | ||
* [.build()](#module_customize..Customize+build) ⇒ <code>Promise.<object></code> | ||
* [.watched()](#module_customize..Customize+watched) ⇒ <code>Promise.<object.<Array.<string>>></code> | ||
* [.run([options])](#module_customize..Customize+run) ⇒ <code>Promise.<object></code> | ||
* [~customize()](#module_customize..customize) ⇒ <code>Customize</code> | ||
<a name="module_customize.withParent"></a> | ||
##### customize.withParent | ||
Wrap a function so that if it overrides another function, that function will | ||
be available as `this.parent` | ||
**Kind**: static property of <code>[customize](#module_customize)</code> | ||
**Read only**: true | ||
**Api**: public | ||
* * * | ||
| Param | | ||
| --- | | ||
| fn | | ||
##### exports() | ||
Create a new Customize object with an empty configuration | ||
**Returns**: `Customize` | ||
#### Class: Customize | ||
The main class. The heart of Customize | ||
**withParent**: , Wrap a function so that if it overrides another function, that function will | ||
be available as `this.parent` | ||
**leaf**: , Create a promise that is regarded as leaf in the configuration tree. | ||
<a name="module_customize.leaf"></a> | ||
##### customize.leaf ⇒ <code>Promise</code> | ||
Create a promise that is regarded as leaf in the configuration tree. | ||
That means, that the overrider is not resolving this promise when overriding values. | ||
Promised object values will not be merged but replaced. | ||
**overrider**: `customOverrider` , The custom-overrider used by Customize | ||
##### Customize.registerEngine(id, engine) | ||
Register an engine with a default config | ||
**Kind**: static property of <code>[customize](#module_customize)</code> | ||
**Access:** public | ||
**Read only**: true | ||
**Parameters** | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| promiseOrValue | <code>\*</code> | a promise or a valude that represents the leaf | | ||
**id**: `string`, the identifier of the engine (also within the config) | ||
<a name="module_customize..Customize"></a> | ||
##### customize~Customize | ||
**Kind**: inner class of <code>[customize](#module_customize)</code> | ||
**engine**: `function`, Register an engine with a default config | ||
* [~Customize](#module_customize..Customize) | ||
* [new Customize()](#new_module_customize..Customize_new) | ||
* [.registerEngine(id, engine)](#module_customize..Customize+registerEngine) | ||
* [.merge(config)](#module_customize..Customize+merge) ⇒ <code>Customize</code> | ||
* [.load(customizeModule)](#module_customize..Customize+load) ⇒ <code>Customize</code> | ||
* [.build()](#module_customize..Customize+build) ⇒ <code>Promise.<object></code> | ||
* [.watched()](#module_customize..Customize+watched) ⇒ <code>Promise.<object.<Array.<string>>></code> | ||
* [.run([options])](#module_customize..Customize+run) ⇒ <code>Promise.<object></code> | ||
<a name="new_module_customize..Customize_new"></a> | ||
###### new Customize() | ||
This class does the actual work. When calling | ||
`require('customize')()` a new instance of this | ||
class is returned with an empty configuration, so | ||
`new Customize(...)` should never be called outside | ||
this module | ||
`config` and `parentConfig` are of the form | ||
##### Customize.merge(config) | ||
```js | ||
{ engine: { config: ..., watched: [ ... ] } } | ||
``` | ||
Creates a new instance of Customize. The config of the current Customize | ||
are used as default values and are overridden by the config provided as parameter. | ||
<a name="module_customize..Customize+registerEngine"></a> | ||
###### customize.registerEngine(id, engine) | ||
Register an engine an engine | ||
**Parameters** | ||
**Kind**: instance method of <code>[Customize](#module_customize..Customize)</code> | ||
**Access:** public | ||
**config**: `object`, config overriding the config of this builder | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| id | <code>string</code> | the identifier of the engine. This identifier is also used within the config as key within the configuration object to identify the sub-configuration stored for this engine. | | ||
| engine | <code>Object</code> | a customize engine that is registered | | ||
**Returns**: `Customize`, new Builder instance | ||
<a name="module_customize..Customize+merge"></a> | ||
###### customize.merge(config) ⇒ <code>Customize</code> | ||
Creates a new instance of Customize. The configuration values of the current Customize | ||
are used as default values and are overridden by the configuration provided as parameter. | ||
##### Customize.load(builderFunction) | ||
**Kind**: instance method of <code>[Customize](#module_customize..Customize)</code> | ||
**Returns**: <code>Customize</code> - the new Customize instance | ||
**Api**: public | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| config | <code>object</code> | configuration overriding the current configuration | | ||
<a name="module_customize..Customize+load"></a> | ||
###### customize.load(customizeModule) ⇒ <code>Customize</code> | ||
Inherit configuration config from another module. | ||
`require("Customize-modulename")` usually return a function(builder) | ||
and this functions needs to be passed in here. | ||
A new Customize will be returned that overrides the current config | ||
with config from the builderFunction's result. | ||
a Customizer-module usually exports a `function(Customize):Customize` | ||
which in tern calls `Customize.merge` to create a new Customize instance. | ||
This function needs to be passed in here. | ||
**Parameters** | ||
A new Customize will be returned that overrides the current configuration | ||
with the configuration of the module. | ||
**builderFunction**: `function`, that receives a Customize as paramater | ||
and returns a Customize with changed configuration. | ||
**Kind**: instance method of <code>[Customize](#module_customize..Customize)</code> | ||
**Returns**: <code>Customize</code> - the Customize instance returned by the module | ||
**Access:** public | ||
**Returns**: `Customize`, the result of the builderFunction | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| customizeModule | <code>function</code> | that receives a Customize as paramater and returns a Customize with changed configuration. | | ||
##### Customize.build() | ||
<a name="module_customize..Customize+build"></a> | ||
###### customize.build() ⇒ <code>Promise.<object></code> | ||
Return a promise for the merged configuration. | ||
This functions is only needed to inspect intermediate configuration results | ||
(i.e. for testing and documentation purposes) | ||
Build the configured Bootprint-instance. | ||
**Kind**: instance method of <code>[Customize](#module_customize..Customize)</code> | ||
**Returns**: <code>Promise.<object></code> - a promise for the whole configuration | ||
**Access:** public | ||
<a name="module_customize..Customize+watched"></a> | ||
###### customize.watched() ⇒ <code>Promise.<object.<Array.<string>>></code> | ||
Return a promise for the files needing to be watched in watch-mode, | ||
indexed by engine. | ||
**Returns**: `Promise.<object>`, a promise for the whole configuration | ||
##### Customize.run() | ||
**Kind**: instance method of <code>[Customize](#module_customize..Customize)</code> | ||
**Returns**: <code>Promise.<object.<Array.<string>>></code> - a promise for the files to be watched. | ||
**Access:** public | ||
<a name="module_customize..Customize+run"></a> | ||
###### customize.run([options]) ⇒ <code>Promise.<object></code> | ||
Run each engine with its part of the config. | ||
**Kind**: instance method of <code>[Customize](#module_customize..Customize)</code> | ||
**Returns**: <code>Promise.<object></code> - an object containing on property per registered engine | ||
(the key is the engine-id) containing the result of each engine | ||
**Access:** public | ||
##### Customize.customOverrider(a, b, propertyName) | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| [options] | <code>object</code> | optional paramters | | ||
| [options.onlyEngine] | <code>string</code> | optionally the name of an engine, if only a single engine should be executed | | ||
Customize has predefined override rules for merging configs. | ||
<a name="module_customize..customize"></a> | ||
##### customize~customize() ⇒ <code>Customize</code> | ||
**Kind**: inner method of <code>[customize](#module_customize)</code> | ||
**Api**: public | ||
* If the overriding object has a `_customize_custom_overrider` function-property, | ||
it is called to perform the merger. | ||
* Arrays are concatenated | ||
* Promises are resolved and the results are merged | ||
**Parameters** | ||
**a**: , the overridden value | ||
**b**: , the overriding value | ||
**propertyName**: , the property name | ||
**Returns**: `*`, the merged value | ||
* * * | ||
## IO/Helpers | ||
### Global | ||
* * * | ||
##### files(baseDir) | ||
<a name="files"></a> | ||
#### files(baseDir) ⇒ <code>Promise.<object.<Promise.<string>>></code> | ||
The file helper resolves the directory filename to the contents of the included files (promised). | ||
**Parameters** | ||
**baseDir**: `string`, the name of the directory | ||
**Returns**: `Promise.<object.<Promise.<string>>>`, an object, containing one entry for each file. | ||
**Kind**: global function | ||
**Returns**: <code>Promise.<object.<Promise.<string>>></code> - an object, containing one entry for each file. | ||
The key of each entry is the path to the file (relative to the baseDir). The value is | ||
a promise that resolves to the file-contents when the `.then()` method is called. | ||
a promise that resolves to the file-contents when the `.then()` method is called. | ||
**Api**: public | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| baseDir | <code>string</code> | the name of the directory | | ||
* * * | ||
## License | ||
@@ -372,38 +428,8 @@ | ||
## Contributing Guidelines | ||
## Release-Notes | ||
For release notes, see [CHANGELOG.md](CHANGELOG.md) | ||
## Contributing guidelines | ||
<!-- Taken from @tunnckoCore: https://github.com/tunnckoCore/coreflow-templates/blob/master/template/CONTRIBUTING.md --> | ||
Contributions are always welcome! | ||
**Before spending lots of time on something, ask for feedback on your idea first!** | ||
Please search issues and pull requests before adding something new to avoid duplicating | ||
efforts and conversations. | ||
### Installing | ||
Fork and clone the repo, then `npm install` to install all dependencies and `npm test` to | ||
ensure all is okay before you start anything. | ||
### Testing | ||
Tests are run with `npm test`. Please ensure all tests are passing before submitting | ||
a pull request (unless you're creating a failing test to increase test coverage or show a problem). | ||
### Code Style | ||
[![standard][standard-image]][standard-url] | ||
This repository uses [`standard`][standard-url] to maintain code style and consistency, | ||
and to avoid style arguments. | ||
``` | ||
npm i standard -g | ||
``` | ||
It is intentional to don't have `standard`, `istanbul` and `coveralls` in the devDependencies. Travis will handle all that stuffs. That approach will save bandwidth also installing and development time. | ||
[standard-image]: https://cdn.rawgit.com/feross/standard/master/badge.svg | ||
[standard-url]: https://github.com/feross/standard | ||
See [CONTRIBUTING.md](CONTRIBUTING.md). |
Sorry, the diff of this file is not supported yet
101147
21
416
429
7