diff --git a/README.md b/README.md index ed8e3b5..0bb81d1 100644 --- a/README.md +++ b/README.md @@ -62,9 +62,9 @@ Alternately, install the latest bleeding-edge version (updated daily): HackMyResume tries not to impose a specific PDF engine requirement on the user, but will instead work with whatever PDF engines you have installed. -Currently, HackMyResume's PDF generation requires either [Phantom.js][2] or -[wkhtmltopdf][3] to be installed on your system and the `phantomjs` and/or -`wkhtmltopdf` binaries to be accessible on your PATH. This is an optional +Currently, HackMyResume's PDF generation requires either [Phantom.js][2], +[wkhtmltopdf][3], or [WeasyPrint][11] to be installed on your system and the +corresponding binary to be accessible on your PATH. This is an optional requirement for users who care about PDF formats. If you don't care about PDF formats, skip this step. @@ -184,7 +184,7 @@ Assuming you've got a JSON-formatted resume handy, generating resumes in different formats and combinations is easy. Just run: ```bash -hackmyresume BUILD [-t theme]. +hackmyresume BUILD TO [-t theme]. ``` Where `` is one or more .json resume files, separated by spaces; @@ -320,7 +320,8 @@ PDF engine you have installed through the engine's command-line interface (CLI). Currently that means one or both of... - [wkhtmltopdf][3] -- [Phantom.js][3] +- [Phantom.js][2] +- [WeasyPrint][11] ..with support for other engines planned in the future. But for now, **one or both of these engines must be installed and accessible on your PATH in order to @@ -330,6 +331,7 @@ invoke either of these tools directly from your shell or terminal without error: ```bash wkhtmltopdf input.html output.pdf phantomjs script.js input.html output.pdf +weasyprint input.html output.pdf ``` Assuming you've installed one or both of these engines on your system, you can @@ -339,6 +341,7 @@ tell HackMyResume which flavor of PDF generation to use via the `--pdf` option ```bash hackmyresume BUILD resume.json TO out.all --pdf phantom hackmyresume BUILD resume.json TO out.all --pdf wkhtmltopdf +hackmyresume BUILD resume.json TO out.all --pdf weasyprint hackmyresume BUILD resume.json TO out.all --pdf none ``` @@ -488,6 +491,10 @@ The options file can contain any documented HackMyResume option, including "sectionTitles": { "employment": "Work" } + // Change wkhtmltopdf margins + "wkhtmltopdf": { + "margin-top": "20mm" + } } ``` @@ -552,6 +559,7 @@ MIT. Go crazy. See [LICENSE.md][1] for details. [8]: https://youtu.be/N9wsjroVlu8 [9]: https://api.jquery.com/jquery.extend/ [10]: https://github.com/beautify-web/js-beautify +[11]: http://weasyprint.org/ [fresh]: https://github.com/fluentdesk/FRESH [fresca]: https://github.com/fluentdesk/FRESCA [dry]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself diff --git a/dist/generators/html-pdf-cli-generator.js b/dist/generators/html-pdf-cli-generator.js index c93aea2..eb4692e 100644 --- a/dist/generators/html-pdf-cli-generator.js +++ b/dist/generators/html-pdf-cli-generator.js @@ -52,7 +52,7 @@ Definition of the HtmlPdfCLIGenerator class. } if (_.has(engines, safe_eng)) { this.errHandler = info.opts.errHandler; - engines[safe_eng].call(this, info.mk, info.outputFile, this.onError); + engines[safe_eng].call(this, info.mk, info.outputFile, info.opts, this.onError); return null; } }; @@ -86,11 +86,19 @@ Definition of the HtmlPdfCLIGenerator class. TODO: If HTML generation has run, reuse that output TODO: Local web server to ease wkhtmltopdf rendering */ - wkhtmltopdf: function(markup, fOut, on_error) { - var tempFile; + wkhtmltopdf: function(markup, fOut, opts, on_error) { + var tempFile, wkhtmltopdf_args, wkhtmltopdf_options; tempFile = fOut.replace(/\.pdf$/i, '.pdf.html'); FS.writeFileSync(tempFile, markup, 'utf8'); - SPAWN('wkhtmltopdf', [tempFile, fOut], false, on_error, this); + wkhtmltopdf_options = _.extend({ + 'margin-bottom': '10mm', + 'margin-top': '10mm' + }, opts.wkhtmltopdf); + wkhtmltopdf_options = _.flatten(_.map(wkhtmltopdf_options, function(v, k) { + return ['--' + k, v]; + })); + wkhtmltopdf_args = wkhtmltopdf_options.concat([tempFile, fOut]); + SPAWN('wkhtmltopdf', wkhtmltopdf_args, false, on_error, this); }, /** @@ -100,7 +108,7 @@ Definition of the HtmlPdfCLIGenerator class. TODO: If HTML generation has run, reuse that output TODO: Local web server to ease Phantom rendering */ - phantomjs: function(markup, fOut, on_error) { + phantomjs: function(markup, fOut, opts, on_error) { var destPath, scriptPath, sourcePath, tempFile; tempFile = fOut.replace(/\.pdf$/i, '.pdf.html'); FS.writeFileSync(tempFile, markup, 'utf8'); @@ -109,6 +117,19 @@ Definition of the HtmlPdfCLIGenerator class. sourcePath = SLASH(PATH.relative(process.cwd(), tempFile)); destPath = SLASH(PATH.relative(process.cwd(), fOut)); SPAWN('phantomjs', [scriptPath, sourcePath, destPath], false, on_error, this); + }, + + /** + Generate a PDF from HTML using WeasyPrint's CLI interface. + Spawns a child process with `weasyprint `. Weasy Print + must be installed and path-accessible. + TODO: If HTML generation has run, reuse that output + */ + weasyprint: function(markup, fOut, opts, on_error) { + var tempFile; + tempFile = fOut.replace(/\.pdf$/i, '.pdf.html'); + FS.writeFileSync(tempFile, markup, 'utf8'); + SPAWN('weasyprint', [tempFile, fOut], false, on_error, this); } }; diff --git a/dist/helpers/generic-helpers.js b/dist/helpers/generic-helpers.js index 6d65c56..a9da25e 100644 --- a/dist/helpers/generic-helpers.js +++ b/dist/helpers/generic-helpers.js @@ -589,7 +589,9 @@ Generic template helper definitions for HackMyResume / FluentCV. dateTemp = FluentDate.fmt(dateB); dateTo = dateTemp.format(fmt); } - if (dateFrom && dateTo) { + if (dateFrom === dateTo) { + return dateFrom; + } else if (dateFrom && dateTo) { return dateFrom + sep + dateTo; } else if (dateFrom || dateTo) { return dateFrom || dateTo; diff --git a/dist/verbs/build.js b/dist/verbs/build.js index 7273c62..8f0bb4f 100644 --- a/dist/verbs/build.js +++ b/dist/verbs/build.js @@ -246,6 +246,7 @@ Implementation of the 'build' verb for HackMyResume. _opts.noTips = opts.noTips; _opts.debug = opts.debug; _opts.sort = opts.sort; + _opts.wkhtmltopdf = opts.wkhtmltopdf; that = this; _opts.onTransform = function(info) { that.stat(HMEVENT.afterTransform, info); diff --git a/src/generators/html-pdf-cli-generator.coffee b/src/generators/html-pdf-cli-generator.coffee index 29884af..15a7edd 100644 --- a/src/generators/html-pdf-cli-generator.coffee +++ b/src/generators/html-pdf-cli-generator.coffee @@ -37,7 +37,7 @@ module.exports = class HtmlPdfCLIGenerator extends TemplateGenerator safe_eng = 'phantomjs' if safe_eng == 'phantom' if _.has engines, safe_eng @errHandler = info.opts.errHandler - engines[ safe_eng ].call @, info.mk, info.outputFile, @onError + engines[ safe_eng ].call @, info.mk, info.outputFile, info.opts, @onError return null # halt further processing @@ -64,11 +64,20 @@ engines = TODO: If HTML generation has run, reuse that output TODO: Local web server to ease wkhtmltopdf rendering ### - wkhtmltopdf: (markup, fOut, on_error) -> + wkhtmltopdf: (markup, fOut, opts, on_error) -> # Save the markup to a temporary file tempFile = fOut.replace /\.pdf$/i, '.pdf.html' FS.writeFileSync tempFile, markup, 'utf8' - SPAWN 'wkhtmltopdf', [ tempFile, fOut ], false, on_error, @ + + # Prepare wkhtmltopdf arguments. + wkhtmltopdf_options = _.extend( + {'margin-bottom': '10mm', 'margin-top': '10mm'}, opts.wkhtmltopdf) + wkhtmltopdf_options = _.flatten(_.map(wkhtmltopdf_options, (v, k)-> + return ['--' + k, v] + )) + wkhtmltopdf_args = wkhtmltopdf_options.concat [ tempFile, fOut ] + + SPAWN 'wkhtmltopdf', wkhtmltopdf_args , false, on_error, @ return @@ -80,7 +89,7 @@ engines = TODO: If HTML generation has run, reuse that output TODO: Local web server to ease Phantom rendering ### - phantomjs: ( markup, fOut, on_error ) -> + phantomjs: ( markup, fOut, opts, on_error ) -> # Save the markup to a temporary file tempFile = fOut.replace /\.pdf$/i, '.pdf.html' FS.writeFileSync tempFile, markup, 'utf8' @@ -90,3 +99,17 @@ engines = destPath = SLASH PATH.relative( process.cwd(), fOut) SPAWN 'phantomjs', [ scriptPath, sourcePath, destPath ], false, on_error, @ return + + ###* + Generate a PDF from HTML using WeasyPrint's CLI interface. + Spawns a child process with `weasyprint `. Weasy Print + must be installed and path-accessible. + TODO: If HTML generation has run, reuse that output + ### + weasyprint: ( markup, fOut, opts, on_error ) -> + # Save the markup to a temporary file + tempFile = fOut.replace /\.pdf$/i, '.pdf.html' + FS.writeFileSync tempFile, markup, 'utf8' + + SPAWN 'weasyprint', [tempFile, fOut], false, on_error, @ + return diff --git a/src/helpers/generic-helpers.coffee b/src/helpers/generic-helpers.coffee index 242c4fc..dddef4d 100644 --- a/src/helpers/generic-helpers.coffee +++ b/src/helpers/generic-helpers.coffee @@ -551,7 +551,10 @@ _fromTo = ( dateA, dateB, fmt, sep, fallback ) -> dateTemp = FluentDate.fmt( dateB ) dateTo = dateTemp.format( fmt ) - if dateFrom && dateTo + + if dateFrom == dateTo + return dateFrom + else if dateFrom && dateTo return dateFrom + sep + dateTo else if dateFrom || dateTo return dateFrom || dateTo diff --git a/src/verbs/build.coffee b/src/verbs/build.coffee index 01a0128..dfed1e6 100644 --- a/src/verbs/build.coffee +++ b/src/verbs/build.coffee @@ -179,6 +179,7 @@ _prep = ( src, dst, opts ) -> _opts.noTips = opts.noTips _opts.debug = opts.debug _opts.sort = opts.sort + _opts.wkhtmltopdf = opts.wkhtmltopdf that = @ # Set up callbacks for internal generators