maizzle / framework

Quickly build HTML emails with Tailwind CSS.
https://maizzle.com
MIT License
1.24k stars 49 forks source link

Tailwind class bg-no-repeat and base64 background image url conflict #1208

Closed sebastianblesgen closed 7 months ago

sebastianblesgen commented 8 months ago

When I use a base64 image in the url plus the bg-no-repeat class, the url is not rendered well. I think there is a conflict trying to merge everything in the style attribute. style="background-repeat: no-repeat; background-image: url('data:image/jpeg }}"> The url is trunc afeter jpeg and }} remains.

Note: If I do not use the main layout then the class are not inlined as style (that is expected) and the url is correctly rendered .

My template (x-main is the one that is installed when I create the project):

---
image: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQY..."
---

<x-main>
      <div class="bg-no-repeat" style="background-image: url('{{{ page.image }}}');">

      </div>
</x-main>

Result:

<!DOCTYPE html>
<html lang="en" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
  <meta charset="utf-8">
  <meta name="x-apple-disable-message-reformatting">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="format-detection" content="telephone=no, date=no, address=no, email=no, url=no">
  <meta name="color-scheme" content="light dark">
  <meta name="supported-color-schemes" content="light dark">
  <!--[if mso]>
  <noscript>
    <xml>
      <o:OfficeDocumentSettings xmlns:o="urn:schemas-microsoft-com:office:office">
        <o:PixelsPerInch>96</o:PixelsPerInch>
      </o:OfficeDocumentSettings>
    </xml>
  </noscript>
  <style>
    td,th,div,p,a,h1,h2,h3,h4,h5,h6 {font-family: "Segoe UI", sans-serif; mso-line-height-rule: exactly;}
  </style>
  <![endif]-->
  <style>
    img {
      max-width: 100%;
      vertical-align: middle;
      line-height: 1
    }
  </style>
</head>
<body style="margin: 0; width: 100%; padding: 0; -webkit-font-smoothing: antialiased; word-break: break-word">
  <div role="article" aria-roledescription="email" aria-label lang="en">
    <div style="background-repeat: no-repeat; background-image: url('data:image/jpeg }}">
    </div>
  </div>
</body>
</html>
cossssmin commented 8 months ago

Ugh, tough one to track down! Looks like it's coming from a dependency in our removeInlinedSelectors code, which tries to remove possibly-inlined CSS selectors.

The issue occurs in posthtml-attrs-parser, which we use to parse HTML element attributes in order to handle said removal. This library currently trips on the ; in the base64 string and produces a broken property value.

I tested with this custom Tailwind CSS utility, just in case expressions in Maizzle had anything to do (they don't):

@layer utilities {
  .bg-base64-px {
    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkAAIAAAoAAv/lxKUAAAAASUVORK5CYII=');
  }
}

Then used it in the template:

<x-main>
  <div class="bg-base64-px">
    test
  </div>
</x-main>

This is what posthtml-attrs-parser produces for that node:

{
  class: [ 'bg-base64-px' ],
  style: { 'background-image': "url('data:image/png" },
  compose: [Function (anonymous)]
}

For now one way to deal with it is to disable it:

// config.production.js
module.exports = {
  // ...
  removeUnusedCSS: {
    removeInlinedSelectors: false,
  },
}

Though keep in mind that will increase your HTML size, since unused CSS won't be purged anymore.

/cc @maltsev I'll try to add a failing test for this but think I'll need your help to fix it; we'll also need to backport it to v0.1.x

cossssmin commented 8 months ago

Opened a PR, once we get it fixed I'll work on backporting it to v0.1.2 so we can use it in Maizzle 4.x πŸ‘

https://github.com/posthtml/posthtml-attrs-parser/pull/17

cossssmin commented 8 months ago

By the way, if you're using base64 in HTML emails:

https://www.caniemail.com/features/image-base64/

maltsev commented 8 months ago

Opened a PR, once we get it fixed I'll work on backporting it to v0.1.2 so we can use it in Maizzle 4.x πŸ‘

Thanks! I'll release both versions (1.x and 0.1.x) after the 2nd PR will get merged.

cossssmin commented 7 months ago

@sebastianblesgen sorry this took a while, published v4.8.3 now that should fix it πŸ‘