Mjml: mj-include won't work when mjml file is in subdirectory

Created on 3 Feb 2018  路  15Comments  路  Source: mjmlio/mjml

mj-include won't work if .mjml file is in a subdirectory.

Reproduction Steps:

  1. Create a node script for parsing in folder .../ like that:
const fs = require("fs");
const path = require('path');
const mjml = require("mjml");
const mjMail = fs.readFileSync(path.join(__dirname, "emails", "email.mjml"), "utf8");
const htmlMail = mjml.mjml2html(mjMail);
  1. Create file .../emails/email.mjml in folder .../emails/:
<mjml>
  <mj-head> <mj-include path="./emails/common-head" /> </mj-head>
  <mj-body> <mj-container> ... </mj-container> </mj-body>
</mjml>
  1. Create file .../emails/common-head.mjml:
<mj-attributes>...</mj-attributes>
<mj-style>...</mj-style>
  1. Run script from step 1

Expected behavior:

An HTML file will be created with the included common head file

Observed behavior:

The common head is not included and the script prints the error Warning: No handler found for: mj-raw, in mj-head, skipping it

MJML version:

v3.3.5

Changes which resolve the issue:

  • Putting every file in a common folder (may result in confusing)
  • Putting only the root mjml file email.mjml in the same directory as the script and including the mjml files from a subdirectory. (also not ideal)

Most helpful comment

This is what worked for med:

File tree:

/mail.js
/templates/hello.mjml
/components/header.mjml
/components/footer.mjml

hello.mjml

<mjml lang="en">
  <mj-body>
    <mj-include path="__dirname/../components/header.mjml" />
    <mj-text>Hello</mj-text>
    <mj-include path="__dirname/../components/footer.mjml" />
  </mj-body>
</mjml>

mail.js

export const sendHello = () => {
  const mjmlTemplate = fs.readFileSync(`${__dirname}/templates/hello.mjml`, 'utf8');
  const { html }聽= mjml2html(, {
      filePath: path.join(__dirname, 'components'),
  });
  // send email..
}

All 15 comments

Hey @IchordeDionysos, thanks for taking the time to investigate and describe that issue.

It looks related to https://github.com/mjmlio/mjml/issues/970 which is fixed for the next beta. We'll release a new beta version tomorrow with that fix, please let us know if it still happens then!

Waiting for new release

Same here

Any news?

Please be patient @ilyaskorik, we're working on the new beta version and will release it really soon. Also, if it's that urgent, you can git clone and install MJML locally instead of waiting for us to publish the beta release (everything you need is in the readme).

The issue was opened 4 days ago, bumping it every 18 hours won't help 馃檪.

This is now fixed in MJML 4.0.0-beta.2 so I'm closing!

Please upgrade with npm install mjml@next to use the latest beta.

I somehow can't include it anymore in any way using node.js ...

In the HTML always occurs this error:
<!-- mj-include fails to read file : ./common-footer.mjml at /.../common-footer.mjml -->
In any configuration describe above

Can you try to pass down { filePath: process.cwd() } as option to see if it does work ?

No sorry, doesn't work

Ok, and { filePath: path.join(__dirname, "emails", "email.mjml") } ?

Yes, that worked :)
But it's not possible (anymore) to leave out the .mjml suffix.
I don't know if this is the intended behavior? 馃

In my use-case, i loaded up the template in a different folder, and this worked:

My file tree:

/emails/global/footer.mjml
/emails/welcome/html.mjml
/utils/mailer.js

My html.mjml:
<mj-include path="./../global/footer.mjml" />

My mailer.js to load the template:

var templatePath = path.resolve(__dirname, '../emails/welcome/html.mjml);
var mjmlTemplate = fs.readFileSync(templatePath, 'utf8');
var htmlTemplate = mjml2html.default(mjmlTemplate, {filePath: path.resolve(__dirname, "../emails/global/email.mjml")}).html;

email.mjml does not exists, it just needs a file with an extension in order to work.

This is what worked for med:

File tree:

/mail.js
/templates/hello.mjml
/components/header.mjml
/components/footer.mjml

hello.mjml

<mjml lang="en">
  <mj-body>
    <mj-include path="__dirname/../components/header.mjml" />
    <mj-text>Hello</mj-text>
    <mj-include path="__dirname/../components/footer.mjml" />
  </mj-body>
</mjml>

mail.js

export const sendHello = () => {
  const mjmlTemplate = fs.readFileSync(`${__dirname}/templates/hello.mjml`, 'utf8');
  const { html }聽= mjml2html(, {
      filePath: path.join(__dirname, 'components'),
  });
  // send email..
}

@nomadoda thank!
I will just add a comment to give more description because I needed time to understand your code.
In filePath prop pass the path to your common files such as header, footer, etc.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tobystokes picture tobystokes  路  3Comments

lucasnantonio picture lucasnantonio  路  4Comments

iwanaga-sakura picture iwanaga-sakura  路  4Comments

samatcd picture samatcd  路  4Comments

sinsunsan picture sinsunsan  路  4Comments