grunt-processhtml
Process html files at build time to modify them depending on the release environment
Looking for the stand-alone version?
Use node-htmlprocessor
Getting Started
This plugin requires Grunt ^1.0.1
If you haven't used Grunt before, be sure to check out the Getting Started guide, as it explains how to create a Gruntfile as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:
npm install grunt-processhtml --save-dev
Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:
grunt.loadNpmTasks('grunt-processhtml');
The "processhtml" task
Process html
files with special comments:
...
type
This is required.
Types: js
, css
, remove
, template
, include
or any html attribute if written like this: [href]
, [src]
, etc.
target
This is optional.
Is the target name of your grunt task, for example: dist
. Is supported for all types, so you can always specify the target if needed.
You can pass multiple comma-separated targets, e.g. <!-- build:remove:dist,dev,prod -->
and block will be parsed for each.
inline
This modifier can be used with js
and css
types.
If used, the styles or scripts will be included in the output html file.
value
Required for types: js
, css
, include
and [attr]
.
Optional for types: remove
, template
, js
and css
types with inline
modifier.
Could be a file name: script.min.js
or a path if an attribute like [src]
is specified to keep the original file name intact but replace its path.
Simple examples
build:js[:targets] [inline] <value>
Replace many script tags into one.
[:targets]
Optional build targets.
inline
Optional modifier.
<value>
Required value: A file path.
<script src="my/lib/path/lib.js"></script>
<script src="my/deep/development/path/script.js"></script>
<script src="app.min.js"></script>
You can embed your javascript:
<script src="my/lib/path/lib.js"></script>
<script src="my/deep/development/path/script.js"></script>
<script>
</script>
or
<script src="my/lib/path/lib.js"></script>
<script src="my/deep/development/path/script.js"></script>
<script>
</script>
build:css[:targets] [inline] <value>
Replace many stylesheet link tags into one.
[:targets]
Optional build targets.
inline
Optional modifier.
<value>
Required value: A file path.
<link rel="stylesheet" href="path/to/normalize.css">
<link rel="stylesheet" href="path/to/main.css">
<link rel="stylesheet" href="style.min.css">
You can embed your styles like with js
type above:
<link rel="stylesheet" href="path/to/normalize.css">
<link rel="stylesheet" href="path/to/main.css">
<style>
</style>
or
<link rel="stylesheet" href="path/to/normalize.css">
<link rel="stylesheet" href="path/to/main.css">
<style>
</style>
build:<[attr]>[:targets] <value>
Change the value of an attribute. In most cases using [src]
and [href]
will be enough but it works with any html attribute.
<[attr]>
Required html attribute, i.e. [src]
, [href]
.
[:targets]
Optional build targets.
<value>
Required value: A path, a file path or any string value
<script src="my/lib/path/lib.js"></script>
<script src="my/deep/development/path/script.js"></script>
<script src="js/lib.js"></script>
<script src="js/script.js"></script>
<link rel="apple-touch-icon-precomposed" href="skins/demo/img/icon.png">
<link rel="apple-touch-icon-precomposed" href="skins/demo/img/icon-72x72.png" sizes="72x72">
<link rel="apple-touch-icon-precomposed" href="img/icon.png">
<link rel="apple-touch-icon-precomposed" href="img/icon-72x72.png" sizes="72x72">
<html class="debug_mode">
<html class="production">
build:include[:targets] <value>
Include an external file.
[:targets]
Optional build targets.
<value>
Required value: A file path.
This will be replaced by the content of header.html
This will be replaced by the content of dev/content.html
This will be replaced by the content of dist/content.html
build:template[:targets]
Process a template block with a data object inside options.data.
[:targets]
Optional build targets.
build:remove[:targets]
Remove a block.
[:targets]
Optional build targets
<p>This will be removed when any processhtml target is done</p>
<p>But this one only when doing processhtml:dist target</p>
Overview
In your project's Gruntfile, add a section named processhtml
to the data object passed into grunt.initConfig()
.
grunt.initConfig({
processhtml: {
options: {
},
your_target: {
},
},
})
Options
options.process
Type: Boolean
Default value: false
Process the entire html
file through grunt.template.process
, a default object with the build target will be passed to the
template in the form of {environment: target}
where environment will be the build target of the grunt task.
Important note: The process
option is not needed if you don't want to process the entire html file. See the example
below to see that you can have templates blocks to be processed.
If you do want to process the whole file as a template, it will be compiled after compiling the inside template blocks
if any.
options.environment
Type: Object
Default value: target
The environemnt variable will be available to use in the comments, it defaults to the task target.
options.data
Type: Object
Default value: {}
An object data
that is passed to the html
file used to compile all template blocks and the entire file if process
is true.
options.templateSettings
Type: Object
Default value: null
(Will use default lodash template delimiters <%
and %>
)
Define the templateSettings
option with lodash templateSettings options to customize the
template syntax.
templateSettings: {
interpolate: /{{([\s\S]+?)}}/g
}
options.includeBase
Type: String
Default value: null
(Will use the path of the including file)
Specify an optional path to look for include files. ie, app/assets/includes/
Type: String
Default value: build
Specify the word used to indicate the special begin/end comments. This is useful if you want to use this plugin
in conjunction with other plugins that use a similar, conflicting build:<type>
comment
(such as grunt-usemin).
With options.commentMarker
set to process
, a typical comment would look like:
...
options.strip
Type: Boolean
Default value: null
Specifying true
will strip comments which do not match the current target:
strip: true
options.recursive
Type: Boolean
Default value: false
Recursively process files that are being included using build:include
.
recursive: true
options.customBlockTypes
Type: Array
Default value: []
Define an array of .js
files that define custom block types.
customBlockTypes: ['custom-blocktype.js']
A custom block type example:
custom-blocktype.js
'use strict';
module.exports = function (processor) {
processor.registerBlockType('customBlock', function (content, block, blockLine, blockContent) {
var title = '<h1>' + block.asset + '</h1>';
var result = content.replace(blockLine, title);
return result;
});
};
file.html
<p>This will be replaced with the result of the custom block above</p>
The result will be
<h1>myValue</h1>
Usage Examples
Default Options
Set the task in your grunt file which is going to process the index.html
file and save the output to
dest/index.html
grunt.initConfig({
processhtml: {
options: {
data: {
message: 'Hello world!'
}
},
dist: {
files: {
'dest/index.html': ['index.html']
}
}
}
});
What will be processed?
Following the previous task configuration, the index.html
could look like this:
<!doctype html>
<title>title</title>
<link rel="apple-touch-icon-precomposed" href="my/theme/img/apple-touch-icon-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="my/theme/img/apple-touch-icon-72x72-precomposed.png" sizes="72x72">
<link rel="stylesheet" href="normalize.css">
<link rel="stylesheet" href="main.css">
<script src="js/libs/require.js" data-main="js/config.js"></script>
This will be replaced by the content of header.html
<p>This is the html file without being processed</p>
After processing this file, the output will be:
<!doctype html>
<title>title</title>
<link rel="apple-touch-icon-precomposed" href="img/apple-touch-icon-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="img/apple-touch-icon-72x72-precomposed.png" sizes="72x72">
<link rel="stylesheet" href="style.min.css">
<script src="app.min.js"></script>
<h1>Content from header.html</h1>
<p>Hello world!</p>
Advanced example
In this example there are multiple targets where we can process the html file depending on which target is being run.
grunt.initConfig({
processhtml: {
dev: {
options: {
data: {
message: 'This is development environment'
}
},
files: {
'dev/index.html': ['index.html']
}
},
dist: {
options: {
process: true,
data: {
title: 'My app',
message: 'This is production distribution'
}
},
files: {
'dest/index.html': ['index.html']
}
},
custom: {
options: {
templateSettings: {
interpolate: /{{([\s\S]+?)}}/g
},
data: {
message: 'This has custom template delimiters'
}
},
files: {
'custom/custom.html': ['custom.html']
}
}
}
});
The index.html
to be processed (the custom.html
is below):
<!doctype html>
<title><%= title %></title>
<link rel="stylesheet" href="normalize.css">
<link rel="stylesheet" href="main.css">
<p>This is the html file without being processed</p>
<script src="js/libs/require.js" data-main="js/config.js"></script>
The custom.html
to be processed:
<!doctype html>
<html>
<head>
<title>Custom template delimiters example</title>
</head>
<body>
</body>
</html>
Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using Grunt.
Release History
- 0.4.1 node-htmlprocessor@0.2.4
- 0.4.0 Update Grunt to 1.0
- 0.3.13 node-htmlprocessor@0.2.3 and clone data object (#85)
- 0.3.12 Update node-htmlprocessor to version 0.2.2 (escape regex from remove)
- 0.3.11 get ready for grunt v1.0.0
- 0.3.10 Update node-htmlprocessor to version 0.2.1
- 0.3.9 Update node-htmlprocessor to version 0.2.0
- 0.3.8 Fix #74
- 0.3.7 Update node-htmlprocessor dependency with added
inline
modifier - 0.3.6 Update node-htmlprocessor version and add specific test for templates
- 0.3.5 Fixes issue when passing data to a
template
- 0.3.4 Fixes issue when passing a path te replace an
[attr]
- 0.3.3 Add node-htmlprocessor as a dependency
- 0.3.2 Fix/feature #39
- 0.3.1 Fix #35
- 0.3.0 Allow creating custom block types.
- 0.2.9 Added
recursive
option - 0.2.8 Changed
include
to not use replace()
- 0.2.7 Added
commentMarker
option - 0.2.6 Fix #14 and added grunt-release
- 0.2.5 Create first tag using grunt-release
- 0.2.3 Fix #8
- 0.2.2 Small code refactor
- 0.2.1 Added
templateSettings
option tu customize template delimiters - 0.2.0 Added the
build:include
feature to include any external file - 0.1.1 Lint js files inside tasks/lib/
- 0.1.0 Initial release