CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-plop

Micro-generator framework that makes it easy for an entire team to create files with a level of uniformity

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

template-system.mddocs/

Template System

Plop uses Handlebars templating with built-in helpers, custom helpers, and partials for flexible file generation. The template system supports both inline templates and external template files.

Capabilities

Helper Management

Register and use custom Handlebars helpers for template processing.

/**
 * Register a custom Handlebars helper
 * @param name - Helper name for use in templates
 * @param fn - Helper function
 */
setHelper(name: string, fn: HelperFunction): void;

/**
 * Get a registered helper function by name
 * @param name - Helper name
 * @returns Helper function
 */
getHelper(name: string): Function;

/**
 * Get list of all registered helper names
 * @returns Array of helper names
 */
getHelperList(): string[];

/**
 * @deprecated Use setHelper instead
 */
addHelper(name: string, fn: Function): void;

Usage Examples:

import { nodePlop } from "plop";

const plop = await nodePlop();

// Register a custom helper
plop.setHelper('upperCase', (text) => text.toUpperCase());

// Register a helper with options
plop.setHelper('repeat', (text, count) => {
  return new Array(count + 1).join(text);
});

// Use in templates
const template = '{{upperCase name}} - {{repeat "!" 3}}';
const result = plop.renderString(template, { name: 'hello' });
console.log(result); // "HELLO - !!!"

// List all helpers
const helpers = plop.getHelperList();
console.log(helpers);

Built-in Helpers

Plop includes numerous built-in case conversion and utility helpers.

// Case conversion helpers (all available by default)
const BUILT_IN_HELPERS = {
  // Basic case transformations
  camelCase: Function;      // myVariableName
  pascalCase: Function;     // MyVariableName  
  properCase: Function;     // Alias for pascalCase
  snakeCase: Function;      // my_variable_name
  kebabCase: Function;      // my-variable-name
  dashCase: Function;       // Alias for kebabCase
  kabobCase: Function;      // Alias for kebabCase
  constantCase: Function;   // MY_VARIABLE_NAME
  dotCase: Function;        // my.variable.name
  pathCase: Function;       // my/variable/name
  sentenceCase: Function;   // My variable name
  titleCase: Function;      // My Variable Name
  lowerCase: Function;      // my variable name
  upperCase: Function;      // MY VARIABLE NAME
  
  // Package helper
  pkg: Function;            // Access package.json properties
};

Usage Examples:

// Template using built-in helpers
const template = `
class {{pascalCase name}} {
  constructor() {
    this.{{camelCase name}} = '{{kebabCase name}}';
    this.version = '{{pkg "version"}}';
  }
}
`;

const result = plop.renderString(template, { name: 'my-component' });

Partial Management

Register and use Handlebars partials for reusable template components.

/**
 * Register a Handlebars partial
 * @param name - Partial name for use in templates
 * @param str - Partial template string
 */
setPartial(name: string, str: string): void;

/**
 * Get a registered partial by name
 * @param name - Partial name
 * @returns Partial template string
 */
getPartial(name: string): string;

/**
 * Get list of all registered partial names
 * @returns Array of partial names
 */
getPartialList(): string[];

/**
 * @deprecated Use setPartial instead
 */
addPartial(name: string, str: string): void;

Usage Examples:

const plop = await nodePlop();

// Register partials
plop.setPartial('header', '// Generated by Plop on {{date}}');
plop.setPartial('footer', '// End of generated file');

// Register a partial with parameters
plop.setPartial('method', `
  {{#if async}}async {{/if}}{{name}}({{#each params}}{{name}}{{#unless @last}}, {{/unless}}{{/each}}) {
    {{body}}
  }
`);

// Use partials in templates
const template = `
{{> header}}

class {{pascalCase name}} {
  {{#each methods}}
  {{> method this}}
  {{/each}}
}

{{> footer}}
`;

const result = plop.renderString(template, {
  name: 'my-class',
  date: new Date().toISOString(),
  methods: [
    {
      name: 'getData',
      async: true,
      params: [{ name: 'id' }],
      body: 'return await api.get(id);'
    }
  ]
});

