This repository has been archived by the owner. It is now read-only.

Repository files navigation

IMPORTANT - DEPRECATED

Please view the new stable version of this project Mjml.Net.

MJML.NET

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Introduction

MJML is a markup language created by Mailjet and designed to reduce the pain of coding a responsive email. Its semantic syntax makes the language easy and straightforward while its rich standard components library shortens your development time and lightens your email codebase. MJML’s open-source engine takes care of translating the MJML you wrote into responsive HTML.

You can find out more about MJML 4 from the official website.

| Official Website | Official Documentation | Official Onboarding |

Usage

Firstly, you'll need to reference the MJML.NET NuGet Package into your project.

PM > Install-Package MjmlDotNet

Secondly, include MJML.NET namespace into your project.

usingMjmlDotNet;

Finally, the boilerplate code.

publicvoidMain(){// or DIIMjmlParsermjmlParser=newMjmlParser();stringmjml=@" <mjml> <mj-head> <mj-title>Hello World Example</mj-title> </mj-head> <mj-body> <mj-section> <mj-column> <mj-text> Hello World! </mj-text> </mj-column> </mj-section> </mj-body> </mjml>";stringhtml=mjmlParser.ParseDocument(mjmlString);}

Options

You can also specify options to the MJML parser. This can be done either at instantiation throught the defaultOptions parameter or at time of parsing the document. Both options are shown below.

publicvoidMain(){// 1. Default Options for every MJML documentMjmlParserOptionsdefaultOptions=newMjmlParserOptions(){Minify=true;Prettify=false;}IMjmlParsermjmlParser=newMjmlParser(defaultOptions);// Or 2. Override at per-document parsingMjmlParserOptionsoptions=newMjmlParserOptions(){Minify=true;Prettify=false;}stringhtml=mjmlParser.ParseDocument(mjml,options);}

Currently, we've not implemented all of the same options. This is because we're still introducing components and refactoring the project. However, the currently supported options are:

NameData TypeDefaultDescription
PrettifyBooleanFalsePrettifies the output when enabled.
MinifyBooleanTrueMinifies the output when enabled. This overrides Prettify as this would be ideal default in production environment.

Status

MJML.NET tries to implement all functionality 1-2-1 with the MJML 4 project. However, due to JavaScript not being a typed language this means there has been considerate refactoring to the code to make it more aligned with C# typed requirements.

As the project is currently still in experimental state not all MJML components have been added. Please see the below table for a list of all components and the current implementation state:

TypeComponentImplementedTestsState
CoremjmlAwaiting Tests
Coremjml-headAwaiting Tests
Coremjml-bodyAwaiting Tests
Coremjml-includeNot Implemented
Headmjml-attributesAwaiting Tests
Headmjml-classNot Implemented
Headmjml-allNot Implemented
Headmjml-breakpointAwaiting Tests
Headmjml-fontAwaiting Tests
Headmjml-html-attributesNot Implemented
Headmjml-previewAwaiting Tests
Headmjml-style☑️Partially Complete (Inline Support Required)
Headmjml-titleComplete
Bodymjml-accordionNot Implemented
Bodymjml-buttonAwaiting Tests
Bodymjml-carouselNot Implemented
Bodymjml-columnAwaiting Tests
Bodymjml-dividerAwaiting Tests
Bodymjml-groupAwaiting Tests
Bodymjml-heroAwaiting Tests
Bodymjml-imageAwaiting Tests
Bodymjml-navbarAwaiting Tests
Bodymjml-rawAwaiting Tests
Bodymjml-section☑️Partially Complete (Background Position Bug)
Bodymjml-socialAwaiting Tests
Bodymjml-spacerAwaiting Tests
Bodymjml-tableAwaiting Tests (AngleSharp Issue)
Bodymjml-textAwaiting Tests
Bodymjml-wrapperAwaiting Tests

Tests

Testing this project has been rather difficult due to the nature of the output. However, we're still trying to provide valuable tests for components which can validate correct output. For example, if we set the <mj-title> the outputted HTML document <title> should match.

Furthermore, this project will fall into the grey area of testing. Because of this, we'll rely heavily on bug reports from usage of MJML.NET.

Benchmark

We've benchmarked the main components of the library to make sure we're within a suitable execution speed. We'll continue monitoring the execution speed as part of project development. We benchmark based off the default MJML templates.

MethodMeanErrorStdDev
TryParseDocument37.64 ms2.538 ms7.483 ms
ParseDocument38.77 ms2.549 ms7.515 ms
ParseDocumentAsync38.24 ms2.157 ms6.360 ms

Contribution

We really appreciate any contribution to the project to help provide a native version of MJML to C#.

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Side Note: In your PR you should summarise your changes, bug fixes or general modifications.

Appreciations

Once again, it's good to share some appreciation to the projects that make MJML.NET possible.

License

MIT License

Copyright (c) 2020 Liam Riddell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository has been archived by the owner. It is now read-only.

Repository files navigation

IMPORTANT - DEPRECATED

Please view the new stable version of this project Mjml.Net.

MJML.NET

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Introduction

MJML is a markup language created by Mailjet and designed to reduce the pain of coding a responsive email. Its semantic syntax makes the language easy and straightforward while its rich standard components library shortens your development time and lightens your email codebase. MJML’s open-source engine takes care of translating the MJML you wrote into responsive HTML.

You can find out more about MJML 4 from the official website.

| Official Website | Official Documentation | Official Onboarding |

Usage

Firstly, you'll need to reference the MJML.NET NuGet Package into your project.

PM > Install-Package MjmlDotNet

Secondly, include MJML.NET namespace into your project.

usingMjmlDotNet;

Finally, the boilerplate code.

publicvoidMain(){// or DIIMjmlParsermjmlParser=newMjmlParser();stringmjml=@" <mjml> <mj-head> <mj-title>Hello World Example</mj-title> </mj-head> <mj-body> <mj-section> <mj-column> <mj-text> Hello World! </mj-text> </mj-column> </mj-section> </mj-body> </mjml>";stringhtml=mjmlParser.ParseDocument(mjmlString);}

Options

You can also specify options to the MJML parser. This can be done either at instantiation throught the defaultOptions parameter or at time of parsing the document. Both options are shown below.

publicvoidMain(){// 1. Default Options for every MJML documentMjmlParserOptionsdefaultOptions=newMjmlParserOptions(){Minify=true;Prettify=false;}IMjmlParsermjmlParser=newMjmlParser(defaultOptions);// Or 2. Override at per-document parsingMjmlParserOptionsoptions=newMjmlParserOptions(){Minify=true;Prettify=false;}stringhtml=mjmlParser.ParseDocument(mjml,options);}

Currently, we've not implemented all of the same options. This is because we're still introducing components and refactoring the project. However, the currently supported options are:

NameData TypeDefaultDescription
PrettifyBooleanFalsePrettifies the output when enabled.
MinifyBooleanTrueMinifies the output when enabled. This overrides Prettify as this would be ideal default in production environment.

Status

MJML.NET tries to implement all functionality 1-2-1 with the MJML 4 project. However, due to JavaScript not being a typed language this means there has been considerate refactoring to the code to make it more aligned with C# typed requirements.

As the project is currently still in experimental state not all MJML components have been added. Please see the below table for a list of all components and the current implementation state:

TypeComponentImplementedTestsState
CoremjmlAwaiting Tests
Coremjml-headAwaiting Tests
Coremjml-bodyAwaiting Tests
Coremjml-includeNot Implemented
Headmjml-attributesAwaiting Tests
Headmjml-classNot Implemented
Headmjml-allNot Implemented
Headmjml-breakpointAwaiting Tests
Headmjml-fontAwaiting Tests
Headmjml-html-attributesNot Implemented
Headmjml-previewAwaiting Tests
Headmjml-style☑️Partially Complete (Inline Support Required)
Headmjml-titleComplete
Bodymjml-accordionNot Implemented
Bodymjml-buttonAwaiting Tests
Bodymjml-carouselNot Implemented
Bodymjml-columnAwaiting Tests
Bodymjml-dividerAwaiting Tests
Bodymjml-groupAwaiting Tests
Bodymjml-heroAwaiting Tests
Bodymjml-imageAwaiting Tests
Bodymjml-navbarAwaiting Tests
Bodymjml-rawAwaiting Tests
Bodymjml-section☑️Partially Complete (Background Position Bug)
Bodymjml-socialAwaiting Tests
Bodymjml-spacerAwaiting Tests
Bodymjml-tableAwaiting Tests (AngleSharp Issue)
Bodymjml-textAwaiting Tests
Bodymjml-wrapperAwaiting Tests

Tests

Testing this project has been rather difficult due to the nature of the output. However, we're still trying to provide valuable tests for components which can validate correct output. For example, if we set the <mj-title> the outputted HTML document <title> should match.

Furthermore, this project will fall into the grey area of testing. Because of this, we'll rely heavily on bug reports from usage of MJML.NET.

Benchmark

We've benchmarked the main components of the library to make sure we're within a suitable execution speed. We'll continue monitoring the execution speed as part of project development. We benchmark based off the default MJML templates.

MethodMeanErrorStdDev
TryParseDocument37.64 ms2.538 ms7.483 ms
ParseDocument38.77 ms2.549 ms7.515 ms
ParseDocumentAsync38.24 ms2.157 ms6.360 ms

Contribution

We really appreciate any contribution to the project to help provide a native version of MJML to C#.

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Side Note: In your PR you should summarise your changes, bug fixes or general modifications.

Appreciations

Once again, it's good to share some appreciation to the projects that make MJML.NET possible.

License

MIT License

Copyright (c) 2020 Liam Riddell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository has been archived by the owner. It is now read-only.

Repository files navigation

IMPORTANT - DEPRECATED

Please view the new stable version of this project Mjml.Net.

MJML.NET

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Introduction

MJML is a markup language created by Mailjet and designed to reduce the pain of coding a responsive email. Its semantic syntax makes the language easy and straightforward while its rich standard components library shortens your development time and lightens your email codebase. MJML’s open-source engine takes care of translating the MJML you wrote into responsive HTML.

You can find out more about MJML 4 from the official website.

| Official Website | Official Documentation | Official Onboarding |

Usage

Firstly, you'll need to reference the MJML.NET NuGet Package into your project.

PM > Install-Package MjmlDotNet

Secondly, include MJML.NET namespace into your project.

usingMjmlDotNet;

Finally, the boilerplate code.

publicvoidMain(){// or DIIMjmlParsermjmlParser=newMjmlParser();stringmjml=@" <mjml> <mj-head> <mj-title>Hello World Example</mj-title> </mj-head> <mj-body> <mj-section> <mj-column> <mj-text> Hello World! </mj-text> </mj-column> </mj-section> </mj-body> </mjml>";stringhtml=mjmlParser.ParseDocument(mjmlString);}

Options

You can also specify options to the MJML parser. This can be done either at instantiation throught the defaultOptions parameter or at time of parsing the document. Both options are shown below.

publicvoidMain(){// 1. Default Options for every MJML documentMjmlParserOptionsdefaultOptions=newMjmlParserOptions(){Minify=true;Prettify=false;}IMjmlParsermjmlParser=newMjmlParser(defaultOptions);// Or 2. Override at per-document parsingMjmlParserOptionsoptions=newMjmlParserOptions(){Minify=true;Prettify=false;}stringhtml=mjmlParser.ParseDocument(mjml,options);}

Currently, we've not implemented all of the same options. This is because we're still introducing components and refactoring the project. However, the currently supported options are:

NameData TypeDefaultDescription
PrettifyBooleanFalsePrettifies the output when enabled.
MinifyBooleanTrueMinifies the output when enabled. This overrides Prettify as this would be ideal default in production environment.

Status

MJML.NET tries to implement all functionality 1-2-1 with the MJML 4 project. However, due to JavaScript not being a typed language this means there has been considerate refactoring to the code to make it more aligned with C# typed requirements.

As the project is currently still in experimental state not all MJML components have been added. Please see the below table for a list of all components and the current implementation state:

TypeComponentImplementedTestsState
CoremjmlAwaiting Tests
Coremjml-headAwaiting Tests
Coremjml-bodyAwaiting Tests
Coremjml-includeNot Implemented
Headmjml-attributesAwaiting Tests
Headmjml-classNot Implemented
Headmjml-allNot Implemented
Headmjml-breakpointAwaiting Tests
Headmjml-fontAwaiting Tests
Headmjml-html-attributesNot Implemented
Headmjml-previewAwaiting Tests
Headmjml-style☑️Partially Complete (Inline Support Required)
Headmjml-titleComplete
Bodymjml-accordionNot Implemented
Bodymjml-buttonAwaiting Tests
Bodymjml-carouselNot Implemented
Bodymjml-columnAwaiting Tests
Bodymjml-dividerAwaiting Tests
Bodymjml-groupAwaiting Tests
Bodymjml-heroAwaiting Tests
Bodymjml-imageAwaiting Tests
Bodymjml-navbarAwaiting Tests
Bodymjml-rawAwaiting Tests
Bodymjml-section☑️Partially Complete (Background Position Bug)
Bodymjml-socialAwaiting Tests
Bodymjml-spacerAwaiting Tests
Bodymjml-tableAwaiting Tests (AngleSharp Issue)
Bodymjml-textAwaiting Tests
Bodymjml-wrapperAwaiting Tests

Tests

Testing this project has been rather difficult due to the nature of the output. However, we're still trying to provide valuable tests for components which can validate correct output. For example, if we set the <mj-title> the outputted HTML document <title> should match.

Furthermore, this project will fall into the grey area of testing. Because of this, we'll rely heavily on bug reports from usage of MJML.NET.

Benchmark

We've benchmarked the main components of the library to make sure we're within a suitable execution speed. We'll continue monitoring the execution speed as part of project development. We benchmark based off the default MJML templates.

MethodMeanErrorStdDev
TryParseDocument37.64 ms2.538 ms7.483 ms
ParseDocument38.77 ms2.549 ms7.515 ms
ParseDocumentAsync38.24 ms2.157 ms6.360 ms

Contribution

We really appreciate any contribution to the project to help provide a native version of MJML to C#.

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Side Note: In your PR you should summarise your changes, bug fixes or general modifications.

Appreciations

Once again, it's good to share some appreciation to the projects that make MJML.NET possible.

License

MIT License

Copyright (c) 2020 Liam Riddell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository has been archived by the owner. It is now read-only.

Repository files navigation

IMPORTANT - DEPRECATED

Please view the new stable version of this project Mjml.Net.

MJML.NET

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Introduction

MJML is a markup language created by Mailjet and designed to reduce the pain of coding a responsive email. Its semantic syntax makes the language easy and straightforward while its rich standard components library shortens your development time and lightens your email codebase. MJML’s open-source engine takes care of translating the MJML you wrote into responsive HTML.

You can find out more about MJML 4 from the official website.

| Official Website | Official Documentation | Official Onboarding |

Usage

Firstly, you'll need to reference the MJML.NET NuGet Package into your project.

PM > Install-Package MjmlDotNet

Secondly, include MJML.NET namespace into your project.

usingMjmlDotNet;

Finally, the boilerplate code.

publicvoidMain(){// or DIIMjmlParsermjmlParser=newMjmlParser();stringmjml=@" <mjml> <mj-head> <mj-title>Hello World Example</mj-title> </mj-head> <mj-body> <mj-section> <mj-column> <mj-text> Hello World! </mj-text> </mj-column> </mj-section> </mj-body> </mjml>";stringhtml=mjmlParser.ParseDocument(mjmlString);}

Options

You can also specify options to the MJML parser. This can be done either at instantiation throught the defaultOptions parameter or at time of parsing the document. Both options are shown below.

publicvoidMain(){// 1. Default Options for every MJML documentMjmlParserOptionsdefaultOptions=newMjmlParserOptions(){Minify=true;Prettify=false;}IMjmlParsermjmlParser=newMjmlParser(defaultOptions);// Or 2. Override at per-document parsingMjmlParserOptionsoptions=newMjmlParserOptions(){Minify=true;Prettify=false;}stringhtml=mjmlParser.ParseDocument(mjml,options);}

Currently, we've not implemented all of the same options. This is because we're still introducing components and refactoring the project. However, the currently supported options are:

NameData TypeDefaultDescription
PrettifyBooleanFalsePrettifies the output when enabled.
MinifyBooleanTrueMinifies the output when enabled. This overrides Prettify as this would be ideal default in production environment.

Status

MJML.NET tries to implement all functionality 1-2-1 with the MJML 4 project. However, due to JavaScript not being a typed language this means there has been considerate refactoring to the code to make it more aligned with C# typed requirements.

As the project is currently still in experimental state not all MJML components have been added. Please see the below table for a list of all components and the current implementation state:

TypeComponentImplementedTestsState
CoremjmlAwaiting Tests
Coremjml-headAwaiting Tests
Coremjml-bodyAwaiting Tests
Coremjml-includeNot Implemented
Headmjml-attributesAwaiting Tests
Headmjml-classNot Implemented
Headmjml-allNot Implemented
Headmjml-breakpointAwaiting Tests
Headmjml-fontAwaiting Tests
Headmjml-html-attributesNot Implemented
Headmjml-previewAwaiting Tests
Headmjml-style☑️Partially Complete (Inline Support Required)
Headmjml-titleComplete
Bodymjml-accordionNot Implemented
Bodymjml-buttonAwaiting Tests
Bodymjml-carouselNot Implemented
Bodymjml-columnAwaiting Tests
Bodymjml-dividerAwaiting Tests
Bodymjml-groupAwaiting Tests
Bodymjml-heroAwaiting Tests
Bodymjml-imageAwaiting Tests
Bodymjml-navbarAwaiting Tests
Bodymjml-rawAwaiting Tests
Bodymjml-section☑️Partially Complete (Background Position Bug)
Bodymjml-socialAwaiting Tests
Bodymjml-spacerAwaiting Tests
Bodymjml-tableAwaiting Tests (AngleSharp Issue)
Bodymjml-textAwaiting Tests
Bodymjml-wrapperAwaiting Tests

Tests

Testing this project has been rather difficult due to the nature of the output. However, we're still trying to provide valuable tests for components which can validate correct output. For example, if we set the <mj-title> the outputted HTML document <title> should match.

Furthermore, this project will fall into the grey area of testing. Because of this, we'll rely heavily on bug reports from usage of MJML.NET.

Benchmark

We've benchmarked the main components of the library to make sure we're within a suitable execution speed. We'll continue monitoring the execution speed as part of project development. We benchmark based off the default MJML templates.

MethodMeanErrorStdDev
TryParseDocument37.64 ms2.538 ms7.483 ms
ParseDocument38.77 ms2.549 ms7.515 ms
ParseDocumentAsync38.24 ms2.157 ms6.360 ms

Contribution

We really appreciate any contribution to the project to help provide a native version of MJML to C#.

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Side Note: In your PR you should summarise your changes, bug fixes or general modifications.

Appreciations

Once again, it's good to share some appreciation to the projects that make MJML.NET possible.

License

MIT License

Copyright (c) 2020 Liam Riddell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository has been archived by the owner. It is now read-only.

Repository files navigation

IMPORTANT - DEPRECATED

Please view the new stable version of this project Mjml.Net.

MJML.NET

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Introduction

MJML is a markup language created by Mailjet and designed to reduce the pain of coding a responsive email. Its semantic syntax makes the language easy and straightforward while its rich standard components library shortens your development time and lightens your email codebase. MJML’s open-source engine takes care of translating the MJML you wrote into responsive HTML.

You can find out more about MJML 4 from the official website.

| Official Website | Official Documentation | Official Onboarding |

Usage

Firstly, you'll need to reference the MJML.NET NuGet Package into your project.

PM > Install-Package MjmlDotNet

Secondly, include MJML.NET namespace into your project.

usingMjmlDotNet;

Finally, the boilerplate code.

publicvoidMain(){// or DIIMjmlParsermjmlParser=newMjmlParser();stringmjml=@" <mjml> <mj-head> <mj-title>Hello World Example</mj-title> </mj-head> <mj-body> <mj-section> <mj-column> <mj-text> Hello World! </mj-text> </mj-column> </mj-section> </mj-body> </mjml>";stringhtml=mjmlParser.ParseDocument(mjmlString);}

Options

You can also specify options to the MJML parser. This can be done either at instantiation throught the defaultOptions parameter or at time of parsing the document. Both options are shown below.

publicvoidMain(){// 1. Default Options for every MJML documentMjmlParserOptionsdefaultOptions=newMjmlParserOptions(){Minify=true;Prettify=false;}IMjmlParsermjmlParser=newMjmlParser(defaultOptions);// Or 2. Override at per-document parsingMjmlParserOptionsoptions=newMjmlParserOptions(){Minify=true;Prettify=false;}stringhtml=mjmlParser.ParseDocument(mjml,options);}

Currently, we've not implemented all of the same options. This is because we're still introducing components and refactoring the project. However, the currently supported options are:

NameData TypeDefaultDescription
PrettifyBooleanFalsePrettifies the output when enabled.
MinifyBooleanTrueMinifies the output when enabled. This overrides Prettify as this would be ideal default in production environment.

Status

MJML.NET tries to implement all functionality 1-2-1 with the MJML 4 project. However, due to JavaScript not being a typed language this means there has been considerate refactoring to the code to make it more aligned with C# typed requirements.

As the project is currently still in experimental state not all MJML components have been added. Please see the below table for a list of all components and the current implementation state:

TypeComponentImplementedTestsState
CoremjmlAwaiting Tests
Coremjml-headAwaiting Tests
Coremjml-bodyAwaiting Tests
Coremjml-includeNot Implemented
Headmjml-attributesAwaiting Tests
Headmjml-classNot Implemented
Headmjml-allNot Implemented
Headmjml-breakpointAwaiting Tests
Headmjml-fontAwaiting Tests
Headmjml-html-attributesNot Implemented
Headmjml-previewAwaiting Tests
Headmjml-style☑️Partially Complete (Inline Support Required)
Headmjml-titleComplete
Bodymjml-accordionNot Implemented
Bodymjml-buttonAwaiting Tests
Bodymjml-carouselNot Implemented
Bodymjml-columnAwaiting Tests
Bodymjml-dividerAwaiting Tests
Bodymjml-groupAwaiting Tests
Bodymjml-heroAwaiting Tests
Bodymjml-imageAwaiting Tests
Bodymjml-navbarAwaiting Tests
Bodymjml-rawAwaiting Tests
Bodymjml-section☑️Partially Complete (Background Position Bug)
Bodymjml-socialAwaiting Tests
Bodymjml-spacerAwaiting Tests
Bodymjml-tableAwaiting Tests (AngleSharp Issue)
Bodymjml-textAwaiting Tests
Bodymjml-wrapperAwaiting Tests

Tests

Testing this project has been rather difficult due to the nature of the output. However, we're still trying to provide valuable tests for components which can validate correct output. For example, if we set the <mj-title> the outputted HTML document <title> should match.

Furthermore, this project will fall into the grey area of testing. Because of this, we'll rely heavily on bug reports from usage of MJML.NET.

Benchmark

We've benchmarked the main components of the library to make sure we're within a suitable execution speed. We'll continue monitoring the execution speed as part of project development. We benchmark based off the default MJML templates.

MethodMeanErrorStdDev
TryParseDocument37.64 ms2.538 ms7.483 ms
ParseDocument38.77 ms2.549 ms7.515 ms
ParseDocumentAsync38.24 ms2.157 ms6.360 ms

Contribution

We really appreciate any contribution to the project to help provide a native version of MJML to C#.

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Side Note: In your PR you should summarise your changes, bug fixes or general modifications.

Appreciations

Once again, it's good to share some appreciation to the projects that make MJML.NET possible.

License

MIT License

Copyright (c) 2020 Liam Riddell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository has been archived by the owner. It is now read-only.

Repository files navigation

IMPORTANT - DEPRECATED

Please view the new stable version of this project Mjml.Net.

MJML.NET

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Introduction

MJML is a markup language created by Mailjet and designed to reduce the pain of coding a responsive email. Its semantic syntax makes the language easy and straightforward while its rich standard components library shortens your development time and lightens your email codebase. MJML’s open-source engine takes care of translating the MJML you wrote into responsive HTML.

You can find out more about MJML 4 from the official website.

| Official Website | Official Documentation | Official Onboarding |

Usage

Firstly, you'll need to reference the MJML.NET NuGet Package into your project.

PM > Install-Package MjmlDotNet

Secondly, include MJML.NET namespace into your project.

usingMjmlDotNet;

Finally, the boilerplate code.

publicvoidMain(){// or DIIMjmlParsermjmlParser=newMjmlParser();stringmjml=@" <mjml> <mj-head> <mj-title>Hello World Example</mj-title> </mj-head> <mj-body> <mj-section> <mj-column> <mj-text> Hello World! </mj-text> </mj-column> </mj-section> </mj-body> </mjml>";stringhtml=mjmlParser.ParseDocument(mjmlString);}

Options

You can also specify options to the MJML parser. This can be done either at instantiation throught the defaultOptions parameter or at time of parsing the document. Both options are shown below.

publicvoidMain(){// 1. Default Options for every MJML documentMjmlParserOptionsdefaultOptions=newMjmlParserOptions(){Minify=true;Prettify=false;}IMjmlParsermjmlParser=newMjmlParser(defaultOptions);// Or 2. Override at per-document parsingMjmlParserOptionsoptions=newMjmlParserOptions(){Minify=true;Prettify=false;}stringhtml=mjmlParser.ParseDocument(mjml,options);}

Currently, we've not implemented all of the same options. This is because we're still introducing components and refactoring the project. However, the currently supported options are:

NameData TypeDefaultDescription
PrettifyBooleanFalsePrettifies the output when enabled.
MinifyBooleanTrueMinifies the output when enabled. This overrides Prettify as this would be ideal default in production environment.

Status

MJML.NET tries to implement all functionality 1-2-1 with the MJML 4 project. However, due to JavaScript not being a typed language this means there has been considerate refactoring to the code to make it more aligned with C# typed requirements.

As the project is currently still in experimental state not all MJML components have been added. Please see the below table for a list of all components and the current implementation state:

TypeComponentImplementedTestsState
CoremjmlAwaiting Tests
Coremjml-headAwaiting Tests
Coremjml-bodyAwaiting Tests
Coremjml-includeNot Implemented
Headmjml-attributesAwaiting Tests
Headmjml-classNot Implemented
Headmjml-allNot Implemented
Headmjml-breakpointAwaiting Tests
Headmjml-fontAwaiting Tests
Headmjml-html-attributesNot Implemented
Headmjml-previewAwaiting Tests
Headmjml-style☑️Partially Complete (Inline Support Required)
Headmjml-titleComplete
Bodymjml-accordionNot Implemented
Bodymjml-buttonAwaiting Tests
Bodymjml-carouselNot Implemented
Bodymjml-columnAwaiting Tests
Bodymjml-dividerAwaiting Tests
Bodymjml-groupAwaiting Tests
Bodymjml-heroAwaiting Tests
Bodymjml-imageAwaiting Tests
Bodymjml-navbarAwaiting Tests
Bodymjml-rawAwaiting Tests
Bodymjml-section☑️Partially Complete (Background Position Bug)
Bodymjml-socialAwaiting Tests
Bodymjml-spacerAwaiting Tests
Bodymjml-tableAwaiting Tests (AngleSharp Issue)
Bodymjml-textAwaiting Tests
Bodymjml-wrapperAwaiting Tests

Tests

Testing this project has been rather difficult due to the nature of the output. However, we're still trying to provide valuable tests for components which can validate correct output. For example, if we set the <mj-title> the outputted HTML document <title> should match.

Furthermore, this project will fall into the grey area of testing. Because of this, we'll rely heavily on bug reports from usage of MJML.NET.

Benchmark

We've benchmarked the main components of the library to make sure we're within a suitable execution speed. We'll continue monitoring the execution speed as part of project development. We benchmark based off the default MJML templates.

MethodMeanErrorStdDev
TryParseDocument37.64 ms2.538 ms7.483 ms
ParseDocument38.77 ms2.549 ms7.515 ms
ParseDocumentAsync38.24 ms2.157 ms6.360 ms

Contribution

We really appreciate any contribution to the project to help provide a native version of MJML to C#.

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Side Note: In your PR you should summarise your changes, bug fixes or general modifications.

Appreciations

Once again, it's good to share some appreciation to the projects that make MJML.NET possible.

License

MIT License

Copyright (c) 2020 Liam Riddell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository has been archived by the owner. It is now read-only.

Repository files navigation

IMPORTANT - DEPRECATED

Please view the new stable version of this project Mjml.Net.

MJML.NET

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Introduction

MJML is a markup language created by Mailjet and designed to reduce the pain of coding a responsive email. Its semantic syntax makes the language easy and straightforward while its rich standard components library shortens your development time and lightens your email codebase. MJML’s open-source engine takes care of translating the MJML you wrote into responsive HTML.

You can find out more about MJML 4 from the official website.

| Official Website | Official Documentation | Official Onboarding |

Usage

Firstly, you'll need to reference the MJML.NET NuGet Package into your project.

PM > Install-Package MjmlDotNet

Secondly, include MJML.NET namespace into your project.

usingMjmlDotNet;

Finally, the boilerplate code.

publicvoidMain(){// or DIIMjmlParsermjmlParser=newMjmlParser();stringmjml=@" <mjml> <mj-head> <mj-title>Hello World Example</mj-title> </mj-head> <mj-body> <mj-section> <mj-column> <mj-text> Hello World! </mj-text> </mj-column> </mj-section> </mj-body> </mjml>";stringhtml=mjmlParser.ParseDocument(mjmlString);}

Options

You can also specify options to the MJML parser. This can be done either at instantiation throught the defaultOptions parameter or at time of parsing the document. Both options are shown below.

publicvoidMain(){// 1. Default Options for every MJML documentMjmlParserOptionsdefaultOptions=newMjmlParserOptions(){Minify=true;Prettify=false;}IMjmlParsermjmlParser=newMjmlParser(defaultOptions);// Or 2. Override at per-document parsingMjmlParserOptionsoptions=newMjmlParserOptions(){Minify=true;Prettify=false;}stringhtml=mjmlParser.ParseDocument(mjml,options);}

Currently, we've not implemented all of the same options. This is because we're still introducing components and refactoring the project. However, the currently supported options are:

NameData TypeDefaultDescription
PrettifyBooleanFalsePrettifies the output when enabled.
MinifyBooleanTrueMinifies the output when enabled. This overrides Prettify as this would be ideal default in production environment.

Status

MJML.NET tries to implement all functionality 1-2-1 with the MJML 4 project. However, due to JavaScript not being a typed language this means there has been considerate refactoring to the code to make it more aligned with C# typed requirements.

As the project is currently still in experimental state not all MJML components have been added. Please see the below table for a list of all components and the current implementation state:

TypeComponentImplementedTestsState
CoremjmlAwaiting Tests
Coremjml-headAwaiting Tests
Coremjml-bodyAwaiting Tests
Coremjml-includeNot Implemented
Headmjml-attributesAwaiting Tests
Headmjml-classNot Implemented
Headmjml-allNot Implemented
Headmjml-breakpointAwaiting Tests
Headmjml-fontAwaiting Tests
Headmjml-html-attributesNot Implemented
Headmjml-previewAwaiting Tests
Headmjml-style☑️Partially Complete (Inline Support Required)
Headmjml-titleComplete
Bodymjml-accordionNot Implemented
Bodymjml-buttonAwaiting Tests
Bodymjml-carouselNot Implemented
Bodymjml-columnAwaiting Tests
Bodymjml-dividerAwaiting Tests
Bodymjml-groupAwaiting Tests
Bodymjml-heroAwaiting Tests
Bodymjml-imageAwaiting Tests
Bodymjml-navbarAwaiting Tests
Bodymjml-rawAwaiting Tests
Bodymjml-section☑️Partially Complete (Background Position Bug)
Bodymjml-socialAwaiting Tests
Bodymjml-spacerAwaiting Tests
Bodymjml-tableAwaiting Tests (AngleSharp Issue)
Bodymjml-textAwaiting Tests
Bodymjml-wrapperAwaiting Tests

Tests

Testing this project has been rather difficult due to the nature of the output. However, we're still trying to provide valuable tests for components which can validate correct output. For example, if we set the <mj-title> the outputted HTML document <title> should match.

Furthermore, this project will fall into the grey area of testing. Because of this, we'll rely heavily on bug reports from usage of MJML.NET.

Benchmark

We've benchmarked the main components of the library to make sure we're within a suitable execution speed. We'll continue monitoring the execution speed as part of project development. We benchmark based off the default MJML templates.

MethodMeanErrorStdDev
TryParseDocument37.64 ms2.538 ms7.483 ms
ParseDocument38.77 ms2.549 ms7.515 ms
ParseDocumentAsync38.24 ms2.157 ms6.360 ms

Contribution

We really appreciate any contribution to the project to help provide a native version of MJML to C#.

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Side Note: In your PR you should summarise your changes, bug fixes or general modifications.

Appreciations

Once again, it's good to share some appreciation to the projects that make MJML.NET possible.

License

MIT License

Copyright (c) 2020 Liam Riddell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository has been archived by the owner. It is now read-only.

Repository files navigation

IMPORTANT - DEPRECATED

Please view the new stable version of this project Mjml.Net.

MJML.NET

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Introduction

MJML is a markup language created by Mailjet and designed to reduce the pain of coding a responsive email. Its semantic syntax makes the language easy and straightforward while its rich standard components library shortens your development time and lightens your email codebase. MJML’s open-source engine takes care of translating the MJML you wrote into responsive HTML.

You can find out more about MJML 4 from the official website.

| Official Website | Official Documentation | Official Onboarding |

Usage

Firstly, you'll need to reference the MJML.NET NuGet Package into your project.

PM > Install-Package MjmlDotNet

Secondly, include MJML.NET namespace into your project.

usingMjmlDotNet;

Finally, the boilerplate code.

publicvoidMain(){// or DIIMjmlParsermjmlParser=newMjmlParser();stringmjml=@" <mjml> <mj-head> <mj-title>Hello World Example</mj-title> </mj-head> <mj-body> <mj-section> <mj-column> <mj-text> Hello World! </mj-text> </mj-column> </mj-section> </mj-body> </mjml>";stringhtml=mjmlParser.ParseDocument(mjmlString);}

Options

You can also specify options to the MJML parser. This can be done either at instantiation throught the defaultOptions parameter or at time of parsing the document. Both options are shown below.

publicvoidMain(){// 1. Default Options for every MJML documentMjmlParserOptionsdefaultOptions=newMjmlParserOptions(){Minify=true;Prettify=false;}IMjmlParsermjmlParser=newMjmlParser(defaultOptions);// Or 2. Override at per-document parsingMjmlParserOptionsoptions=newMjmlParserOptions(){Minify=true;Prettify=false;}stringhtml=mjmlParser.ParseDocument(mjml,options);}

Currently, we've not implemented all of the same options. This is because we're still introducing components and refactoring the project. However, the currently supported options are:

NameData TypeDefaultDescription
PrettifyBooleanFalsePrettifies the output when enabled.
MinifyBooleanTrueMinifies the output when enabled. This overrides Prettify as this would be ideal default in production environment.

Status

MJML.NET tries to implement all functionality 1-2-1 with the MJML 4 project. However, due to JavaScript not being a typed language this means there has been considerate refactoring to the code to make it more aligned with C# typed requirements.

As the project is currently still in experimental state not all MJML components have been added. Please see the below table for a list of all components and the current implementation state:

TypeComponentImplementedTestsState
CoremjmlAwaiting Tests
Coremjml-headAwaiting Tests
Coremjml-bodyAwaiting Tests
Coremjml-includeNot Implemented
Headmjml-attributesAwaiting Tests
Headmjml-classNot Implemented
Headmjml-allNot Implemented
Headmjml-breakpointAwaiting Tests
Headmjml-fontAwaiting Tests
Headmjml-html-attributesNot Implemented
Headmjml-previewAwaiting Tests
Headmjml-style☑️Partially Complete (Inline Support Required)
Headmjml-titleComplete
Bodymjml-accordionNot Implemented
Bodymjml-buttonAwaiting Tests
Bodymjml-carouselNot Implemented
Bodymjml-columnAwaiting Tests
Bodymjml-dividerAwaiting Tests
Bodymjml-groupAwaiting Tests
Bodymjml-heroAwaiting Tests
Bodymjml-imageAwaiting Tests
Bodymjml-navbarAwaiting Tests
Bodymjml-rawAwaiting Tests
Bodymjml-section☑️Partially Complete (Background Position Bug)
Bodymjml-socialAwaiting Tests
Bodymjml-spacerAwaiting Tests
Bodymjml-tableAwaiting Tests (AngleSharp Issue)
Bodymjml-textAwaiting Tests
Bodymjml-wrapperAwaiting Tests

Tests

Testing this project has been rather difficult due to the nature of the output. However, we're still trying to provide valuable tests for components which can validate correct output. For example, if we set the <mj-title> the outputted HTML document <title> should match.

Furthermore, this project will fall into the grey area of testing. Because of this, we'll rely heavily on bug reports from usage of MJML.NET.

Benchmark

We've benchmarked the main components of the library to make sure we're within a suitable execution speed. We'll continue monitoring the execution speed as part of project development. We benchmark based off the default MJML templates.

MethodMeanErrorStdDev
TryParseDocument37.64 ms2.538 ms7.483 ms
ParseDocument38.77 ms2.549 ms7.515 ms
ParseDocumentAsync38.24 ms2.157 ms6.360 ms

Contribution

We really appreciate any contribution to the project to help provide a native version of MJML to C#.

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Side Note: In your PR you should summarise your changes, bug fixes or general modifications.

Appreciations

Once again, it's good to share some appreciation to the projects that make MJML.NET possible.

License

MIT License

Copyright (c) 2020 Liam Riddell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

An unofficial port of MJML (by MailJet) to .NET Standard. This project is currently in an experimental state and should not be used in a production environment.

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Packages

Used by

Contributors

Languages