Skip to content
This repository has been archived by the owner on Apr 20, 2018. It is now read-only.

add suport for block replacement for custom block types #337

Merged
merged 2 commits into from
Jun 23, 2014
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Blocks are expressed as:
<!-- endbuild -->
```

* **type**: either `js` or `css`
* **type**: can be `js`, `css` or a custom type with a [block replacement function](#blockreplacements) defined
* If another type, the block will be ignored. Useful for "development only" blocks that won't appear in your build
* **alternate search path**: (optional) By default the input files are relative to the treated file. Alternate search path allows one to change that
* **path**: the file path of the optimized file, the target output
Expand Down Expand Up @@ -327,7 +327,7 @@ By default `usemin` will look under `dist/html` for revved versions of `styles/m

#### assetsDirs

Type: 'Array'
Type: 'Array' <br/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two space is linebreak in markdown

Default: Single item array set to the value of the directory where the currently looked at file is.

List of directories where we should start to look for revved version of the assets referenced in the currently looked at file.
Expand All @@ -344,7 +344,7 @@ usemin: {

#### patterns

Type: 'Object'
Type: 'Object' <br/>
Default: Empty

Allows for user defined pattern to replace reference to files. For example, let's suppose that you want to replace
Expand Down Expand Up @@ -375,9 +375,36 @@ So in short:
* FIXME
* FIXME

#### blockReplacements

Type: 'Object' <br/>
Default: `{ css: function (block) { ... }, js: function (block) { ... } }`

This lets you define how blocks get their content replaced. Useful to have block types other that `css` and `js`.

* Object key matches a block type
* Value is the replacement function for that block type.
* The replacement function gets called with a single argument: a [block](#block) object.
* Must return a `String`, the "summary" line that will replace the block content.

For example, to create a `less` block you could define its replacement function like this:

```js
usemin: {
html: index.html,
options: {
blockReplacements: {
less: function (block) {
return '<link rel="stylesheet" href="' + block.dest + '" />';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

" /> => ">

}
}
}
}
```

#### revmap

Type: 'String'
Type: 'String' <br/>
Default: Empty

Indicate the location of a map file, as produced by `grunt-filerev` for example. This map file is a simple JSON file, holding an object
Expand Down
36 changes: 25 additions & 11 deletions lib/fileprocessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,22 @@ var _defaultPatterns = {
]
};

var FileProcessor = module.exports = function (patterns, finder, logcb) {
//
// Default block replacement functions, for css and js types
//
var defaultBlockReplacements = {
css: function (block) {
var media = block.media ? ' media="' + block.media + '"' : '';
return '<link rel="stylesheet" href="' + block.dest + '"' + media + '/>';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

" /> => ">

},
js: function (block) {
var defer = block.defer ? 'defer ' : '';
var async = block.async ? 'async ' : '';
return '<script ' + defer + async + 'src="' + block.dest + '"><\/script>';
}
};

var FileProcessor = module.exports = function (patterns, finder, logcb, blockReplacements) {
if (!patterns) {
throw new Error('No pattern given');
}
Expand All @@ -89,6 +104,13 @@ var FileProcessor = module.exports = function (patterns, finder, logcb) {
throw new Error('Missing parameter: finder');
}
this.finder = finder;


this.blockReplacements = _.assign({}, defaultBlockReplacements);
if (blockReplacements && _.keys(blockReplacements).length > 0) {
_.assign(this.blockReplacements, blockReplacements);
}

};

//
Expand All @@ -107,21 +129,13 @@ FileProcessor.prototype.replaceBlocks = function replaceBlocks(file) {

FileProcessor.prototype.replaceWith = function replaceWith(block) {
var result;
var dest = block.dest;
var conditionalStart = block.conditionalStart ? block.conditionalStart + '\n' + block.indent : '';
var conditionalEnd = block.conditionalEnd ? '\n' + block.indent + block.conditionalEnd : '';
if (typeof block.src === 'undefined' || block.src === null || block.src.length === 0) {
// there are no css or js files in the block, remove it completely
result = '';
} else if (block.type === 'css') {
var media = block.media ? ' media="' + block.media + '"' : '';
result = block.indent + conditionalStart + '<link rel="stylesheet" href="' + dest + '"' + media + '/>' + conditionalEnd;
} else if (block.defer) {
result = block.indent + conditionalStart + '<script defer src="' + dest + '"><\/script>' + conditionalEnd;
} else if (block.async) {
result = block.indent + conditionalStart + '<script async src="' + dest + '"><\/script>' + conditionalEnd;
} else if (block.type === 'js') {
result = block.indent + conditionalStart + '<script src="' + dest + '"><\/script>' + conditionalEnd;
} else if (_.contains(_.keys(this.blockReplacements), block.type)) {
result = block.indent + conditionalStart + this.blockReplacements[block.type](block) + conditionalEnd;
} else {
result = '';
}
Expand Down
3 changes: 2 additions & 1 deletion tasks/usemin.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ module.exports = function (grunt) {
var options = this.options({
type: this.target
});
var blockReplacements = options.blockReplacements || {};

debug('Looking at %s target', this.target);
var patterns;
Expand All @@ -129,7 +130,7 @@ module.exports = function (grunt) {
var revvedfinder = new RevvedFinder(locator);
var handler = new FileProcessor(patterns, revvedfinder, function (msg) {
grunt.log.writeln(msg);
});
}, blockReplacements);

this.files.forEach(function (fileObj) {
var files = grunt.file.expand({
Expand Down
4 changes: 4 additions & 0 deletions test/fixtures/block_with_custom_type.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!-- build:less styles/main.css -->
<link rel="stylesheet/less" href="styles/foo.less">
<link rel="stylesheet/less" href="styles/bar.less">
<!-- endbuild -->
18 changes: 18 additions & 0 deletions test/test-fileprocessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@ describe('FileProcessor', function () {
assert.equal(result, '');
});

it('should replace cutsom blocks using provided replacement function', function () {
var blockReplacements = {
less: function (block) {
return 'custom replacement for ' + block.dest;
}
};
var fp = new FileProcessor('html', {}, function () {}, blockReplacements);
var block = {
dest: 'foo.css',
type: 'less',
src: ['bar.less'],
indent: ' '
};

var result = fp.replaceWith(block);
assert.equal(result, ' custom replacement for foo.css');
});

it('should preserve defer attribute (JS)', function () {
var fp = new FileProcessor('html', {});
var block = {
Expand Down
21 changes: 21 additions & 0 deletions test/test-usemin.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,27 @@ describe('usemin', function () {
assert.ok(changed.match('<img src="images/test.2134.png">'));
});

it('should allow for custom block replacement functions', function () {
grunt.log.muted = true;
grunt.config.init();
grunt.config('usemin', {
html: 'index.html',
options: {
blockReplacements: {
less: function (block) {
return '<link rel="stylesheet" href="' + block.dest + '" />';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

" /> => ">

}
}
}
});
grunt.file.copy(path.join(__dirname, 'fixtures/block_with_custom_type.html'), 'index.html');
grunt.task.run('usemin');
grunt.task.start();

var changed = grunt.file.read('index.html');
// Check replace has performed its duty
assert.equal(changed, '<link rel="stylesheet" href="styles/main.css" />');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

" /> => ">

});
});

describe('useminPrepare', function () {
Expand Down