Creating a new template
To create a new template, runmoon generate while passing the --template option. This will create a template directory and template.* file in the 1st file-based template location defined in generator.templates.
Configure template metadata
Every template requires a
template.* file in the template’s directory root. This file acts as a schema and declares metadata and variables required by the generator.template.yml
Add template files
Feel free to add any files and folders to the template that you’d like to be generated by consumers! These files will then be scaffolded 1:1 in structure at the target destination.An example of the templates folder structure may look something like the following:
Use template syntax (optional)
Template files use Tera template engine with syntax similar to Twig, Liquid, and Django.
package.json
Template features
Interpolation
Variables can be interpolated into file paths using the form[varName]. For example, if you had a template file src/[type].ts, and a variable type with a value of “bin”, then the destination file path would be src/bin.ts.
This syntax also supports filters, such as [varName | camel_case].
File extensions
To enable syntax highlighting for template engine syntax, you may use the.tera (preferred) or .twig file extensions. These extensions are optional, but will be removed when the files are generated.
Depending on your preferred editor, these extensions may be supported through a plugin:
- VS Code - Tera extension or Twig extension
- Atom - Twig package
- Webstorm - Twig plugin
Partials
Partials are special template files that are used for composition and inheritance. Because of this, these files should not be generated into the target destination, and do not support frontmatter. To ensure they are not generated, include the word “partial” anywhere in the file path. For example,partials/header.tpl or header.partial.tpl.
Raws
Raw template files are another special type of file that bypass all Tera rendering, and are used as-is instead. This is useful for files that contain syntax that conflicts with Tera. To mark a file as raw, add a.raw extension, for example: file.raw.js or file.js.raw. When the file is generated, the .raw extension will be removed.
Frontmatter
Frontmatter is a well-known concept for “per-file configuration”, and is achieved by inserting YAML at the top of the file, delimited by wrapping---. This is a very powerful feature that provides more control than the alternatives.
package.json
Template engine & syntax
Rendering templates is powered by Tera, a Rust based template engine with syntax similar to Twig, Liquid, Django, and more.Variable interpolation
Conditional blocks
Loops
Filters
Filters are a mechanism for transforming values during interpolation and are written using pipes (|). Tera provides many built-in filters, but we also provide the following custom filters:
- Strings -
camel_case,pascal_case,snake_case,upper_snake_case,kebab_case,upper_kebab_case,lower_case,upper_case
- Paths -
path_join,path_relative
Built-in variables
The following variables are always available within a template:dest_dir- Absolute path to the destination folder.dest_rel_dir- Relative path to the destination folder from the working directory.working_dir- Current working directory.workspace_root- The moon workspace root.
Generating code from a template
Once a template has been created and configured, you can generate files based on it using themoon generate command! This is also know as scaffolding or code generation.
This command requires the name of a template as the 1st argument. The template name is the folder name on the file system that houses all the template files, or the id setting configured in template.*.
This command is extremely interactive, as we’ll prompt you for the destination path, variable values, whether to overwrite files, and more. If you’d prefer to avoid interactions, pass
--defaults, or --force, or both.Configuring template locations
Templates can be located anywhere, especially when being shared. Because of this, our generator will loop through all template paths configured ingenerator.templates, in order, until a match is found.
.moon/workspace.yml
Archive URLs
Template locations can reference archives (zip, tar, etc) through https URLs. These archives should contain templates and will be downloaded and unpacked..moon/workspace.yml
Archives will be unpacked to
~/.moon/templates/archive/<host>, and will be cached for future use.Globs
If you’d prefer more control over literal file paths, you can instead use glob paths or theglob:// protocol. Globs are relative from the workspace root, and will only match directories, or patterns that end in template.*.
.moon/workspace.yml
Git repositories
Templates locations can also reference templates in an external Git repository using thegit:// locator protocol. This locator requires the Git host, repository path, and revision (branch, tag, commit, etc).
.moon/workspace.yml
Git repositories will be cloned to
~/.moon/templates/git/<host> using an HTTPS URL (not a Git URL), and will be cached for future use.npm packages
Additionally, template locations can also reference npm packages using thenpm:// locator protocol. This locator requires a package name and published version.
.moon/workspace.yml
npm packages will be downloaded and unpacked to
~/.moon/templates/npm and cached for future use.Declaring variables with CLI arguments
During generation, you’ll be prompted in the terminal to provide a value for any configured variables. However, you can pre-fill these variable values by passing arbitrary command line arguments after-- to moon generate. Argument names must exactly match the variable names.
Using the package template example above, we could pre-fill the name variable like so:
- Array variables support multiple options of the same name.
- Boolean variables can be negated by prefixing the argument with
--no-<arg>. - Object variables can not declare values through arguments.
Sharing templates
Although moon is designed for a monorepo, you may be using multiple repositories and would like to use the same templates across all of them. You can share templates using:- Git submodules
- Git repositories (using
git://protocol) - File archives
- Node.js modules
- npm packages (using
npm://protocol) - Another packaging system
generator.templates to point to these locations:
.moon/workspace.yml