diff --git a/grunt.js b/Gruntfile.js similarity index 60% rename from grunt.js rename to Gruntfile.js index 008da40..ccdf7bd 100644 --- a/grunt.js +++ b/Gruntfile.js @@ -1,12 +1,14 @@ +'use strict'; + module.exports = function(grunt) { + // Load grunt tasks automatically + require('load-grunt-tasks')(grunt); + // Project configuration. grunt.initConfig({ - test: { - files: ['test/**/*.js'] - }, - lint: { - files: ['grunt.js', 'tasks/**/*.js', 'test/**/*.js'] + nodeunit: { + all: ['test/**/_test.js'] }, watch: { files: '', @@ -25,16 +27,19 @@ module.exports = function(grunt) { boss: true, eqnull: true, node: true, - es5: true }, - globals: {} + all: [ + 'Gruntfile.js', + 'tasks/{,*/}*.js', + 'test/{,*/}*.js', + ] } }); - // Load local tasks. - grunt.loadTasks('tasks'); - // Default task. - grunt.registerTask('default', 'lint test'); + grunt.registerTask('default', [ + 'jshint', + 'nodeunit:all' + ]); }; diff --git a/README.md b/README.md index 030dc8b..b55cf47 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,20 @@ Convertion to PDF takes care of `@media print` CSS rules and preserves links to ## Getting Started -### Setting up wkhtmltopdf +### Setting up wkhtmltopdf Download and install wkhtmltopdf from the [project page][wkhtmltopdf_dl]. -Make sure `wkhtmltopdf` is accessible from your `PATH` (Try `wkhtmltopdf -V` in your Terminal). -I'm on Mas OS X, so I created the following symlink to my `/usr/local/bin/` folder: +Make sure `wkhtmltopdf` is accessible from your `PATH` (Try `wkhtmltopdf -V` in your Terminal). +I'm on Mac OS X, so I created the following symlink to my `/usr/local/bin/` folder: ``` ln -s /usr/local/bin/wkhtmltopdf.app/Contents/MacOS/wkhtmltopdf /usr/local/bin/wkhtmltopdf ``` +You can also install it via homebrew: `$ brew install wkhtmltopdf`. + + ### Use it with grunt Install this grunt plugin next to your project's [grunt.js gruntfile][getting_started] with: `npm install grunt-wkhtmltopdf` @@ -26,11 +29,6 @@ Then add this line to your project's `grunt.js` gruntfile: grunt.loadNpmTasks('grunt-wkhtmltopdf'); ``` -[wkhtmltopdf]: http://code.google.com/p/wkhtmltopdf/ -[wkhtmltopdf_dl]: http://code.google.com/p/wkhtmltopdf/downloads/list -[grunt]: https://github.com/cowboy/grunt -[getting_started]: https://github.com/cowboy/grunt/blob/master/docs/getting_started.md - ## Documentation Simply add task definition in your gruntfile. See the folllowing example: @@ -51,15 +49,61 @@ Simply add task definition in your gruntfile. See the folllowing example: Run `grunt wkhtmltopdf` to execute all the targets or `grunt wkhtmltopdf:targetname` to execute a specific target. Every `html` file defined by the `src` parameter will be turned into a PDF and saved to `dest` folder. +### Sending arguments to `wkhtml2pdf` + +Arguments sent via the `args` key in the task definition will be forwarded to `wkhtml2pdf` as follow : + +```javascript + //... + wkhtmltopdf: { + prod: { + src: 'path/to/some/html/file/*.html', + dest: 'pdf/output/', + args: [ + '--dpi', '96', + '--print-media-type', + '--grayscale' + ] + } + }, + //... +``` + +Defining custom arguments will override default ones: + +```javascript +// grunt-wkhtml2pdf default arguments +var args = [ + '--dpi', '96', + '--print-media-type' +] +``` + +See [wkhtml2pdf documentation][wkhtmltopdf_doc] for available options + ## 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][grunt]. ## Release History - - *v0.1.0*: First Release - - *v0.2.0*: Fixed compatibility with grunt 0.4 + - *v0.5.0*: + - Merged [#12](https://github.com/dharFr/grunt-wkhtmltopdf/pull/12) (Fix [#11](https://github.com/dharFr/grunt-wkhtmltopdf/issues/11)) : Added async support + - Merged [#9](https://github.com/dharFr/grunt-wkhtmltopdf/pull/9) : Added ability to override the arguments + - *v0.4.0*: + - Update project config files to work with Grunt 0.4 + - Update wkthmltopdf task to use Grunt 0.4 multi-task API + - Improve predictability of the destination for created PDFs - *v0.3.0*: grunt-wkhtmltopdf is now a multi-task + - *v0.2.0*: Fixed compatibility with grunt 0.4 + - *v0.1.0*: First Release ## License -Copyright (c) 2012 Olivier Audard +Copyright (c) 2012 Olivier Audard Licensed under the MIT license. + + +[wkhtmltopdf]: http://wkhtmltopdf.org/ +[wkhtmltopdf_dl]: http://wkhtmltopdf.org/downloads.html +[wkhtmltopdf_doc]: http://wkhtmltopdf.org/docs.html +[grunt]: https://github.com/gruntjs/grunt +[getting_started]: https://github.com/cowboy/grunt/blob/master/docs/getting_started.md diff --git a/package.json b/package.json index a677a37..4b0888f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "grunt-wkhtmltopdf", "description": "Grunt Task that uses wkhtmltopdf to convert HTML files to PDF", - "version": "0.3.0", + "version": "0.4.0", "homepage": "http://www.dhar.fr/grunt-wkhtmltopdf/", "author": { "name": "Olivier Audard", @@ -30,10 +30,13 @@ "test": "grunt test" }, "dependencies": { - "grunt": "~0.3.9" + "grunt": "~0.4.1" }, "devDependencies": { - "grunt": "~0.3.9" + "grunt": "~0.4.1", + "grunt-contrib-jshint": "^0.10.0", + "grunt-contrib-nodeunit": "^0.4.0", + "load-grunt-tasks": "^0.4.0" }, "keywords": [ "gruntplugin", @@ -41,4 +44,4 @@ "convert", "html" ] -} \ No newline at end of file +} diff --git a/tasks/wkhtmltopdf.js b/tasks/wkhtmltopdf.js index ee673be..375915d 100644 --- a/tasks/wkhtmltopdf.js +++ b/tasks/wkhtmltopdf.js @@ -18,33 +18,73 @@ module.exports = function(grunt) { grunt.registerMultiTask('wkhtmltopdf', 'Your task description goes here.', function() { - var htmlFiles = grunt.file.expandFiles(this.file.src), - dest = (this.file.dest && this.file.dest !== '') ? this.file.dest + '/' : ''; + // using grunt async support so we can be sure task doesn't + // end before PDF processing does: http://gruntjs.com/api/inside-tasks + var done = this.async(), + files = this.files; - grunt.log.writeln("pdf output is: " + dest); + // iterate through each file grouping + files.forEach(function(file, filesIndex) { - htmlFiles.forEach(function(srcpath) { - var dir = dest + srcpath.replace(/.*\/([^\/]+)\/[^\/]+\.html/, '$1'); + var pathlib = require('path'); + // calculate the destination directory and ensure it exists, since + // wkhtmltopdf won't create the PDF if the destination directory doesn't + // exist + var destPath = file.dest; + if (grunt.file.isFile(file.dest)) { + destPath = pathlib.dirname(file.dest); + } + grunt.file.mkdir(destPath); - // Create dest folder as wkhtmltopdf won't generate output if it doesn't exist - grunt.file.mkdir(dir); - var destpath = dir + '/' + - srcpath.replace(/.*\/([^\/]+)\.html/, '$1.pdf'); + file.src.forEach(function(src, srcIndex) { - // Launch PhantomJS. - helper.convert({ - code: 90, - args: [ - '--dpi', '96', // workarround to wkhtmltopdf letter-spacing bug (see http://code.google.com/p/wkhtmltopdf/issues/detail?id=72) - '--print-media-type', // Use @print media type - srcpath, - destpath - ], - done: function(err) { - if (err) { - grunt.log('>>>', err); - } + var dest = file.dest; + // wkhtmltopdf seems to require that the destination be a file + // location, not a directory, so if the given destination is a + // directory then append the name of the source file but with the + // extension changed to .pdf + if (grunt.file.isDir(dest)) { + var srcFileName = pathlib.basename(src); + var srcFileExtension = pathlib.extname(src); + var destFileName = srcFileName.replace( + new RegExp(srcFileExtension + "$"), // match only the end of the string + ".pdf" + ); + dest = pathlib.join(destPath + destFileName); } + + grunt.log.writeln( + "Converting " + src + " -> " + dest + ); + + // default args + var args = [ + '--dpi', '96', // workarround to wkhtmltopdf letter-spacing bug (see http://code.google.com/p/wkhtmltopdf/issues/detail?id=72) + '--print-media-type' // Use @print media type + ]; + + // overrides the args + if (file.args) { + args = file.args; + } + + // adds the src and dest + args = args.concat([src, dest]); + + // Launch wkhtmltopdf. + helper.convert({ + code: 90, + args: args, + done: function(err) { + if (err) { + grunt.log('>>>', err); + } + // if this is the last src of the last file, we are done. + if((filesIndex+1 >= files.length) && (srcIndex+1 >= file.src.length)) { + done(); + } + } + }); }); }); });