grunt-usemin
Advanced tools
Comparing version 0.1.2 to 0.1.5
@@ -7,11 +7,14 @@ 'use strict'; | ||
// It is given: | ||
// - the filepath of the file to consider | ||
// - the content of the file to consider | ||
// - An object representing the file, with the following keys: | ||
// name: name of the file (optional) | ||
// dir: directory location of the file to examine | ||
// content: the content of the file to look at | ||
// - a file replacement locator | ||
// - a destination directory (optional) | ||
// - an optional log callback that will be called as soon as there's something to log | ||
// | ||
var CSSProcessor = module.exports = function (filepath, content, revvedfinder, logcb) { | ||
this.content = content; | ||
this.filepath = filepath; | ||
this.linefeed = /\r\n/g.test(content) ? '\r\n' : '\n'; | ||
var CSSProcessor = module.exports = function (file, revvedfinder, logcb) { | ||
this.content = file.content; | ||
this.filepath = file.dir; | ||
this.linefeed = /\r\n/g.test(this.content) ? '\r\n' : '\n'; | ||
this.revvedfinder = revvedfinder; | ||
@@ -18,0 +21,0 @@ this.logcb = logcb || function () {}; |
@@ -94,2 +94,3 @@ 'use strict'; | ||
last.requirejs.name = path.basename(main[1]); | ||
last.requirejs.src = last.src.pop(); | ||
last.src.push(last.dest); | ||
@@ -108,13 +109,16 @@ } | ||
// It is given: | ||
// - the filepath of the file to consider | ||
// - the content of the file to consider | ||
// - An object representing the file, with the following keys: | ||
// name: name of the file (optional) | ||
// dir: directory location of the file to examine | ||
// content: the content of the file to look at | ||
// - a file replacement locator | ||
// - an optional log callback that will be called as soon as there's something to log | ||
// | ||
var HTMLProcessor = module.exports = function (filepath, content, revvedfinder, logcb) { | ||
this.filepath = filepath; | ||
this.relativePath = path.relative(process.cwd(), path.dirname(filepath)); | ||
this.content = content; | ||
var HTMLProcessor = module.exports = function (file, revvedfinder, logcb) { | ||
// FIXME: Check consistency of the file object | ||
this.file = file; | ||
this.relativePath = path.relative(process.cwd(), file.dir); | ||
this.content = file.content; | ||
this.revvedfinder = revvedfinder; | ||
this.linefeed = /\r\n/g.test(content) ? '\r\n' : '\n'; | ||
this.linefeed = /\r\n/g.test(this.content) ? '\r\n' : '\n'; | ||
this.blocks = getBlocks(this.relativePath, this.content); | ||
@@ -136,2 +140,3 @@ this.logcb = logcb || function () {}; | ||
var result; | ||
var backslash = /\\/g; | ||
@@ -147,6 +152,16 @@ // Determine the relative path from the destination to the source | ||
// fix windows style paths. Dirty but works. | ||
dest = dest.replace('\\', '/'); | ||
dest = dest.replace(backslash, '/'); | ||
if (block.type === 'css') { | ||
result = block.indent + '<link rel="stylesheet" href="' + dest + '">'; | ||
} else if (block.requirejs !== undefined) { | ||
var dataMain = path.relative(this.relativePath, block.requirejs.dest); | ||
dataMain = dataMain.replace(backslash, '/'); | ||
var requireSrc = path.relative(this.relativePath, block.requirejs.src); | ||
requireSrc = requireSrc.replace(backslash, '/'); | ||
if (block.startFromRoot) { | ||
dataMain = '/' + dataMain; | ||
requireSrc = '/' + requireSrc; | ||
} | ||
result = block.indent + '<script data-main="' + dataMain + '" src="' + requireSrc + '"><\/script>'; | ||
} else if (block.type === 'js') { | ||
@@ -184,3 +199,3 @@ result = block.indent + '<script src="' + dest + '"><\/script>'; | ||
/*jshint regexp:false */ | ||
[/<script.+src=['"]([^"']+)["'][\/>]?><[\\]?\/script>/gm, | ||
[/<script.+src=['"]([^"']+)["']/gm, | ||
'Update the HTML to reference our concat/min/revved script files' | ||
@@ -194,2 +209,6 @@ ], | ||
], | ||
[/data-main\s*=['"]([^"']+)['"]/gm, | ||
'Update the HTML with data-main tags', | ||
function(m) { return m.match(/\.js$/) ? m : m + ".js"; } | ||
], | ||
[/data-[A-Za-z0-9]*=['"]([^"']+)["']/gm, | ||
@@ -208,12 +227,16 @@ 'Update the HTML with the data tags' | ||
]; | ||
var identity = function (m) { return m; }; | ||
// Replace reference to script with the actual name of the revved script | ||
regexps.forEach(function (rxl) { | ||
var filter = rxl[2] || identity; | ||
self.log(rxl[1]); | ||
content = content.replace(rxl[0], function (match, src) { | ||
// Consider reference from site root | ||
var file = self.revvedfinder.find(src, path.dirname(self.filepath)); | ||
var srcfile = filter(src); | ||
var file = self.revvedfinder.find(srcfile, self.file.dir); | ||
var res = match.replace(src, file); | ||
if (src !== file) { | ||
if (srcfile !== file) { | ||
self.log(match + ' changed to ' + res); | ||
@@ -220,0 +243,0 @@ } |
@@ -7,7 +7,16 @@ 'use strict'; | ||
// | ||
// +base_dir+ : the base repository which will be the root for our search | ||
// +expandfn+ : a function that will return a list of file matching a given pattern (for example grunt.file.expand) | ||
// +dirs+: restrict the search to these subdirectories | ||
// | ||
var RevvedFinder = module.exports = function (expandfn) { | ||
var RevvedFinder = module.exports = function (expandfn, dirs) { | ||
this.expandfn = expandfn; | ||
this.dirs = dirs; | ||
if (!dirs || dirs.length === 0) { | ||
this.dirs_string = ''; | ||
} else if (dirs.length == 1) { | ||
this.dirs_string = dirs[0] + '/'; | ||
} else { | ||
this.dirs_string = '{' + dirs.join(',') + '}/'; | ||
} | ||
}; | ||
@@ -62,6 +71,6 @@ | ||
// a images/misc/4567.test.png for example) | ||
var filepaths = this.expandfn('**/*' + basename); | ||
var re = new RegExp('\\d+\\.' + basename + '$'); | ||
var filepaths = this.expandfn(this.dirs_string + '**/*' + basename); | ||
var re = new RegExp('[0-9a-fA-F]+\\.' + basename + '$'); | ||
var filepath = filepaths.filter(function (f) { | ||
return f.match(re) && (normalizedDirname === path.dirname(f)); | ||
return f.match(re) && (path.dirname(f).match(normalizedDirname)); | ||
})[0]; | ||
@@ -68,0 +77,0 @@ |
{ | ||
"name": "grunt-usemin", | ||
"version": "0.1.2", | ||
"version": "0.1.5", | ||
"description": "Grunt task replaces references to non-optimized scripts or stylesheets into a set of HTML files (or any templates/views).", | ||
"keywords": [ | ||
"gruntplugin", | ||
"grunt", | ||
"usemin", | ||
"yeoman", | ||
"html" | ||
"gruntplugin", | ||
"grunt", | ||
"usemin", | ||
"yeoman", | ||
"html" | ||
], | ||
@@ -17,21 +17,21 @@ "homepage": "https://github.com/yeoman/grunt-usemin", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/yeoman/grunt-usemin.git" | ||
"type": "git", | ||
"url": "git://github.com/yeoman/grunt-usemin.git" | ||
}, | ||
"scripts": { | ||
"test": "node node_modules/mocha/bin/mocha test/test-*.js" | ||
"test": "node node_modules/mocha/bin/mocha test/test-*.js" | ||
}, | ||
"devDependencies": { | ||
"grunt": "~0.4.0", | ||
"mocha": "~1.7.4", | ||
"mkdirp": "~0.3.1", | ||
"rimraf": "~2.0.1", | ||
"grunt-contrib-jshint": "~0.1.1" | ||
"grunt": "~0.4.0", | ||
"mocha": "~1.7.4", | ||
"mkdirp": "~0.3.1", | ||
"rimraf": "~2.0.1", | ||
"grunt-contrib-jshint": "~0.1.1" | ||
}, | ||
"engines": { | ||
"node": ">=0.8.0" | ||
"node": ">=0.8.0" | ||
}, | ||
"licenses": { | ||
"type": "BSD" | ||
"type": "BSD" | ||
} | ||
} |
@@ -20,6 +20,6 @@ # grunt-usemin [![Build Status](https://secure.travis-ci.org/yeoman/grunt-usemin.png?branch=master)](http://travis-ci.org/yeoman/grunt-usemin) | ||
- **useminPrepare**: detects special construction (blocks) in the HTML files and update the `grunt` config to run `concat`/`min`/`css`/`requirejs` on the files referenced in the block. It does not changes the HTML files it is working on. | ||
- **useminPrepare**: detects special construction (blocks) in the HTML files and update the `grunt` config to run `concat`/`uglify`/`cssmin`/`requirejs` on the files referenced in the block. It does not changes the HTML files it is working on. | ||
- **usemin**: in the HTML and CSS files it treats, it replaces the blocks by a reference to a single file, as well as all references to images, scripts, CSS files, by their minified/revved/.. version if it is found on the disk. As such this target rewrites the HTML and CSS files it is working on. | ||
Usually, `useminPrepare` is launched first, then the `concat`, `min`, `css` and `requirejs` tasks are launched (they will created the minified/revved version of the referenced files), and then, in the end `usemin` is launched. | ||
Usually, `useminPrepare` is launched first, then the `concat`, `uglify`, `cssmin` and `requirejs` tasks are launched (they will created the minified/revved version of the referenced files), and then, in the end `usemin` is launched. | ||
@@ -52,3 +52,3 @@ ## The useminPrepare task | ||
Internally, the task parses your HTML markup to find each of these blocks, and initializes for you the corresponding Grunt config for the concat / min tasks when `type=js`, the concat / css tasks when `type=css`. | ||
Internally, the task parses your HTML markup to find each of these blocks, and initializes for you the corresponding Grunt config for the concat / uglify tasks when `type=js`, the concat / cssmin tasks when `type=css`. | ||
@@ -63,3 +63,3 @@ The task also handles use of RequireJS, for the scenario where you specify the main entry point for your application using the "data-main" attribute as follows: | ||
One doesn't need to specify a concat/min/css or RequireJS configuration anymore. | ||
One doesn't need to specify a concat/uglify/cssmin or RequireJS configuration anymore. | ||
@@ -74,3 +74,28 @@ It is using only one target: `html`, with a list of the concerned files. For example, in your `Gruntfile.js`: | ||
### Options | ||
#### uglify | ||
Type: 'string' | ||
Default: 'uglify' | ||
Name of the tool used to uglify the JavaScript. | ||
#### cssmin | ||
Type: 'string' | ||
Default: 'cssmin' | ||
Name of the tool used to minify the CSS. | ||
### dirs | ||
Type: 'array of strings' | ||
Default: nil | ||
Used to limit the directories that will be looked for revved files when replacing reference. By default all subdirectories are looked at. | ||
### dest | ||
Type: 'string' | ||
Default: nil | ||
Base directory where the transformed files should be output. | ||
## The usemin task | ||
@@ -83,3 +108,6 @@ | ||
html: ['**/*.html'], | ||
css: ['**/*.css'] | ||
css: ['**/*.css'], | ||
options: { | ||
dirs: ['temp', 'dist'] | ||
} | ||
} | ||
@@ -86,0 +114,0 @@ ``` |
'use strict'; | ||
var util = require('util'); | ||
var path = require('path'); | ||
@@ -51,4 +52,4 @@ var inspect = function (obj) { | ||
// Internally, the task parses your HTML markup to find each of these blocks, and | ||
// initializes for you the corresponding Grunt config for the concat / min tasks | ||
// when `type=js`, the concat / css tasks when `type=css`. | ||
// initializes for you the corresponding Grunt config for the concat / uglify tasks | ||
// when `type=js`, the concat / cssmin tasks when `type=css`. | ||
// | ||
@@ -63,3 +64,3 @@ // The task also handles use of RequireJS, for the scenario where you specify | ||
// | ||
// One doesn't need to specify a concat/min/css or requirejs configuration anymore. | ||
// One doesn't need to specify a concat/uglify/cssmin or requirejs configuration anymore. | ||
// | ||
@@ -82,6 +83,8 @@ // Inspired by previous work in https://gist.github.com/3024891 | ||
var data = this.data; | ||
var files = grunt.file.expand(data); | ||
var options = this.options(); | ||
var files = grunt.file.expand({filter: 'isFile'}, data); | ||
files.map(grunt.file.read).forEach(function (content, i) { | ||
var filepath = files[i]; | ||
var filedir = options.basedir || path.dirname(filepath); | ||
@@ -96,6 +99,6 @@ grunt.log.subhead('usemin:' + name + ' - ' + filepath); | ||
// Our revved version locator | ||
var revvedfinder = new RevvedFinder(grunt.file.expand); | ||
var revvedfinder = new RevvedFinder(function (p) { return grunt.file.expand({filter: 'isFile'},p);}, options.dirs); | ||
// ext-specific directives handling and replacement of blocks | ||
var proc = new processors[name](filepath, content, revvedfinder, function (msg) { | ||
var proc = new processors[name]({dir: filedir, content: content}, revvedfinder, function (msg) { | ||
grunt.log.writeln(msg); | ||
@@ -111,9 +114,13 @@ }); | ||
grunt.registerMultiTask('useminPrepare', 'Using HTML markup as the primary source of information', function () { | ||
var options = this.options(); | ||
// collect files | ||
var files = grunt.file.expand({filter: 'isFile'}, this.data); | ||
var uglifyName = options.uglify || 'uglify'; | ||
var cssminName = options.cssmin || 'cssmin'; | ||
var dest = options.dest; | ||
// concat / min / css / requirejs config | ||
// concat / uglify / cssmin / requirejs config | ||
var concat = grunt.config('concat') || {}; | ||
var min = grunt.config('min') || {}; | ||
var css = grunt.config('css') || {}; | ||
var uglify = grunt.config(uglifyName) || {}; | ||
var cssmin = grunt.config(cssminName) || {}; | ||
var requirejs = grunt.config('requirejs') || {}; | ||
@@ -133,4 +140,4 @@ | ||
files.forEach(function (file) { | ||
var revvedfinder = new RevvedFinder(grunt.file.expand); | ||
var proc = new HTMLProcessor(file.path, file.body, revvedfinder, function (msg) { | ||
var revvedfinder = new RevvedFinder(function (p) { return grunt.file.expand({filter: 'isFile'},p); } ); | ||
var proc = new HTMLProcessor({dir: path.dirname(file.path), content: file.body}, revvedfinder, function (msg) { | ||
grunt.log.writeln(msg); | ||
@@ -145,4 +152,11 @@ }); | ||
var outputDestination = function (obj, dst, input) { | ||
if (dest) { | ||
dst = path.join(dest, dst); | ||
} | ||
obj[dst] = input; | ||
}; | ||
// update concat config for this block | ||
concat[block.dest] = block.src; | ||
outputDestination(concat, block.dest, block.src); | ||
grunt.config('concat', concat); | ||
@@ -152,19 +166,48 @@ | ||
// updated it on data-main attribute | ||
if (block.requirejs) { | ||
requirejs.out = requirejs.out || block.requirejs.dest; | ||
requirejs.baseUrl = requirejs.baseUrl || block.requirejs.baseUrl; | ||
requirejs.name = requirejs.name || block.requirejs.name; | ||
var hasTasks; | ||
for (var i in requirejs) { | ||
if (requirejs.hasOwnProperty(i)) { | ||
hasTasks = true; | ||
var task = requirejs[i]; | ||
var options = task.options; | ||
if (options) { | ||
options.name = options.name || block.requirejs.name; | ||
options.out = options.out || block.requirejs.dest; | ||
options.baseUrl = options.baseUrl || block.requirejs.baseUrl; | ||
} else { | ||
task.options = { | ||
name: block.requirejs.name, | ||
out: block.requirejs.dest, | ||
baseUrl: block.requirejs.baseUrl | ||
}; | ||
} | ||
} | ||
} | ||
if (!hasTasks) { | ||
requirejs.default = { | ||
options: { | ||
name: block.requirejs.name, | ||
out: block.requirejs.dest, | ||
baseUrl: block.requirejs.baseUrl | ||
} | ||
}; | ||
} | ||
grunt.config('requirejs', requirejs); | ||
} | ||
// min config, only for js type block | ||
// uglify config, only for js type block | ||
if (block.type === 'js') { | ||
min[block.dest] = block.dest; | ||
grunt.config('min', min); | ||
// TODO: we should differentiate whether or not we're | ||
// using concat before ... Option ? | ||
outputDestination(uglify, block.dest, block.dest); | ||
grunt.config(uglifyName, uglify); | ||
} | ||
// css config, only for css type block | ||
// cssmin config, only for cssmin type block | ||
if (block.type === 'css') { | ||
css[block.dest] = block.dest; | ||
grunt.config('css', css); | ||
outputDestination(cssmin, block.dest, block.src); | ||
grunt.config(cssminName, cssmin); | ||
} | ||
@@ -176,8 +219,8 @@ }); | ||
grunt.log.subhead('Configuration is now:') | ||
.subhead(' css:') | ||
.writeln(' ' + inspect(css)) | ||
.subhead(' cssmin:') | ||
.writeln(' ' + inspect(cssmin)) | ||
.subhead(' concat:') | ||
.writeln(' ' + inspect(concat)) | ||
.subhead(' min:') | ||
.writeln(' ' + inspect(min)) | ||
.subhead(' uglify:') | ||
.writeln(' ' + inspect(uglify)) | ||
.subhead(' requirejs:') | ||
@@ -184,0 +227,0 @@ .writeln(' ' + inspect(requirejs)); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
26672
567
115