What is Plop?

Plop is a file generator tool system which allows you to define a script file to generate all the boilerplate files for you. Similar in how Angular schematics works, you can define a set of actions who would generate all the pre-defined code for you either automatically or by answering to some CLI prompts.

First you will need to define a plopfile.js who would contain a function who would receive a plop object with access to all the methods to generate the code.

module.exports = function (plop) {
    plop.setGenerator('components', {
        description: 'This will generate the components folder',
        prompts: [{
            type: 'input',
            name: 'name',
            message: 'type the name for your components folder'
        }],
        actions: [{
            type: 'add',
            path: 'src/components/{{name}}.component.js',
            templateFile: 'plop-templates/components.hbs'
        }]
    });
};
  • First of all we will use the .setGenerator function using 'components' as the generator name, so if we want to trigger this generator we would use plop components.
  • Then, in the prompts array, we will define a array of InquirerQuestion we could later use the input values for these question as parameters in our templates.
  • Finally, actions, who accept a array of ActionConfig, these actions will act on the files we will create and adapt them according to our needs.

We will also need to add a new folder were we will store our template, I will call it plop-templates and add a new file components.hbs.

<br />{{name}}

We will have the following structure:

initial folder structure

Now if we jump into the console in within our folder where we have the plopfile file and type plop components we will be asked 'type the name for your components folder' which is the message we defined in the message key for th object of the prompts array. After answering it will generate a folder with the answer we provided, in my case was test-components.

After this we will have the following structure:

folder structure

And if we open the generated test-components.js we will see that the {{name}} variable has been modified with the name we provided in the console:

test-components

When to use Plop

Now that we saw a simple example of how it works we can start creating more complex templates to automate our task. For example, we will create a new generator to generate all our Redux boilerplate for us.

main.hbs

import { Action } from '@ngrx/store';

// constants

// actions

export type {{pascalCase fileName }}Actions =
;

constants.hbs

export const {{constantCase actionName}} = '[Talents] {{actionName}}';
export const {{constantCase actionName}}_FAIL = '[Talents] {{actionName}} Fail';
export const {{constantCase actionName}}_SUCCESS = '[Talents] {{actionName}} Success';

actions.hbs

export class {{pascalCase actionName}} implements Action {
public readonly type = {{constantCase actionName}};
constructor(public payload) {}
}

export class {{pascalCase actionName}}Fail implements Action {
public readonly type = {{constantCase actionName}}_FAIL;
constructor(public payload) {}
}

export class {{pascalCase actionName}}Success implements Action {
public readonly type = {{constantCase actionName}}_SUCCESS;
constructor(public payload) {}
}

typeExport.hbs

| {{pascalCase actionName}}
| {{pascalCase actionName}}Success
| {{pascalCase actionName}}Fail

ploplfile.js

module.exports = function (plop) {
    plop.setGenerator('actions', {
        description: 'This will generate the actions file',
        prompts: [
            {
                type: 'input',
                name: 'fileName',
                message: 'type the name for your file'
            },
            {
                type: 'input',
                name: 'actionName',
                message: 'type the name for your action'
            }
        ],
        actions: [
            {
                type: 'add',
                path: '{{pascalCase fileName}}.actions.ts',
                templateFile: 'plop-templates/actions/main.hbs',
                skipIfExists: true
            },
            {
                type: 'append',
                path: '{{pascalCase fileName}}.actions.ts',
                pattern: /(\/\/ constants)/g,
                templateFile: 'plop-templates/actions/constants.hbs',
            },
            {
                type: 'append',
                path: '{{pascalCase fileName}}.actions.ts',
                pattern: /(\/\/ actions)/g,
                templateFile: 'plop-templates/actions/actions.hbs',
            },
            {
                type: 'append',
                path: '{{pascalCase fileName}}.actions.ts',
                pattern: /(export\s+type\s[\w]+\s=)/g,
                templateFile: 'plop-templates/actions/typeExport.hbs',
            }
        ]
    });
};

Link to the repo