Lodash-based template engine with custom delimiters, date utilities, and configuration integration. Supports complex template processing with runtime data binding and custom template delimiters.
Process templates with data using Lodash template syntax or custom delimiters.
/**
* Process template string with data
* @param {string} template - Template string with placeholders
* @param {object} [options] - Processing options
* @param {object} [options.data] - Data object for template variables
* @param {string} [options.delimiters] - Custom delimiter set name
* @returns {string} Processed template string
*/
grunt.template.process = function(template, options) {};
/**
* Set active template delimiters
* @param {string} name - Delimiter set name ('config' or custom)
*/
grunt.template.setDelimiters = function(name) {};
/**
* Add custom template delimiters
* @param {string} name - Delimiter set name
* @param {string} opener - Opening delimiter
* @param {string} closer - Closing delimiter
*/
grunt.template.addDelimiters = function(name, opener, closer) {};Usage Examples:
// Basic template processing with configuration data
const template = 'Project: <%= pkg.name %> v<%= pkg.version %>';
const processed = grunt.template.process(template);
// Uses grunt.config data automatically
// Process with custom data
const customTemplate = 'Hello <%= name %>!';
const result = grunt.template.process(customTemplate, {
data: { name: 'World' }
});
// Result: "Hello World!"
// Complex template with nested properties
const complexTemplate = `
Build Configuration:
- Name: <%= project.name %>
- Environment: <%= env.NODE_ENV %>
- Build Number: <%= build.number %>
- Timestamp: <%= build.timestamp %>
`;
const processed = grunt.template.process(complexTemplate, {
data: {
project: { name: 'MyApp' },
env: process.env,
build: {
number: 42,
timestamp: new Date().toISOString()
}
}
});
// Using custom delimiters
grunt.template.addDelimiters('mustache', '{{', '}}');
grunt.template.setDelimiters('mustache');
const mustacheTemplate = 'Hello {{name}}!';
const mustacheResult = grunt.template.process(mustacheTemplate, {
data: { name: 'Mustache' }
});Date formatting utilities with support for SOURCE_DATE_EPOCH environment variable.
/**
* The dateformat library for advanced date formatting
* @type {function}
*/
grunt.template.date = require('dateformat');
/**
* Format current date using dateformat patterns
* @param {string} [format='yyyy-mm-dd'] - Date format pattern
* @returns {string} Formatted date string
*/
grunt.template.today = function(format) {};Usage Examples:
// Current date with default format
const today = grunt.template.today();
// Result: "2023-12-25" (yyyy-mm-dd format)
// Custom date formats
const timestamp = grunt.template.today('yyyy-mm-dd HH:MM:ss');
const shortDate = grunt.template.today('m/d/yy');
const longDate = grunt.template.today('dddd, mmmm dS, yyyy');
// Use in templates
const bannerTemplate = '/*! Built on <%= grunt.template.today("yyyy-mm-dd") %> */';
const banner = grunt.template.process(bannerTemplate);
// Direct dateformat usage for custom dates
const releaseDate = grunt.template.date(new Date('2023-12-25'), 'fullDate');
const buildTime = grunt.template.date(Date.now(), 'HH:MM:ss');
// Respect SOURCE_DATE_EPOCH for reproducible builds
process.env.SOURCE_DATE_EPOCH = '1672531200'; // Unix timestamp
const reproducibleDate = grunt.template.today('yyyy-mm-dd');
// Will use the epoch time instead of current timeUsing templates within Grunt configuration and tasks.
Configuration Templates:
// Templates in grunt configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
meta: {
banner: '/*! <%= pkg.name %> v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
concat: {
options: {
banner: '<%= meta.banner %>'
},
dist: {
src: ['src/*.js'],
dest: 'dist/<%= pkg.name %>.js'
}
},
uglify: {
options: {
banner: '<%= meta.banner %>'
},
dist: {
files: {
'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
}
}
});
// Dynamic file paths with templates
const buildConfig = {
version: '1.2.0',
paths: {
src: 'src',
dist: 'dist/<%= version %>',
tmp: '.tmp/<%= version %>'
}
};
grunt.initConfig(buildConfig);Task Template Processing:
// Process templates in tasks
grunt.registerTask('generate-config', function() {
const template = grunt.file.read('config.template.js');
const config = grunt.template.process(template, {
data: {
apiUrl: process.env.API_URL || 'http://localhost:3000',
version: grunt.config.get('pkg.version'),
buildTime: grunt.template.today('yyyy-mm-dd HH:MM:ss')
}
});
grunt.file.write('dist/config.js', config);
});
// Multi-task with template processing
grunt.registerMultiTask('template-files', function() {
const options = this.options({
data: {}
});
this.files.forEach(function(fileObj) {
fileObj.src.forEach(function(srcFile) {
const template = grunt.file.read(srcFile);
const processed = grunt.template.process(template, {
data: options.data
});
grunt.file.write(fileObj.dest, processed);
grunt.log.writeln('Template processed: ' + srcFile + ' -> ' + fileObj.dest);
});
});
});Complex templating scenarios and best practices.
Conditional Templates:
// Template with conditional logic
const conditionalTemplate = `
<% if (env === 'production') { %>
// Production build
const API_URL = '<%= prodApiUrl %>';
<% } else { %>
// Development build
const API_URL = '<%= devApiUrl %>';
<% } %>
const VERSION = '<%= version %>';
`;
const config = grunt.template.process(conditionalTemplate, {
data: {
env: process.env.NODE_ENV,
version: '1.0.0',
prodApiUrl: 'https://api.example.com',
devApiUrl: 'http://localhost:3000'
}
});Template Loops:
// Template with loops
const listTemplate = `
const MODULES = [
<% modules.forEach(function(module) { %>
'<%= module %>',
<% }); %>
];
`;
const moduleConfig = grunt.template.process(listTemplate, {
data: {
modules: ['core', 'ui', 'utils', 'api']
}
});Nested Template Processing:
// Multi-level template processing
grunt.registerTask('build-manifest', function() {
// First level: process file paths
const manifestTemplate = grunt.file.read('manifest.template.json');
const manifest = grunt.template.process(manifestTemplate);
// Second level: process with runtime data
const finalManifest = grunt.template.process(manifest, {
data: {
buildNumber: process.env.BUILD_NUMBER || '1',
commitHash: process.env.GIT_COMMIT || 'unknown'
}
});
grunt.file.write('dist/manifest.json', finalManifest);
});Template Helpers:
// Custom template helpers
grunt.template.addDelimiters('helpers', '{%', '%}');
// Create template with helper functions
const helperTemplate = `
Name: {% name.toUpperCase() %}
Files: {% files.join(', ') %}
Size: {% formatBytes(totalSize) %}
`;
const processed = grunt.template.process(helperTemplate, {
delimiters: 'helpers',
data: {
name: 'my-project',
files: ['app.js', 'styles.css'],
totalSize: 1024000,
formatBytes: function(bytes) {
return (bytes / 1024).toFixed(1) + ' KB';
}
}
});Handle template processing errors gracefully.
// Safe template processing with error handling
grunt.registerTask('safe-template', function() {
const template = '<%= missing.property %>';
try {
const result = grunt.template.process(template);
grunt.log.writeln('Result: ' + result);
} catch (e) {
grunt.fail.warn('Template processing failed: ' + e.message);
}
});
// Provide default values for missing properties
const safeTemplate = '<%= title || "Untitled Project" %>';
const result = grunt.template.process(safeTemplate, {
data: {} // title is missing, will use default
});
// Result: "Untitled Project"