Template Sources

Specify templates using inline strings or external files.

// Template source configuration
interface TemplateStrOrFile {
  template?: string;        // Inline template string
  templateFile?: string;    // Path to template file
}

// Used in action configurations
interface ActionWithTemplate extends ActionConfig, TemplateStrOrFile {
  // Action-specific properties
}

Usage Examples:

// Using inline template
{
  type: 'add',
  path: 'src/{{name}}.js',
  template: 'export const {{name}} = "{{value}}";'
}

// Using template file
{
  type: 'add',
  path: 'src/{{name}}.js',
  templateFile: 'templates/module.hbs'
}

// Template file: templates/module.hbs
import React from 'react';

export const {{pascalCase name}} = ({{#if props}}{ {{#each props}}{{name}}{{#unless @last}}, {{/unless}}{{/each}} }{{/if}}) => {
  return (
    <div className="{{kebabCase name}}">
      {{#if children}}
        {children}
      {{else}}
        <h1>{{titleCase name}}</h1>
      {{/if}}
    </div>
  );
};

Template Processing

Advanced template processing with transform functions and data manipulation.

/**
 * Transform function applied after template rendering
 * @param template - Rendered template string
 * @param data - Template data object
 * @param config - Action configuration
 * @returns Transformed template string
 */
type TransformFn<T> = (template: string, data: any, config: T) => string;

Usage Examples:

// Action with transform function
{
  type: 'add',
  path: 'src/{{name}}.js',
  templateFile: 'templates/component.hbs',
  transform: (template, data, config) => {
    // Add custom processing
    if (data.typescript) {
      template = template.replace(/\.js/g, '.ts');
    }
    
    // Add prettier formatting
    return prettier.format(template, { parser: 'babel' });
  }
}

// Advanced data processing in template
const template = `
{{#each items}}
  {{#if (eq type "component")}}
    {{> component-partial this}}
  {{else if (eq type "service")}}
    {{> service-partial this}}
  {{/if}}
{{/each}}
`;

Template Data Context

Template data includes user answers plus built-in context variables.

interface TemplateData extends UserAnswers {
  // Built-in context available in all templates
  [key: string]: any;       // User-provided answers from prompts
}

Template Context Examples:

{{!-- User answers from prompts --}}
Component: {{name}}
Type: {{type}}
Props: {{#each props}}{{name}}: {{type}}{{/each}}

{{!-- Built-in helpers --}}
File: {{kebabCase name}}.jsx
Class: {{pascalCase name}}
Constant: {{constantCase name}}_CONFIG

{{!-- Package.json access --}}
Version: {{pkg "version"}}
Author: {{pkg "author.name"}}

{{!-- Conditional rendering --}}
{{#if typescript}}
interface {{pascalCase name}}Props {
  {{#each props}}
  {{name}}: {{type}};
  {{/each}}
}
{{/if}}

{{!-- Loops and arrays --}}
{{#each methods}}
  {{#unless @first}}
  
  {{/unless}}
  {{name}}(): {{returnType}} {
    // TODO: Implement {{name}}
  }
{{/each}}

Advanced Template Features

Conditional Logic

Use Handlebars conditionals for dynamic template generation.

{{#if condition}}
  Render this when condition is true
{{else if otherCondition}}
  Render this when otherCondition is true
{{else}}
  Default content
{{/if}}

{{#unless disabled}}
  Render this when disabled is false
{{/unless}}

Loops and Iteration

Iterate over arrays and objects in templates.

{{#each items}}
  Item {{@index}}: {{name}} ({{@first}} {{@last}})
{{/each}}

{{#each object}}
  {{@key}}: {{this}}
{{/each}}

Helper Combinations

Combine multiple helpers for complex transformations.

{{pascalCase (replace name "-" "")}}
{{upperCase (substring description 0 50)}}
{{#each (sort items "name")}}
  {{camelCase name}}: {{value}}
{{/each}}

Install with Tessl CLI

npx tessl i tessl/npm-plop

docs

action-system.md

cli.md

console.md

generator-api.md

index.md

programmatic.md

template-system.md

tile.json