Skip to content

Commit

Permalink
Getting ready for a real release
Browse files Browse the repository at this point in the history
  • Loading branch information
akoutmos committed Apr 15, 2022
1 parent dd41614 commit 3fb9e8c
Show file tree
Hide file tree
Showing 12 changed files with 378 additions and 24 deletions.
15 changes: 15 additions & 0 deletions .doctor.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
%Doctor.Config{
exception_moduledoc_required: true,
failed: false,
ignore_modules: [MjmlEEx],
ignore_paths: [],
min_module_doc_coverage: 40,
min_module_spec_coverage: 0,
min_overall_doc_coverage: 50,
min_overall_spec_coverage: 0,
moduledoc_required: true,
raise: false,
reporter: Doctor.Reporters.Full,
struct_type_spec_required: true,
umbrella: false
}
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: [akoutmos]
79 changes: 79 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: MJML EEx CI

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SHELL: sh

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
static_analysis:
name: Static Analysis
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Elixir
uses: erlef/setup-elixir@v1
with:
elixir-version: '1.13.3'
otp-version: '24.2'
- name: Restore dependencies cache
uses: actions/cache@v2
with:
path: deps
key: ${{ runner.os }}-mix-v2-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-v2-
- name: Install dependencies
run: mix deps.get
- name: Restore PLT cache
uses: actions/cache@v2
with:
path: priv/plts
key: ${{ runner.os }}-mix-v2-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-v2-
- name: Mix Formatter
run: mix format --check-formatted
- name: Check for compiler warnings
run: mix compile --warnings-as-errors
- name: Credo strict checks
run: mix credo --strict
- name: Doctor documentation checks
run: mix doctor

unit_test:
name: Run ExUnit tests
runs-on: ubuntu-latest

strategy:
matrix:
elixir:
- '1.13.3'
otp:
- '24.2'

steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Elixir
uses: erlef/setup-elixir@v1
with:
elixir-version: ${{ matrix.elixir }}
otp-version: ${{ matrix.otp }}
- name: Restore dependencies cache
uses: actions/cache@v2
with:
path: deps
key: ${{ runner.os }}-mix-v2-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-v2-
- name: Install dependencies
run: mix deps.get
- name: ExUnit tests
env:
MIX_ENV: test
run: mix coveralls.github
81 changes: 74 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
# MjmlEEx
<p align="center">
<img align="center" width="25%" src="guides/images/logo.svg" alt="MJML EEx Logo">
</p>

**TODO: Add description**
<p align="center">
Easily create beautiful email using <a href="https://mjml.io/" target="_blank">MJML</a> right from Elixir!
</p>

<p align="center">
<a href="https://hex.pm/packages/mjml_eex">
<img alt="Hex.pm" src="https://img.shields.io/hexpm/v/mjml_eex?style=for-the-badge">
</a>

<a href="https://github.com/akoutmos/mjml_eex/actions">
<img alt="GitHub Workflow Status (master)"
src="https://img.shields.io/github/workflow/status/akoutmos/mjml_eex/MJML%20EEx%20CI/master?label=Build%20Status&style=for-the-badge">
</a>

<a href="https://coveralls.io/github/akoutmos/mjml_eex?branch=master">
<img alt="Coveralls master branch" src="https://img.shields.io/coveralls/github/akoutmos/mjml_eex/master?style=for-the-badge">
</a>

<a href="https://github.com/sponsors/akoutmos">
<img alt="Support the project" src="https://img.shields.io/badge/Support%20the%20project-%E2%9D%A4-lightblue?style=for-the-badge">
</a>
</p>

<br>

# Contents

