Skip to content

Conversation

@iRyusa
Copy link
Member

@iRyusa iRyusa commented Apr 25, 2024

Edit: Available on MJML on v5 for now on experimental tag

@iRyusa iRyusa added the MJML 5 label Apr 25, 2024
@marvin-wtt
Copy link

I currently get the error nullTypeError: Cannot destructure property 'children' of 'element' as it is undefined. When compiling with CLI

@iRyusa
Copy link
Member Author

iRyusa commented May 4, 2024 via email

@marvin-wtt
Copy link

Make sure to have no global install, clean your node modules + lockfile

Just tried it with a fresh project and only the Black Friday template as test. Still fails.
It also fails in CI, so this can't be a global install issue.

@iRyusa
Copy link
Member Author

iRyusa commented May 14, 2024

@marvin-wtt found out the issue thanks for reporting check the latest version (alpha.2) should be good now 👍

@thewilkybarkid
Copy link

thewilkybarkid commented Jul 16, 2024

How experimental is this now? I see there have been alpha releases. Looks like CI isn't working as support for Node 16 needs to be dropped (cssnano doesn't support it as it's unmaintained).

@iRyusa iRyusa force-pushed the fix/replace-html-minifier branch from 54ebade to 097a2bd Compare July 30, 2024 09:09
@iRyusa
Copy link
Member Author

iRyusa commented Jul 30, 2024

I don't think we'll find some alternative to those lib now. I still need some work tho to bring back the CI to a green state

@AaronMoat
Copy link

@iRyusa for what it's worth, the CI commands locally seem happy enough if packages/mjml/test/html-attributes.test.js is updated to await mjml instead of just mjml; something similar to test.js seems to work:

async function run() {
  const { html } = await mjml(input)

  ... existing ... 
}

run();

@iRyusa
Copy link
Member Author

iRyusa commented Aug 3, 2024 via email

@AaronMoat
Copy link

Is there any other support that you might want to get this over the line from experimental to shipped @iRyusa? 😄

@iRyusa iRyusa linked an issue Oct 1, 2024 that may be closed by this pull request
@iRyusa iRyusa force-pushed the fix/replace-html-minifier branch from 6dfc0d7 to e457883 Compare October 4, 2024 12:40
@iRyusa iRyusa changed the title [EXPERIMENTAL] Replace html-minifier and js-beautify MJML5.0 Replace html-minifier and js-beautify Oct 4, 2024
@iRyusa
Copy link
Member Author

iRyusa commented Oct 4, 2024

Alpha 6 might be the last alpha version. Then I'll push it to the "live".

@robkorv
Copy link

robkorv commented Oct 18, 2024

@iRyusa thank you for this change. It's going to be deployed to our production on Monday 🤞🏽

@iRyusa
Copy link
Member Author

iRyusa commented Oct 18, 2024

Feel free to reach me on slack if you find any issues 👍

@jwaterworth
Copy link

@robkorv How was your deployment? Anything we need to be aware of in using this release?

Thanks @iRyusa for making this available! 🙏

@robkorv
Copy link

robkorv commented Nov 18, 2024

@robkorv How was your deployment? Anything we need to be aware of in using this release?

Without any problems. About 415.358 mail build with "5.0.0-alpha.6" since the deploy. The only thing that is changed is that mjml2html is now asynchronous. Everything else is still the same.

I use mjml in a microservice build with hapi. I only needed this change in a hapi route to make it work.

