mjml-net
mjml-net copied to clipboard
Support for <mj-style inline="inline"
Is it possible to support <mj-style inline="inline"> at all?
Yes, sure ... but it is not simple.
- You need to parse the CSS and create selectors out of it, something like
Dictionary<string, (string Name, string Value)[]> need to be stored somewhere.
- You need to find out which styles should be applied.
I think it is not that easy, especially the selector logic could be complicated.
I wonder, that it is in mjml spec. It is in fact transformation of final HTML, something like html-prettify.
They just leveraged an existing library: https://www.npmjs.com/package/juice
But I am not sure about the value of the inline feature.
Hi, I had another look to the problem and unfortunately you cannot implement this feature without keeping at least the full parent stack in memory. The problem are selectors like this
div[attr=value] a
This means you need all parent elements including its classes and attributes in memory, which will hurt performance a lot, I assume.
I'll try to do it in post build html phase (postprocess), storing inline classes in ?GlobalContext?
Then you need a DOM
Here's my two cents... I see this functionality as a completely different project that should co-exist alongside Mjml.Net. This is evident due to the fact that Mjml in node uses the external package Juice
for handling inlining styles.
I don't believe that it makes sense to introduce functionality to match this out-of-scope library for two reasons:
- It's functionally hard and messy
- It would heavily impact performance (negatively) for minimal value to the project
I would suggest, building, an separate library for example Juice.Net
which ports the HTML styles inlining functionality. This could then be up to the developer to whether they include this package and pass the output HTML from Mjml.Net
into Juice.Net
.
I kind of agree, but for me the value is even too small to implement it. If you have a look to the CSS support in browsers, you will see, that the majority supports them anyway. Without support a lot of other components do not work either. So the only real usage would be relatively simple emails for very old (mobile) clients. For me it is best practice to send out multipart emails, which have a text representation and a html representation. Then you have even more support for different use case.
Therefore I would not invest time into that. If I would invest time, I would probably make an extension to this popular .NET library: https://github.com/zzzprojects/html-agility-pack
About performance: It depends on the shape of your template. If you only allow simple placeholders and no conditional templates, you can precompile your template to html and then run the template engine on top of html. Then performance does not matter for this feature.
For me it is necessary feature. I've implemented it using https://github.com/jhy/jsoup library, it is not too big, but the performance suffers - mjml rendering is ~3x slower with inlining, since DOM construction.
For me it is not that important.
I agree with @SebastianStehle. However, the only reason this feature exists in the original MJML package is that Juice, the 3rd party library which provides this functionality is an easy drop-in feature which looks good on the MJML features sheet. I'm not aware of any library in .NET that would provide this functionality in a 1-to-1 manner as juice
. If so, you could recreate the logic outside of MJML.NET.
The implementation is a straightforward post-process step once the HTML content is generated, as seen here. Due to the implementation. I believe it would make more sense to port Juice
CSS inlining functionality to .NET and add that as a post-process step AFTER MJML.NET has generated the output HTML and returned it back to the developer.
That allows the MJML.NET to focus on speed and keep the dependencies of this project to a minimum.
Its not that important. I guess the challenging part is to implement all the selectors, but for me speed is more important and it is only important for very old email clients I guess.
One of the last missing features has been implemented :)