- [Installation](#installation)
- [Supporting MJML EEx](#supporting-mjml_eex)
- [Setting Up MJML EEx](#setting-up-mjml_eex)
- [Attribution](#attribution)

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `mjml_eex` to your list of dependencies in `mix.exs`:
[Available in Hex](https://hex.pm/packages/mjml_eex), the package can be installed by adding `mjml_eex` to your list of
dependencies in `mix.exs`:

```elixir
def deps do
Expand All @@ -15,6 +47,41 @@ def deps do
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/mjml_eex](https://hexdocs.pm/mjml_eex).
Documentation can be found at [https://hexdocs.pm/mjml_eex](https://hexdocs.pm/mjml_eex).

## Supporting MJML EEx

If you rely on this library to generate awesome looking emails for your application, it would much appreciated
if you can give back to the project in order to help ensure its continued development.

Checkout my [GitHub Sponsorship page](https://github.com/sponsors/akoutmos) if you want to help out!

### Gold Sponsors

<a href="https://github.com/sponsors/akoutmos/sponsorships?sponsor=akoutmos&tier_id=58083">
<img align="center" height="175" src="guides/images/your_logo_here.png" alt="Support the project">
</a>

### Silver Sponsors

<a href="https://github.com/sponsors/akoutmos/sponsorships?sponsor=akoutmos&tier_id=58082">
<img align="center" height="150" src="guides/images/your_logo_here.png" alt="Support the project">
</a>

### Bronze Sponsors

<a href="https://github.com/sponsors/akoutmos/sponsorships?sponsor=akoutmos&tier_id=17615">
<img align="center" height="125" src="guides/images/your_logo_here.png" alt="Support the project">
</a>

## Setting Up MJML EEx

After adding `{:mjml_eex, "~> 0.1.0"}` in your `mix.exs` file and running `mix deps.get`

With those in place, you should be all set to go!

## Attribution

- The logo for the project is an edited version of an SVG image from the [unDraw project](https://undraw.co/)
- The Elixir MJML library that this library builds on top of [MJML](https://github.com/adoptoposs/mjml_nif)
- The Rust MRML library that provides the MJML compilation functionality [MRML](https://github.com/jdrouet/mrml)
18 changes: 18 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Config

if Mix.env() != :prod do
config :git_hooks,
auto_install: true,
verbose: true,
hooks: [
pre_commit: [
tasks: [
{:cmd, "mix format --check-formatted"},
{:cmd, "mix compile --warnings-as-errors"},
{:cmd, "mix credo --strict"},
{:cmd, "mix doctor"},
{:cmd, "mix test"}
]
]
]
end
111 changes: 111 additions & 0 deletions guides/images/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions lib/engines/mjml.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ defmodule MjmlEEx.Engines.Mjml do
end

def handle_expr(state, marker, expr) do
encoded_code = Utils.encode_expression(marker, expr)
encoded_expression = "__MJML_EEX_START__:#{encoded_code}:__MJML_EEX_END__"
encoded_expression = Utils.encode_expression(marker, expr)

%{binary: binary} = state
%{state | binary: [encoded_expression | binary]}
Expand Down
21 changes: 17 additions & 4 deletions lib/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,31 @@ defmodule MjmlEEx.Utils do
General MJML EEx utils reside here for encoding and decoding
Elixir expressions in MJML EEx templates.
"""

@doc """
This function encodes the internals of an MJML EEx document
so that when it is compiled, the EEx expressions don't break
the MJML compiler.
"""
def encode_expression(marker, expression) do
Base.encode16("<%#{marker} #{Macro.to_string(expression)} %>")
end
encoded_code = Base.encode16("<%#{marker} #{Macro.to_string(expression)} %>")

def decode_expression(encoded_string) do
Base.decode16!(encoded_string)
"__MJML_EEX_START__:#{encoded_code}:__MJML_EEX_END__"
end

@doc """
This function finds all of the instances of of encoded EEx expressions
and decodes them so that when the EEx HTML template is finally
rendered, the expressions are executed as expected.
"""
def decode_eex_expressions(email_document) do
~r/__MJML_EEX_START__:([^:]+):__MJML_EEX_END__/
|> Regex.replace(email_document, fn _, base16_code ->
"#{decode_expression(base16_code)}"
end)
end

defp decode_expression(encoded_string) do
Base.decode16!(encoded_string)
end
end
Loading

0 comments on commit 3fb9e8c

Please sign in to comment.