Skip to content

Commit

Permalink
remove "-stub" suffix from project name
Browse files Browse the repository at this point in the history
Since Casey Holzer ported the remaining components from the NodeJS version of mjml,
I think the "stub" label is not warranted any longer.
  • Loading branch information
FelixSchwarz committed May 25, 2023
1 parent 972d255 commit 9f7a942
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 16 deletions.
43 changes: 31 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,56 @@
mjml-stub
=============
# mjml-python

This is an unofficial Python port of [mjml v4](https://github.com/mjmlio/mjml). It is implemented in pure Python and does not require JavaScript/NodeJS. mjml is a markup language created by [Mailjet](https://www.mailjet.com/) and designed to reduce the pain of coding a responsive email.

pip install mjml
### Installation

```sh
pip install mjml
```

### Usage

```py
from mjml import mjml_to_html
with open('foo.mjml', 'rb') as mjml_fp:
result = mjml_to_html(mjml_fp)
assert not result.errors
html: str = result.html
```

Alternatively you can run the code from the CLI:

```sh
$ mjml foo.mjml
```


## Limitations

WARNING: stub implementation only!
------------------------------------
This library only implements a subset of the original MJML project. It lacks several features found in the JavaScript mjml implementation (e.g. minification, beautification and validation). Also the code likely contains many additional bugs.

The upside is that there are lot of possibilities for you to make a real difference when you improve the code :-)


Goals / Motivation
------------------------------------
## Goals / Motivation

This library should track the [JS version of mjml](https://github.com/mjmlio/mjml) so ideally you should get the same HTML. However even under the best circumstances this library will always lag a bit behind as each change must be translated to Python manually (a mostly mechanical process).

While I like the idea behind mjml and all the knowledge about the quirks to get acceptable HTML rendering by various email clients we did not want to deploy a Node.js-based stack on our production servers. We did not feel comfortable auditing all 220 JS packages which are installed by `npm install mjml` (and re-doing this whenever new versions are available). Also due to data-privacy concerns we were unable to use any third-party products (i.e. MJML's API offering).

After a short [spike](https://en.wikipedia.org/wiki/Spike_(software_development)) to check the viability of a Python implementation I went ahead and wrote enough code to ensure some existing messages could be converted to mjml. Currently the library is deployed in some light production scenarios.

Another benefit of using Python is that we can integrate that in our web apps more closely. As the startup overhead of CPython is much lower than Node.js we can also generate a few mails via CLI applications without massive performance problems. CPython uses ~70ms to translate a trivial mjml template to HTML while Node.JS needs ~650ms.
Another benefit of using Python is that we can integrate that in our web apps more closely. As the startup overhead of CPython is much lower than Node.js we can also generate a few mails via CLI applications without massive performance problems. CPython uses \~70ms to translate a trivial mjml template to HTML while Node.JS needs \~650ms.



Documentation
------------------------------------
## Documentation

The idea is to implement the mjml XML dialect exactly like the JS implementation so eventually you should be able to use the [official docs](https://mjml.io/documentation/) and other online resources found on [mjml.io](https://mjml.io/). However we are nowhere near that right now! The current code can render the "Hello World" example as well as images, tables and groups but many components remain to be reimplemented. I'd love to see your pull requests to improve the current state though.


Alternatives / Additional Resources
------------------------------------

## Alternatives / Additional Resources

- **django-mjml**: If deploying NodeJS is not an issue and you are using Django you could use the well established [django-mjml](https://github.com/liminspace/django-mjml) library. That library integrates the mjml JavaScript implementation with Django templates so you can access all mjml features.
- **MJML.NET**: This is an unofficial port of mjml to C# ([github repo](https://github.com/LiamRiddell/MJML.NET/)) which supports more components than this Python implementation.
Expand Down
2 changes: 1 addition & 1 deletion mjml/helpers/json_to_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def json_to_xml(root: Mapping[str, Any], indent: str = '') -> str:
# {"passport": "hidden"} is a special attribute only present in
# JSON MJML. The attribute is set by Passport (Mailjet's template
# editor) to hide specific elements.
# https://github.com/FelixSchwarz/mjml-stub/commit/e1c006e213f26fb6dd9cf406b6e7b849350f6bc7#r47810966
# https://github.com/FelixSchwarz/mjml-python/commit/e1c006e213f26fb6dd9cf406b6e7b849350f6bc7#r47810966
if child.get('attributes', {}).get('passport', {}).get('hidden'):
continue
child_xml = json_to_xml(child, indent=child_indent)
Expand Down
6 changes: 3 additions & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ long_description_content_type = text/markdown

author = Felix Schwarz
author_email = felix.schwarz@oss.schwarz.eu
url = https://github.com/FelixSchwarz/mjml-stub
url = https://github.com/FelixSchwarz/mjml-python
license = MIT
license_file = LICENSE.txt

Expand All @@ -26,8 +26,8 @@ classifiers =
Topic :: Communications :: Email
Topic :: Text Processing :: Markup :: HTML
project_urls =
Code = https://github.com/FelixSchwarz/mjml-stub
Issue tracker = https://github.com/FelixSchwarz/mjml-stub/issues
Code = https://github.com/FelixSchwarz/mjml-python
Issue tracker = https://github.com/FelixSchwarz/mjml-python/issues


[options]
Expand Down

0 comments on commit 9f7a942

Please sign in to comment.