Create project from templates with cool templating capabilities to replace variables in files and paths.
Installation — Documentation — Contributing — License
To start to use Project Scaffolder
, you should first create a npm
module with its package.json
.
Then, You should create:
- A folder
template
which will contain your project template files - A configuration file
scaff.yml
which contains the configuration of your template
projectFolder
|- package.json
|- scaff.yml
|- template/
At this stage, you will be able to install the module project-scaffolder
.
npm install --save project-scaffolder
This README is the main usage documentation.
Project Scaffolder
uses external libraries to provide some of its functionality; refer to their documentation for more information:
The source code is also heavily commented and run through Docker, so you can read the resulting annotated source code for more details about the implementation.
Check the CHANGELOG for information about new features and breaking changes.
- Examples
- How to create a project template
- How to override config file and template folder
- How to write the configuration file
Before going in the details, let's take a look to some examples.
In order to generate a new project based on a template, you should prepare that template. Let's start with a basic example.
Our template project (you can take a look to the First example.) has the following content:
examples/first/
|- package.json
|- scaff.yml
|- template/
|- templateFile.txt
The resulting project from that template will be:
results/first/
|- templateFile.txt
In fact, the content of the templateFile.txt
Welcome {{ username }}!
will become (if the username has the value John
):
Welcome John!
To get that result, we use the following commands and we give the answer John
to the question and also an output folder to store the generated content.
$> cd <projectTemplatePath>
$> project-scaffolder
prompt: Enter your username: John
prompt: finally the output directory (will be created if not existing): <outputFolder>
Project configuration:
username: John
Then you can see the result.
In the second example, we will see an example that use also filtering into the file paths.
Our template project (you can take a look to the Second example.) has the following content:
examples/second/
|- package.json
|- scaff.yml
|- template/
|- __subPath__/
|- templateFile.txt
The resulting project from that template will be (if subpath value is one/two/three
):
destination/folder/
|- one/
|- two/
|- three/
|- templateFile.txt
In fact, the content of the templateFile.txt
Welcome {{ username }}!
will become (if the username has the value John
):
Welcome John!
To get that result, we use the following commands and we give the answer John
to the question and also an output folder to store the generated content.
$> cd <projectTemplatePath>
$> project-scaffolder
prompt: Enter your username: John
prompt: Enter the sub path: one/two/three
prompt: finally the output directory (will be created if not existing): <outputFolder>
Project configuration:
username: John
subPath: one/two/three
Then you can see the result.
Based on the previous examples, you see that your project template need to contains several elements that are used to generate your project from your template.
package.json
Define yournpm
module to allow usingproject-scaffolder
in a specific version for your project template;scaff.yml
where you will store the configuration to be prompt to your template user (and later on, additional project template properties that can be used in the template generation proecss);template
the folder where your template files are stored. The content of this folder will be processed and filtered to generate your project.
The files stored in the template folder can be:
text
files that will be handled by templating engine to apply the filtering;binary
file that will be simply copy from the project template to the project generated.
During the generation process, each text
files will be given to Nunjucks which is the template engine used in project-scaffolder
. This template engine is based on Jinja template engine. Then the syntax is quite similar and the possiblity to use filters is there. It means that you can be able to write something like that in your template files:
{{ someVariable | upper }}
which will result to (if someVariable value is "John"):
JOHN
The same possibility is available to filter the paths but there, we need a different syntax.
The syntax for variable replacement and filtering is the following:
__variableName__
and
__variableName-filterName__
The limitation of that syntax is that you cannot use -
in the variable name or the filter name.
By default, the scaff.yml
and template
folder are mandatory in a template project but you have the possibility to use a custom folder path and a custom configuration file.
For that, you have to use environment variables when you invoke project-scaffolder
.
$> SCAFF_TEMPLATE_CONFIG_FILE=some/great/path/to/config.yml SCAFF_TEMPLATE_FOLDER=some/greate/to/project/template project-scaffolder
You can use only one of these options if you want.
First, you need to create the file scaff.yml
at the root of your template project.
Now, you are able to write something like that:
prompt:
properties:
propertyName:
message: Some message there
required: true
default: some default value
extras:
- extra-module
This configuration section defines the questions that will be asked when the command project-scaffolder
is run in the template project.
As the project-scaffolder
use the module prompt
to present the command line user interface, you can define the options as described in prompt
documentation.
There is only one exception which do not allow to use before
.
Then you can define a command line question like that:
propertyName:
description: String
type: String
pattern: RegExp
message: String
hidden: true|false
default: String
required: true|false
Note: The property name will be used as placeholder name during the templating process. Example:
package:
description: Define the root package for java classes
required: true
default: com.some.where
and one template somewhere:
package {{ package }}.else;
public class {
}
which will produce that result if the default value is used:
package com.some.where.else;
public class {
}
This configuraiton section allow to load more modules for Nunjucks
to enrich filters
and tags
.
The module names specified in the list should be installed in the project as usual via npm
.
The modules must follow the requirements explained in project-scaffolder-extras
In summary, extra module must expose an object which contains the following structure:
module.syncFilters = {
syncFilterName: function(arg1, arg2, ...) {
...
return ...;
}
};
module.asyncFilters = {
asyncFilterName: function(arg1, arg2, callback) {
...
callback(err, res);
}
};
module.syncTags = {
syncTagName: function(...) {
...
return ...;
}
};
module.asyncTags = {
asyncTagName: function(..., callback) {
...
callback(err, res);
}
};
You can also have this syntax:
module.filtersSync = {};
module.filtersAsync = {};
module.tagsSync = {};
module.tagsAsync = {};
You should carefully read the documentation of Nunjucks
to know how to write filters and tags (synchronous vs. asynchronous).
Note: Currently, the asynchronous filters are not supported for the filtering process done in file paths of the template.
- Fork
- Create a topic branch -
git checkout -b feature
- Push to your branch -
git push origin feature
- Create a pull request from your branch
Please add a changelog entry with your name for new features and bug fixes.
Project Scaffolder is licensed under the MIT License. See LICENSE.txt for the full text.