maizzle / framework

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

`plaintext` overrides `afterTransformers` (and maybe more) #1354

Closed krwenholz closed 19 hours ago

krwenholz commented 4 days ago

Hi there! I'm using Maizzle with HEEx. This means I want to output attributes like href={@url} without quotes (HEEx processing doesn't do its nice substitution with quotes present). I do generally want attributes quoted, so it's not desirable to totally disable that for PostHTML.

afterTransformers or replaceStrings seem like the way to go. The following config, however, results in templates output with href="{@url}" (note the quotes):

export default {
  plaintext: {
    output: {
      path: "output/email_text",
      extension: "text.heex",
    },
  },
  build: {
    output: {
      path: "output/email_html",
      extension: "html.heex",
    },
  },
  css: {
    inline: true,
    purge: true,
    shorthand: true,
  },
  prettify: true,
  afterTransformers({ html, config, matter }) {
    return html.replaceAll('href="{@url}"', "href={@url}");
  },
};

If I comment out the plaintext section, everything is good! I can also separate these out, but it seems like I should be able to do both in the same config file.

My JavaScript knowledge isn't great, but this line looks suspicious. It may also suggest some things aren't being applied/ordered correctly in the plaintext generation.

That's as far as I've gotten. Will update if I figure out any more. I'd appreciate any recommendations if I'm doing something off. Thanks!

cossssmin commented 4 days ago

Hi there, thanks for the detailed report!

That line you linked to is not from Maizzle 5 but it works the same way there, it updates the HTML to remove some custom plaintext tags like <not-plaintext>, so that's where it's coming from.

However its behavior is correct, this processing basically takes the compiled HTML through PostHTML again, so quotes will be applied to attributes. You could configure PostHTML to not quote attributes in this case, but that can be unsafe and possibly not even work with CSS inlining etc.

afterTransformers needs to happen inside the render method internally, which in turn needs to come before plaintext generation, so that plaintext generation can operate with the most up-to-date, possibly user-transformed like yours, HTML.

I think in your case it might be better to disable plaintext in the config and instead generate plaintext via the API, in the afterBuild event, which runs last.

krwenholz commented 3 days ago

Ah sorry about that link. And thanks for the advice! I’ll give it a go. If it works, I might suggest a docs update or some flag to alter the behavior such that you get the same output regardless of running with plain text output. I should have time on Monday.

krwenholz commented 1 day ago

Okay, that worked. Thanks!

This definitely works for now. I think a docs mention on the pipeline page would be the minimal change to clear things up. Something more invasive would probably be to be able to configure the plaintext pipeline separately, but I don't want to put that evil on you for v5 :)

Would you accept a docs change as a PR on the maizzle.com repo for this? I'd be happy to whip that up.

For reference:

import { generatePlaintext } from "@maizzle/framework";
import fs from "fs";
import path from "path";

/** @type {import('@maizzle/framework').Config} */
export default {
  /**
  Blah blah blah as above...
  **/
  afterBuild: async ({ files, config }) => {
    files.forEach(async (file) => {
      const content = fs.readFileSync(file, "utf8");
      const plainTextContent = await generatePlaintext(content);
      const newFilePath = path.join(
        "email_text_path",
        path.basename(file).replace("html.heex", "text.heex")
      );
      fs.writeFileSync(newFilePath, plainTextContent, "utf8");
      console.log(`Generated ${newFilePath} from ${file}`);
    });
  },
};
cossssmin commented 1 day ago

Would you accept a docs change as a PR on the maizzle.com repo for this? I'd be happy to whip that up.

Yes of course, it'd be a useful addition to the plaintext docs.

Just please target it at the next branch and we can take it from there 👍

krwenholz commented 19 hours ago

Done!

https://github.com/maizzle/maizzle.com/pull/248

I ended up changing the build-process page instead, as that's where I actually got confused. I'll close this sucker out and just watch the PR now.

Thanks @cossssmin.