Plop Micro-generator Framework

4.0.5 · active · verified Sun Apr 19

Plop is a micro-generator framework designed to streamline the creation of consistent files and code patterns within a project. It acts as 'glue code' connecting Inquirer.js prompts for user input and Handlebars.js templates for content generation. The current stable version is 4.0.5, with patch and minor releases occurring periodically to address bugs, update dependencies, and introduce performance improvements. Major versions, like v4.0.0, introduce breaking changes such as updated Node.js requirements. Plop's core differentiator is its simplicity and focus on turning best practices for file creation into easily executable terminal commands, reducing manual boilerplate and ensuring uniformity across development teams.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates how to programmatically use `nodePlop` from the `plop` package to define and execute a generator, simulating user input for component creation. It sets up a basic `plopfile` to generate a React component, including a TypeScript file and an optional CSS module, then cleans up the temporary files.

import { nodePlop } from 'plop';
import path from 'path';
import fs from 'fs';

// A minimal plopfile content
const plopfileContent = `
export default function (plop) {
  plop.setGenerator('component', {
    description: 'Create a new React component',
    prompts: [
      {
        type: 'input',
        name: 'name',
        message: 'Component name (e.g., Button):'
      },
      {
        type: 'confirm',
        name: 'hasStyle',
        message: 'Include a CSS module?'
      }
    ],
    actions: [
      {
        type: 'add',
        path: 'src/components/{{pascalCase name}}/{{pascalCase name}}.tsx',
        templateFile: 'plop-templates/component.tsx.hbs',
      },
      {
        type: 'add',
        path: 'src/components/{{pascalCase name}}/index.ts',
        template: 'export * from "./{{pascalCase name}}";'
      },
      {
        type: 'add',
        path: 'src/components/{{pascalCase name}}/{{pascalCase name}}.module.css',
        template: '.{{camelCase name}} {\n  /* styles */\n}',
        skip: (data) => !data.hasStyle ? 'Skipping style file' : undefined
      }
    ]
  });
};
`;

// Create a temporary plopfile for demonstration
const tempPlopfilePath = path.join(process.cwd(), 'temp-plopfile.mjs');
const templateDir = path.join(process.cwd(), 'plop-templates');
fs.mkdirSync(templateDir, { recursive: true });
fs.writeFileSync(path.join(templateDir, 'component.tsx.hbs'), `
import React from 'react';
{{#if hasStyle}}import styles from './{{pascalCase name}}.module.css';{{/if}}

interface {{pascalCase name}}Props {
  // Define props here
}

export const {{pascalCase name}}: React.FC<{{pascalCase name}}Props> = ({}) => {
  return (
    <div{{#if hasStyle}} className={styles.{{camelCase name}}}{{/if}}>
      Hello from {{pascalCase name}}!
    </div>
  );
};
`);
fs.writeFileSync(tempPlopfilePath, plopfileContent);

// Programmatically run a plop generator
async function runGenerator() {
  const plop = await nodePlop(tempPlopfilePath, { 
    cwd: process.cwd(), 
    dest: process.cwd() 
  });
  const generator = plop.getGenerator('component');

  // Simulate user input for component 'MyComponent' with styles
  const results = await generator.runActions({
    name: 'MyComponent',
    hasStyle: true
  });

  console.log('Generator results:', results);

  // Clean up temporary files
  fs.unlinkSync(tempPlopfilePath);
  fs.unlinkSync(path.join(templateDir, 'component.tsx.hbs'));
  fs.rmdirSync(templateDir);

  console.log('Generated files for MyComponent and cleaned up temporary files.');
}

runGenerator().catch(console.error);

view raw JSON →