diff --git a/README.md b/README.md index 4f8a4e3..8e8595c 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ In `Mailer.init`, you're able to provide a key-value object with *template objec teamMembers: -> @team.users.map (user) -> Meteor.users.findOne(user) - # For previewing the email in your browser. Behaves like an ordinary Iron Router route. + # For previewing the email in your browser. route: path: '/activity/:user' data: -> @@ -234,16 +234,22 @@ The built in helpers are: baseUrl: (path) -> Utils.joinUrl(Mailer.settings.baseUrl, path) -# `emailUrlFor` takes an Iron Router route (with optional params) and +# `emailUrlFor` takes an Iron Router or Flow Router route (with optional params) and # creates an absolute URL. # # {{ emailUrlFor 'myRoute' param='foo' }} => http://root-domain.com/my-route/foo -emailUrlFor: (route, params) -> - if Router - Utils.joinUrl Mailer.settings.baseUrl, Router.path.call(Router, route, params.hash) - +emailUrlFor: (routeName, params) -> + # if Iron Router + if Router? + Utils.joinUrl Mailer.settings.baseUrl, Router.path.call(Router, routeName, params.hash) + + # if Flow Router + if FlowRouter? + baseUrl = Utils.joinUrl Mailer.settings.baseUrl, FlowRouter.path.call(FlowRouter, routeName, params.hash) ``` +Please note that for Flow Router you need to have your routes defined in a place where the server can see them, in order for the `emailUrlFor` helper to work. + #### The preview line The *preview line* is the first text content of an email, usually visible in many email clients. That can be used to convey more info beyond the `subject` prop. It's possible to have your preview content in your parent layout but still provide the data from a child template. @@ -362,9 +368,9 @@ Consult the `html-to-text` [documentation](https://www.npmjs.com/package/html-to It's also possible to *send* emails to yourself or others for review in a real mail client. -Noticed the `route` property on the template? It uses Iron Router's server side routes under the hood. +Noticed the `route` property on the template? It uses `meteorhacks:picker` server side routes under the hood. -The `route` property expects a `path` property (feel free to use any of Iron Router's fanciness in here) and an optional `data` function providing the data context (an object). The function has access to the same scope as Iron Router's `action` hook, which means you can get a hold of parameters and the whole shebang. +The `route` property expects a `path` property and an optional `data` function providing the data context (an object). The function has access to the parameters of the route. **Three routes** will be added: @@ -375,7 +381,7 @@ The `route` property expects a `path` property (feel free to use any of Iron Rou ``` The `/emails` root prefix is configurable in `config` in the `routePrefix` key. -The Iron Router *route names* will be on the format +The *route names* will be on the format ``` [preview|send]Name @@ -464,6 +470,7 @@ Why not try [`meteor-logger`](https://github.com/lookback/meteor-logger)? :) ## Version history +- `0.7.0` - Replaced Iron Router dependency with `meteorhacks:picker`, which means you can now use this package with Flow Router as well. - `0.6.2` - Support passing options to `html-to-text` module in `Mailer.config()`. - `0.6.1`- Fix critical runtime crash when sending emails. - `0.6.0` - Automatically create and include plain text email version from your HTML templates, using [`html-to-text`](http://npmjs.com/package/html-to-text). diff --git a/emails.coffee b/emails.coffee index c1d9462..4674b5b 100644 --- a/emails.coffee +++ b/emails.coffee @@ -57,9 +57,15 @@ Helpers = # creates an absolute URL. # # {{ emailUrlFor 'myRoute' param='foo' }} => http://root-domain.com/my-route/foo - emailUrlFor: (route, params) -> - if Router - Utils.joinUrl Mailer.settings.baseUrl, Router.path.call(Router, route, params.hash) + emailUrlFor: (routeName, params) -> + # if Iron Router + if Router? + Utils.joinUrl Mailer.settings.baseUrl, Router.path.call(Router, routeName, params.hash) + + # if Flow Router + if FlowRouter? + baseUrl = Utils.joinUrl Mailer.settings.baseUrl, FlowRouter.path.call(FlowRouter, routeName, params.hash) + # # The mailer # @@ -258,18 +264,18 @@ MailerClass = (options) -> # This function adds the `preview` route from a `template` object. # It will apply the returned data from a `data` function on the # provided `route` prop from the template. - previewAction = (opts) -> + previewAction = (opts, template, params) -> check opts, type: Match.OneOf('html', 'text') - return (template) -> + return (template, params) -> try - data = template.route.data and template.route.data.apply(this, arguments) + data = template.route.data and template.route.data.call(this, params) catch ex msg = 'Exception in '+template.name+' data function: '+ex.message Utils.Logger.error msg, TAG - @response.writeHead 500 - return @response.end msg + @writeHead 500 + return @end msg # Compile, since we wanna refresh markup and CSS inlining. compile template @@ -285,21 +291,21 @@ MailerClass = (options) -> Utils.Logger.error msg, TAG content = msg - @response.writeHead 200, 'Content-Type': if opts.type is 'html' then 'text/html' else 'text/plain' - @response.end(content, 'utf8') + @writeHead 200, 'Content-Type': if opts.type is 'html' then 'text/html' else 'text/plain' + @end(content, 'utf8') # This function adds the `send` route, for easy sending emails from # the browser. - sendAction = (template) -> + sendAction = (template, params) -> # Who to send to? It depends: it primarly reads from the `?to` # query param, and secondly from the `testEmail` prop in settings. - to = @params.query.to or settings.testEmail + to = params.query.to or settings.testEmail Utils.Logger.info "Sending #{template.name} ...", TAG if to? try - data = template.route.data and template.route.data.apply(this, arguments) + data = template.route.data and template.route.data.call(this, params) catch ex Utils.Logger.error 'Exception in '+template.name+' data function: '+ex.message, TAG return @@ -315,17 +321,17 @@ MailerClass = (options) -> @response.writeHead 500 msg = 'Did not send test email, something went wrong. Check the logs.' else - @response.writeHead 200 + @writeHead 200 # If there's no `MAIL_URL` environment variable, Meteor cannot send # the email and echoes it out to `STDOUT` instead. reallySentEmail = !!process.env.MAIL_URL msg = if reallySentEmail then "Sent test email to #{to}" else "Sent email to STDOUT" - @response.end(msg) + @end(msg) else - @response.writeHead 400 - @response.end("No testEmail provided.") + @writeHead 400 + @end("No testEmail provided.") # Adds all the routes from a template. addRoutes = (template) -> @@ -347,18 +353,17 @@ MailerClass = (options) -> # Also capitalize the first character in the template name for # the name of the route, so it will look like `previewSample` for a # template named `sample`. - path = "#{settings.routePrefix}/#{type}" + template.route.path + path = "/#{settings.routePrefix}/#{type}" + template.route.path name = Utils.capitalizeFirstChar(template.name) routeName = "#{type}#{name}" - Utils.Logger.info "Add route: [#{routeName}] at path /" + path, TAG + Utils.Logger.info "Add route: [#{routeName}] at path " + path, TAG + + # we use Picker for server side routes + Picker.route(path, (params, req, res) -> + action.call res, template, params + ) - Router.route routeName, - path: path - where: 'server' - # An action still need the route context, but call it - # with our `template` as the sole parameter. - action: -> action.call(this, template) # ## Init # diff --git a/package.js b/package.js index 02d8bcf..9f9b838 100644 --- a/package.js +++ b/package.js @@ -3,7 +3,7 @@ var where = 'server'; Package.describe({ name: 'lookback:emails', summary: 'Send HTML emails with server side Blaze templates. Preview and debug in the browser.', - version: '0.6.2', + version: '0.7.0', git: 'https://github.com/lookback/meteor-emails.git' }); @@ -23,8 +23,8 @@ Package.onUse(function(api) { 'coffeescript', 'email', 'sacha:juice@0.1.3', - 'iron:router@1.0.7', - 'meteorhacks:ssr@2.1.2' + 'meteorhacks:ssr@2.1.2', + 'meteorhacks:picker@1.0.3' ], where); api.addFiles([