@@ -1,37 +1,40 @@
 "use strict";
 
 const Boom = require("@hapi/boom");
 const Mjml = require("mjml");
 
 module.exports = [
   {
     method: ["get", "post"],
     path: "/mjml",
-    handler: (request, h) => {
+    handler: async (request, h) => {
       if (request.method === "post") {
         try {
-          const result = Mjml(request.payload.mjml, request.payload.options);
+          const result = await Mjml(
+            request.payload.mjml,
+            request.payload.options
+          );
 
           if (request.payload.return_html) {
             const formattedMessages = result.errors
               .filter((x) => x.formattedMessage)
               .map((x) => x.formattedMessage);
             if (formattedMessages.length) {
               request.logger.warn(formattedMessages.join("\n"));
             }
 
             return result.html;
           }
 
           return result;
         } catch (err) {
           const boom = new Boom.Boom(err.toString());
           boom.reformat(true);
           return boom;
         }
       } else {
         return "post mjml and I will return html";
       }
     },
   },
 ];

@nickdnk
Copy link

nickdnk commented Jun 24, 2025

Any timeline on this? I would like to move a lot of things to mjml, but I'm a little confused about the state of this package/project. It seems to be a Mailjet product, but only one person works on this in his spare time? Is it not a company-backed library?

@iRyusa
Copy link
Member Author

iRyusa commented Jun 24, 2025

Someone at Mailjet will take the project back in their hands and i'm still trying to fix & merge last 2 pr I've done. This is the last blocking issue to get this merged #2919

Branched from iRyusa's 'MJML5.0 Replace html-minifier and js-beautify' to work on the CSS minification font-family naming issue
- leveraged readMjmlConfig to read config file
- move the fs and path imports
- removed uneccessary code
…minifier

bugfix(minifiers): added cssnano config options
@dazgreer
Copy link
Collaborator

dazgreer commented Nov 4, 2025

cssnano now uses the 'lite' profile by default but you can set your own profile using .mjmlconfig.js

e.g.

module.exports = {
  mjmlConfig: {
    packages: [],
    options: {
      minify: true,
      minifyOptions: {
         minifyCss: {
           options: {
             preset: ['default', {
                 minifyFontValues: { removeQuotes: false },
               },
             ],
           },
         },
      },
    },
  },
}

Add config options when you call mjml2html:

const result = await mjml2html(xml, {
      beautify: true,
      mjmlConfigPath: path.resolve('.mjmlconfig.js'),
      useMjmlConfigOptions: true,
})

fixes #2919

@thewilkybarkid
Copy link

Is this ready to be released now? 🤞

@robkorv
Copy link

robkorv commented Nov 11, 2025

Can you guys publish another alpha so we can test this?

@dazgreer dazgreer force-pushed the fix/replace-html-minifier branch from 2d3d1aa to a8fe155 Compare November 14, 2025 14:39
- created utils.js and updated all tests to use extractStyle function from it
- set keepComments to true by default as per previous minifier
@totocap totocap force-pushed the fix/replace-html-minifier branch from a8fe155 to c0baf31 Compare November 14, 2025 14:55
@dazgreer
Copy link
Collaborator

Hi, @thewilkybarkid @robkorv. We were intending to release on Friday, however we've run into an issue with building the mjml-browser package that seems to have been an issue present from an earlier commit. I'm waiting to sync with @iRyusa on this.

@dazgreer
Copy link
Collaborator

We've released v5.0.0-alpha.7 on an experimental tag.

IMPORTANT: the mjml-browser package will not build for this release (as it won't have since alpha.2) and this is an issue that we will need to resolve before we release MJML 5.0.0 as the latest.

@maxjacobson
Copy link

Thanks for cutting alpha 7 👏.

One observation I'm making is that some new warnings are printed:

Line 3 of /path/to/template.mjml (mj-wrapper) — Attributes border, padding, background-color are illegal

I think those attributes are allowed on mj-wrapper, as far as I can tell (I'm testing on the example template from the docs on this branch). Is this perhaps a bug in alpha 7?

Here's a script to reproduce, showing how the behavior differs between alpha 6 and 7:

Script
#!/bin/sh

set -e

runTest() {
  version="$1"

  dir="$(mktemp --directory)"
  cd "$dir"

  echo "== Creating npm project in $dir"
  npm init --yes >/dev/null

  echo "== installing mjml@$version"
  npm i --silent --save "mjml@$version"

  # Example from https://github.com/mjmlio/mjml/blob/fix/replace-html-minifier/packages/mjml-wrapper/README.md#mj-wrapper
  echo "== Creating example template.mjml"
  cat > template.mjml << 'EOF'
<mjml>
  <mj-body>
    <mj-wrapper border="1px solid #000000" padding="50px 30px" background-color="#ffffff">
      <mj-section border-top="1px solid #aaaaaa" border-left="1px solid #aaaaaa" border-right="1px solid #aaaaaa" padding="20px">
        <mj-column>
          <mj-image padding="0" src="https://placeholdit.imgix.net/~text?&w=350&h=150" />
        </mj-column>
      </mj-section>
      <mj-section border-left="1px solid #aaaaaa" border-right="1px solid #aaaaaa" padding="20px" border-bottom="1px solid #aaaaaa">
        <mj-column border="1px solid #dddddd">
          <mj-text padding="20px"> First line of text </mj-text>
          <mj-divider border-width="1px" border-style="dashed" border-color="lightgrey" padding="0 20px" />
          <mj-text padding="20px"> Second line of text </mj-text>
        </mj-column>
      </mj-section>
    </mj-wrapper>
  </mj-body>
</mjml>
EOF

  echo "== Using mjml@$version to convert template.mjml to template.html"
  node_modules/.bin/mjml --read template.mjml --output template.html --config.validationLevel strict
  echo "== Done!"
}

runTest "5.0.0-alpha.6"

echo
echo

runTest "5.0.0-alpha.7"

You can save this to test.sh and then run it with sh test.sh to see the output yourself

And here's the output of running that script:

$ sh test.sh
== Creating npm project in /var/folders/df/9m4mpnjj1gd1jrqd3kcrnc3h0000gp/T/tmp.cxHR8vN6Ig
== installing [email protected]
== Creating example template.mjml
== Using [email protected] to convert template.mjml to template.html
== Done!


== Creating npm project in /var/folders/df/9m4mpnjj1gd1jrqd3kcrnc3h0000gp/T/tmp.1BTjh4iT6y
== installing [email protected]
== Creating example template.mjml
== Using [email protected] to convert template.mjml to template.html
File: template.mjml
Error: ValidationError:
 Line 3 of /private/var/folders/df/9m4mpnjj1gd1jrqd3kcrnc3h0000gp/T/tmp.1BTjh4iT6y/template.mjml (mj-wrapper) — Attributes border, padding, background-color are illegal

Command line error:
Input file(s) failed to render

as you can see, the warning is not printed in alpha 6, but it is printed in alpha 7

@iRyusa
Copy link
Member Author

iRyusa commented Nov 19, 2025 via email

@maxjacobson
Copy link

Oh great!

@DazGreerMJ
Copy link

Sorry everyone, we didn't rebase. Have included the patch in v5.0.0-alpha.8 and released

@robkorv
Copy link

robkorv commented Nov 20, 2025

edit: and then alpha 8 dropped 😉

I had to install cssnano-preset-lite for v5.0.0-alpha.7 v5.0.0-alpha.8 to fix

../node_modules/cssnano/src/index.js:73
  throw new Error(
        ^

Error: Cannot load preset "lite". Please check your configuration for errors and try again.
    at resolvePreset (../node_modules/cssnano/src/index.js:73:9)
    at resolveConfig (../node_modules/cssnano/src/index.js:87:12)
    at cssnanoPlugin (../node_modules/cssnano/src/index.js:146:23)
    at processStyleNode (../node_modules/mjml-core/node_modules/htmlnano/dist/_modules/minifyCss.js:52:9)
    at ../node_modules/mjml-core/node_modules/htmlnano/dist/_modules/minifyCss.js:26:21
    at traverse (../node_modules/posthtml/lib/api.js:105:26)
    at traverse (../node_modules/posthtml/lib/api.js:111:5)
    at traverse (../node_modules/posthtml/lib/api.js:105:17)
    at traverse (../node_modules/posthtml/lib/api.js:111:5)
    at traverse (../node_modules/posthtml/lib/api.js:105:17)

Our unittests are succeeding with v5.0.0-alpha.7 v5.0.0-alpha.8. We are not using mjml-wrapper, so I'm going to deploy it to production today 🤞🏽.

@dazgreer
Copy link
Collaborator

Hi @robkorv, that's great, 🤞

Yes we've added the lite preset as the default one for cssnano. It's listed in the devDependencies

@maxjacobson
Copy link

maxjacobson commented Nov 20, 2025

Can confirm that for us, alpha 8 runs without error -- when I also install cssnano-preset-lite alongside it.

I wonder if it's possible to control the error message the user sees when that package isn't installed. If so, it would be nice for mjml to tell the user that installing that dependency is one way to resolve the error. Might be helpful. 🤔

Unrelated: I'm also noticing that mjml-cli is depending on a version of glob which is now tripping some security audit tools. Would definitely appreciate for the next alpha to bump the version of glob.

Thank you!

@robkorv
Copy link

robkorv commented Nov 20, 2025

I had to revert back to v5.0.0-alpha.6. Because of what I think is something raised by postcss:

CssSyntaxError: <css input>:1:4: Unknown word style

> 1 | a{{style}}
    |    ^

For some of our mail logic the html that we get from mjml will further be processed with mustache. Some of those values are dynamic per receiver. In alpha.6 faulty attributes are left alone, in 8 they raise an CssSyntaxError error.

This is an example of the mjml that raised the error:

<mjml>
  <mj-head>
    <mj-title>subject</mj-title>
  </mj-head>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-image src="https://example.org/resources/example_banner.png" />
      </mj-column>
    </mj-section>
    <mj-section>
      <mj-column>
        <mj-text>
          <h1>Hi you!</h1>
          <p>Thank you for testing the convert service!</p>
          <a href="{{link}}" style="{{style}}">
            This link is finalised after with mustache
          </a>
          <p>The text below has also replacements with mustache and is dynamic per reciever.</p>
          <p>Dear {{first_name}}, <br> {{body_text}}</p>
        </mj-text>
      </mj-column>
    </mj-section>
    <mj-section>
      <mj-column>
        <mj-button>This button is just for you!</mj-button>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

Is there a way to not raise the CssSyntaxError?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem Compiling Font Names High Severity Vulnerability in html-minifier