Grunt plugin for preprocessing HTML and JavaScript files with environment-based directives
npx @tessl/cli install tessl/npm-grunt-preprocess@5.1.0grunt-preprocess is a Grunt plugin that provides preprocessing capabilities for HTML and JavaScript files using environment-based directives. It wraps the 'preprocess' npm module to enable conditional compilation and template-like functionality in web development workflows.
npm install --save-dev grunt-preprocessLoad the task in your Gruntfile:
grunt.loadNpmTasks('grunt-preprocess');For programmatic usage (initialize with Grunt instance):
const gruntPreprocess = require('grunt-preprocess');
// Initialize the task with a Grunt instance
gruntPreprocess(grunt);CommonJS import:
const gruntPreprocess = require('grunt-preprocess');CLI usage:
grunt-preprocessConfigure the preprocess task in your Gruntfile:
module.exports = function(grunt) {
grunt.initConfig({
preprocess: {
options: {
context: {
NODE_ENV: 'production',
DEBUG: false
}
},
html: {
src: 'src/index.html',
dest: 'dist/index.html'
},
js: {
src: 'src/app.js',
dest: 'dist/app.js'
}
}
});
grunt.loadNpmTasks('grunt-preprocess');
grunt.registerTask('build', ['preprocess']);
};Input file with preprocessor directives:
<head>
<title>My App</title>
<!-- @if NODE_ENV='production' -->
<script src="analytics.js"></script>
<!-- @endif -->
<!-- @ifdef DEBUG -->
<script src="debug-tools.js"></script>
<!-- @endif -->
</head>
<body>
<h1><!-- @echo RELEASE_TAG --></h1>
<p>
<!-- @include welcome_message.txt -->
</p>
</body>The package exports a single initialization function as the main module:
/**
* Main module export - initialization function
* @param grunt - Grunt instance to register task with
* @returns void - Registers 'preprocess' multi-task with Grunt
*/
declare function gruntPreprocess(grunt: GruntInstance): void;
// Default export
export = gruntPreprocess;
// Module structure
interface ModuleExports {
/** Main export is the init function */
default: typeof gruntPreprocess;
/** No named exports - single function export */
}The main entry point that registers the 'preprocess' multi-task with Grunt.
/**
* Initialize and register the preprocess task with Grunt
* @param grunt - Grunt instance with registerMultiTask method
*/
function init(grunt: GruntInstance): void;The preprocess task accepts the following configuration options through standard Grunt task configuration:
interface PreprocessTaskConfig {
/** Task-specific options */
options?: PreprocessOptions;
/** File configuration */
src?: string;
dest?: string;
files?: { [dest: string]: string } | FileConfig[];
}
interface PreprocessOptions {
/** Additional context variables for template processing */
context?: { [key: string]: any };
/** Enable overwriting source files in-place */
inline?: boolean;
/** Directory to look for @include files and @extend directives */
srcDir?: string;
/** End-of-line character for preprocessed output */
srcEol?: string;
/** Syntax type for preprocessing */
type?: string;
}
interface FileConfig {
src: string[];
dest?: string;
expand?: boolean;
cwd?: string;
ext?: string;
}Environment and custom variables are merged for template processing:
/**
* Context merging follows this precedence (highest to lowest):
* 1. Task-level context options
* 2. Global task context options
* 3. process.env environment variables
*
* NODE_ENV defaults to 'development' if not set
*/
interface ContextMerging {
context: {
NODE_ENV: string; // Defaults to 'development'
[key: string]: any; // Custom variables
};
}Process a single source file to a destination:
preprocess: {
html: {
src: 'src/index.html',
dest: 'dist/index.html'
}
}Process multiple files using a files object:
preprocess: {
multifile: {
files: {
'dist/app.js': 'src/app.js',
'dist/styles.css': 'src/styles.css'
}
}
}Process files using glob patterns with expanded configuration:
preprocess: {
all_templates: {
src: '**/*.tmpl',
ext: '.html',
cwd: 'src',
dest: 'build',
expand: true
}
}Overwrite source files in-place (requires inline: true option):
preprocess: {
inline: {
src: ['src/**/*.js'],
options: {
inline: true,
context: {
MINIFIED: true
}
}
}
}Type: Object
Default: {NODE_ENV: 'development'}
Additional context variables for template processing beyond environment variables:
options: {
context: {
VERSION: '1.2.0',
API_URL: 'https://api.example.com',
DEBUG: true,
customFunction: function(param) {
return param + '-processed';
}
}
}Type: Boolean
Default: undefined
Required flag to enable overwriting source files. Must be explicitly set to true for safety:
options: {
inline: true // Required for in-place file modification
}Type: String
Default: Directory path of source file
Directory where @include and @extend directives should look for files:
options: {
srcDir: 'templates/' // Look for includes in templates/ directory
}Type: String
Default: Source file EOL or os.EOL
End-of-line character for preprocessed output:
options: {
srcEol: '\n' // Unix line endings
// srcEol: '\r\n' // Windows line endings
// srcEol: '\r' // Legacy Mac line endings
}Type: String
Default: File extension of source file
Override the syntax type for preprocessing when it can't be determined from file extension:
options: {
type: 'html' // Force HTML preprocessing for .tmpl files
}Additional options are passed through to the underlying 'preprocess' module:
options: {
fileNotFoundSilentFail: true // Silently ignore missing @include files
}Binary executable for running grunt-preprocess from the command line:
# Global installation and usage
npm install -g grunt-preprocess
grunt-preprocess
# NPX usage (recommended)
npx grunt-preprocess
# Direct binary usage after local install
./node_modules/.bin/grunt-preprocessThe CLI binary (bin/grunt-preprocess) is a simple wrapper that delegates to Grunt's CLI system:
/**
* CLI binary that loads and executes grunt-preprocess tasks
* Delegates to grunt.npmTasks('grunt-preprocess').cli()
*/
interface CLIBinary {
/** Executable path from package.json bin field */
executable: "bin/grunt-preprocess";
/** Requires Grunt to be available in the project */
requirement: "grunt";
}
### Preprocessing Directives
Supported directives (processed by the underlying 'preprocess' module):
#### Conditional Blocks
```html
<!-- @if NODE_ENV='production' -->
<script src="analytics.js"></script>
<!-- @endif -->
<!-- @ifdef DEBUG -->
<div class="debug-info">Debug Mode</div>
<!-- @endif -->
<!-- @ifndef PRODUCTION -->
<script src="dev-tools.js"></script>
<!-- @endif --><h1>Version <!-- @echo VERSION --></h1>
<p>Built on <!-- @echo BUILD_DATE --></p><!-- @include header.html -->
<main>Content here</main>
<!-- @include footer.html -->var config = {
// @if NODE_ENV='development'
debug: true,
// @endif
apiUrl: '/* @echo API_URL */' || 'http://localhost:3000'
};
// @ifdef ANALYTICS
trackEvent('page_view');
// @endifThe task includes error handling and logging:
preprocess: {
options: {
context: {
NODE_ENV: process.env.NODE_ENV || 'development'
}
},
build: {
files: [{
expand: true,
cwd: 'src/',
src: ['**/*.html', '**/*.js'],
dest: 'dist/'
}]
}
}preprocess: {
options: {
context: {
VERSION: pkg.version,
BUILD_DATE: new Date().toISOString(),
formatPrice: function(price) {
return '$' + price.toFixed(2);
}
}
},
templates: {
src: 'templates/*.html',
dest: 'build/',
expand: true
}
}preprocess: {
dev: {
options: {
context: {
NODE_ENV: 'development',
API_URL: 'http://localhost:3000'
}
},
src: 'src/config.js',
dest: 'build/config.dev.js'
},
prod: {
options: {
context: {
NODE_ENV: 'production',
API_URL: 'https://api.example.com'
}
},
src: 'src/config.js',
dest: 'build/config.prod.js'
}
}/**
* Grunt file configuration object
*/
interface GruntFileConfig {
src: string | string[];
dest?: string;
expand?: boolean;
cwd?: string;
ext?: string;
flatten?: boolean;
}
/**
* Context object for variable substitution
*/
interface ProcessingContext {
NODE_ENV?: string;
[variableName: string]: string | number | boolean | Function | undefined;
}
/**
* Main preprocessing options (extends options passed to 'preprocess' module)
*/
interface PreprocessingOptions {
context?: ProcessingContext;
inline?: boolean;
srcDir?: string;
srcEol?: '\n' | '\r\n' | '\r';
type?: 'html' | 'js' | 'css' | 'coffee' | string;
fileNotFoundSilentFail?: boolean;
}
/**
* Complete Grunt instance interface required by grunt-preprocess
*/
interface GruntInstance {
registerMultiTask(name: string, description: string, taskFunction: Function): void;
config: {
requires(property: string): void;
getRaw(property: string): any;
};
file: {
read(filepath: string): string;
write(filepath: string, contents: string): void;
};
template: {
process(template: string): string;
};
log: {
error(message: string): void;
errorlns(message: string): void;
};
}