A command line utility that allows to scaffold new projects.
Install the CLI with npm: npm i -g @option26/scaffold
If you want to create a new project from a template, run the scaffold command: scaffold [source] [target]
.
source
can either be a relative or absolute path the template in your file system or alternatively a URL to a git repository.target
has to be a path (relative or absolute) to an empty folder in your filesystem.
scaffold https://github.com/option26/template.git . // Clones the repository from 'https://github.com/option26/template.git' and scaffolds the project to the current directory.
scaffold template/directory /full/target/directory // Scaffolds the project from a template located at $CWD/template/directory to '/full/target/directory'.
In order to create a template, simply add a template.json
file to the root of your template project directory. This files specifies all the information for the templating process.
The template.json
file has the following structure:
{
// Template name (shown when scaffolding project).
name: string;
// Template description (shown when scaffolding project).
description: string;
// List of paths (globs allowed) to be excluded (i.e not copied) from the template. By default, **/.git and **/node_modules are excluded.
exclude: string[];
// List of paths (globs allowed) to be ignored (i.e. copied but not parsed). Useful if a file contains nunjucks syntax.
ignore: string[];
// For each entry, if variable 'name' has specified 'value', all 'paths' are deleted in the final project (no globs allowed).
cleanup: Array<{
name: string,
value: any,
paths: string[]
}>;
// List of variables that will be requested from the user. Follows structure of https://github.com/SBoudrias/Inquirer.js#readme
variables: Array<{
type: string;
name: string;
prompt: string;
default: any;
promptIf?: { name: string, value: any }; // Only as this, if variable 'name' equals 'value'
validation?: { regex: string };
choices?: any[];
}>;
}
The scaffolding process works as follows
- If the
source
is a git repository, clone it's content. Else, check if specified directory exists. - Check if
target
directory exists and is empty - Try to locate the
template.json
file in the source directory and read its contents - Gather user input based on the
variables
property of the template configuration - Iterate over each file/folder in the source directory and
- If the path is in the
exclude
array, skip this file/directory - Else, parse the filename and fill template variables to determine output path (This is useful if you want to name files/folders based on user input)
- If the current path is in the
ignore
array, simply copy the file to the target - Else, read the file content and fill template variables
- If the file was a folder, run the steps recursively
- If the path is in the
- For each entry in the
cleanup
array, check if the condition is true and if so, remove all specified paths from the target directory. - If we cloned a template repository earlier, remove the temporary directory
Scaffold uses the nunjucks templating language to process files and paths in a project template.
You can use templating inside file paths by simply naming the file with a valid nunjucks template string and the filename will be replaced later. This can also be done for the paths in exclude
, ignore
and cleanup
in template config.
Inside files, you can use the default nunjucks syntax including control statements and alike.
The values passed to the nunjucks environment are based on the user input given earlier. As described, this can be configured by specifying entries in the variables
property.
If you manage your template as a git repository, you might want to add .gitignore
files. However, you might also want to template .gitignore
files. As a result, there would be a naming conflict. You can resolve this as follows:
- Create a
.gitignore
file for your template repository just like you usually would. - In your template config, add a new item to the
exclude
array:**/.gitignore
- Now, add the
.gitignore
files you want to template. In order to avoid a naming conflict, name them.gitignore{{template}}
.
TODO