💧 very easy to use multi-language scaffolding/boilerplate tool for creating code for your existing projects
A growing big project might eventually require contributors to write different boilerplates/code templates to be used as a starting point for new modules. Most often those templates are files to copy-paste followed by few variable renamings to reflect new module's name. water-drop
is a scaffolding/boilerplate tool which allows to create new code based on the provided existing templates written by anyone.
This tool was created keeping in mind the following conditions:
- It has to work for multiple languages (Go, JavaScript, Python, etc).
- It has to be easy to use. Nobody should go through pages of documentation or reading many lines of code in order to understand how this tool works.
- It has to be easy to setup new templates to be used by everyone. (For this project
Handlebars
was picked as the main templating engine for its simplicity. You can read more onHandlebars
templating here)
Global installation (suggested)
$ npm i -g water-drop
$ water-drop
Local installation
$ npm install water-drop
$ node_modules/.bin/water-drop
USAGE
$ water-drop <command>
where <command> is one of:
init, list, template, create, uninit
water-drop <command> -i quick help on <command>
EXAMPLES
$ water-drop init
$ water-drop create myNewShinyModule -t exampleModule -p path/within/my/project -v
$ water-drop list
$ water-drop template mySecondShinyModule
$ water-drop template moduleToRemove -d
$ water-drop uninit
- Let's imagine our team need to create lots of new modules which have the same comment about MIT license.
- Let's imagine we need to include a constant file inside our new module.
$ cd /my/amazing/project/
$ water-drop init
$ water-drop template licensedCode
modify water-drop-templates/licensedCode/config.json
file
{
"steps": [
{ "cmd": "mkdir", "path": "{{myProjectPath}}/{{_mPath}}" },
{
"cmd": "cpf",
"what": "licensedFile.js",
"to": "{{myProjectPath}}/{{_mPath}}/{{lcase _mName}}.js"
},
{
"cmd": "cp",
"what": "constants.js",
"to": "{{myProjectPath}}/{{_mPath}}/constants.js"
}
],
"vars": {
"myProjectPath": "./",
"author": "Alexey Novak"
}
}
Create file water-drop-template/licensedCode/__files/licensedFile.js
// MIT © {{author}}
import * from './constants.js';
function {{ucase _mName}}() {
}
export default {{ucase _mName}};
Create file water-drop-template/licensedCode/__files/constants.js
const config = {
VERSION: '1.0.0',
// place your config files here
};
export default config;
Run $ water-drop create NewModule -t licensedCode -p /ui/utils -v
New folder ui/utils/
should be generated in the same folder as water-drop.json
config file.
With new files ui/utils/constants.js
and ui/utils/newModule.js
{ "cmd": "mkdir", "path": "some/folder/structure" }
Property | Description | Can Use Templating |
---|---|---|
path |
New folder path. The whole folder tree will be created if does not exist. Path is relative to the folder where water-drop command is executed. |
Yes |
{
"cmd": "cp",
"what": "fileTemplate.txt",
"to": "some/folder/structure/file.txt"
},
Property | Description | Can Use Templating |
---|---|---|
what |
Path to the file within water-drop-template/<template_type>/ to be used for a file copy operation. |
No |
to |
Path to where file will be copied over. Path is relative to the folder where water-drop command is executed. |
Yes |
{
"cmd": "cpf",
"what": "fileTemplate.txt",
"to": "some/folder/structure/file.txt"
},
Property | Description | Can Use Templating |
---|---|---|
what |
Path to the file within water-drop-template/<template_type>/ to be used for a file copy operation. water-drop will apply templating to the content of the file to make changes on its content. |
No |
to |
Path to where file will be copied over. Path is relative to the folder where water-drop command is executed. |
Yes |
Helper | Description | Example |
---|---|---|
ucase |
Uppercases first character | myModule -> MyModule |
lcase |
Lowercases first character | MyModule -> myModule |
ucaseall |
Uppercases the whole string | myModule -> MYMODULE |
lcaseall |
Lowercases the whole string | MyModule -> mymodule |
u_case_all |
Uppercases the whole string and also adds _ character between each uppercase character |
MyModule -> MY_MODULE |
l_case_all |
Lowercases the whole string and also adds _ character between each uppercase character |
MyModule -> my_module |
Handlebars
uses context object for templating function. Context for each template consist of the following variables:
- All variables within vars property of the config withijn
water-drop.json
file - All variables within vars property of the template configuration within
water-drop.json
file - _mType - template type used to create new module (passed through CLI)
- _mName - new module name (passed through CLI)
- _mPath - path to the new module (passed through CLI)
Also some specific water-drop
tool configuration which most of the times you do not need to modify:
- _tFolder - location of the folder with template files
- _tOpenTag - special open tag to be used for
cpf
command - _tCloseTag - special close tag to be used for
cpf
command
It is very important to remember that Handlebars
keeps {{
and }}
reserved for its template logic. Use <%%
and %%>
respectively in case when a template needs to preserve those tags.
Example:
style=<%% weight: 50px, height: 50px %%>
will be converted to
style={{ weight: 50px, height: 50px }}
Also you might face a problem when trying to replace a value within the object. Example:
// some of my react code
object={this.props.{{lcase _mName}}}
// this would fail since Handlebars would not like those closing }}}
You will need to re-write it as
object={this.props.{{lcase _mName}} }
- There are no tests present for this project yet.
- Step command which will be able to inject a line of code into another existing file "in a smart way".
- Roll-back mechanism for any auto-generated content in case when there is an error during execution.
- Ability to pre-parse and detect issues within the config prior steps execution.
- More detailed logging to identify an exact problem when there is a failure.
MIT license; see LICENSE.
(c) 2017 by Alexey Novak