Add last steps of contributing guide
This commit is contained in:
		
							
								
								
									
										233
									
								
								CONTRIBUTING.md
									
									
									
									
									
								
							
							
						
						
									
										233
									
								
								CONTRIBUTING.md
									
									
									
									
									
								
							@ -20,12 +20,15 @@ This file contains instructions on adding themes to Mailgen:
 | 
				
			|||||||
* [Creating a Built-In Theme](#creating-a-built-in-theme)
 | 
					* [Creating a Built-In Theme](#creating-a-built-in-theme)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
> We use Golang templates under the hood to inject the e-mail body into themes.
 | 
					> We use Golang templates under the hood to inject the e-mail body into themes.
 | 
				
			||||||
 | 
					> - [Official guide](https://golang.org/pkg/text/template/)
 | 
				
			||||||
 | 
					> - [Tutorial](https://astaxie.gitbooks.io/build-web-application-with-golang/en/07.4.html)
 | 
				
			||||||
 | 
					> - [Hugo guide](https://gohugo.io/templates/go-templates/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Using a Custom Theme
 | 
					### Using a Custom Theme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you want to supply your own **custom theme** for Hermes to use (but don't want it included with Mailgen):
 | 
					If you want to supply your own **custom theme** for Hermes to use (but don't want it included with Mailgen):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. Create a new struct implementing `Theme` interface ([hermes.go](hermes.go)). An real-life example is in [default.go](default.go)
 | 
					1. Create a new struct implementing `Theme` interface ([hermes.go](hermes.go)). A real-life example is in [default.go](default.go)
 | 
				
			||||||
2. Supply your new theme at hermes creation
 | 
					2. Supply your new theme at hermes creation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
@ -70,11 +73,11 @@ If you want to create a new **built-in** Mailgen theme:
 | 
				
			|||||||
1. Fork the repository to your GitHub account and clone it to your computer
 | 
					1. Fork the repository to your GitHub account and clone it to your computer
 | 
				
			||||||
2. Create a new Go file named after your new theme
 | 
					2. Create a new Go file named after your new theme
 | 
				
			||||||
3. Copy content of [default.go](default.go) file in new file and make any necessary changes
 | 
					3. Copy content of [default.go](default.go) file in new file and make any necessary changes
 | 
				
			||||||
6. Scroll down to the [injection snippets](#injection-snippets) and copy and paste each code snippet into the relevant area of your template markup
 | 
					4. Scroll down to the [injection snippets](#injection-snippets) and copy and paste each code snippet into the relevant area of your template markup
 | 
				
			||||||
7. Test the theme by running the `examples/*.js` scripts (insert your theme name in each script) and observing the template output in `preview.html`
 | 
					5. Test the theme by adding the theme to slice of tested themes (see [hermes_test.go](hermes_test.go)). A set of tests will be run to check that your theme follows features of Hermes.
 | 
				
			||||||
8. Take a screenshot of your theme portraying each example and place it in `screenshots/{theme}/{example}.png`
 | 
					6. Create examples in new folder for your theme in `examples` folder and run `go run *.go`. It will generate the different `html` and `plaintext` emails for your different examples. Follow the same examples as default theme (3 examples: Welcome, Reset and Receipt)
 | 
				
			||||||
9. Add the theme name, credit, and screenshots to the `README.md` file's [Supported Themes](README.md#supported-themes) section (copy one of the existing themes' markup and modify it accordingly)
 | 
					7. Add the theme name, credit, and screenshots to the `README.md` file's [Supported Themes](README.md#supported-themes) section (copy one of the existing themes' markup and modify it accordingly)
 | 
				
			||||||
7. Submit a pull request with your changes and we'll let you know if anything's missing!
 | 
					8. Submit a pull request with your changes and we'll let you know if anything's missing!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Thanks again for your contribution!
 | 
					Thanks again for your contribution!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -85,12 +88,12 @@ Thanks again for your contribution!
 | 
				
			|||||||
The following will inject either the product logo or name into the template.
 | 
					The following will inject either the product logo or name into the template.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<a href="<%- product.link %>" target="_blank">
 | 
					<a href="{{.Hermes.Product.Link}}" target="_blank">
 | 
				
			||||||
    <% if (locals.product.logo) { %>
 | 
					        {{ if .Hermes.Product.Logo }}
 | 
				
			||||||
        <img src="<%- product.logo %>" class="email-logo" />
 | 
					            <img src="{{.Hermes.Product.Logo}}" class="email-logo" />
 | 
				
			||||||
    <% } else { %>
 | 
					        {{ else }}
 | 
				
			||||||
        <%- product.name %>
 | 
					            {{ .Hermes.Product.Name }}
 | 
				
			||||||
    <% } %>
 | 
					        {{ end }}
 | 
				
			||||||
</a>
 | 
					</a>
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -107,7 +110,7 @@ It's a good idea to add the following CSS declaration to set `max-height: 50px`
 | 
				
			|||||||
The following will inject the e-mail title (Hi John Appleseed,) or a custom title provided by the user:
 | 
					The following will inject the e-mail title (Hi John Appleseed,) or a custom title provided by the user:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<%- title %>
 | 
					<h1>{{if .Email.Body.Title }}{{ .Email.Body.Title }}{{ else }}{{ .Email.Body.Greeting }} {{ .Email.Body.Name }},{{ end }}</h1>
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Intro Injection
 | 
					## Intro Injection
 | 
				
			||||||
@ -115,11 +118,13 @@ The following will inject the e-mail title (Hi John Appleseed,) or a custom titl
 | 
				
			|||||||
The following will inject the intro text (string or array) into the e-mail:
 | 
					The following will inject the intro text (string or array) into the e-mail:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<% if (locals.intro) { %>
 | 
					{{ with .Email.Body.Intros }}
 | 
				
			||||||
    <% intro.forEach(function (introItem) { -%>
 | 
					    {{ if gt (len .) 0 }}
 | 
				
			||||||
        <p><%- introItem %></p>
 | 
					        {{ range $line := . }}
 | 
				
			||||||
    <% }) -%>
 | 
					            <p>{{ $line }}</p>
 | 
				
			||||||
<% } %>
 | 
					        {{ end }}
 | 
				
			||||||
 | 
					    {{ end }}
 | 
				
			||||||
 | 
					{{ end }}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Dictionary Injection
 | 
					## Dictionary Injection
 | 
				
			||||||
@ -127,15 +132,16 @@ The following will inject the intro text (string or array) into the e-mail:
 | 
				
			|||||||
The following will inject a `<dl>` of key-value pairs into the e-mail:
 | 
					The following will inject a `<dl>` of key-value pairs into the e-mail:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<!-- Dictionary -->
 | 
					{{ with .Email.Body.Dictionary }} 
 | 
				
			||||||
<% if (locals.dictionary) { %>
 | 
					    {{ if gt (len .) 0 }}
 | 
				
			||||||
    <dl class="dictionary">
 | 
					        <dl class="body-dictionary">
 | 
				
			||||||
    <% for (item in dictionary) { -%>
 | 
					        {{ range $entry := . }}
 | 
				
			||||||
        <dt><%- item.charAt(0).toUpperCase() + item.slice(1) %>:</dt>
 | 
					            <dt>{{ $entry.Key }}:</dt>
 | 
				
			||||||
        <dd><%- dictionary[item] %></dd>
 | 
					            <dd>{{ $entry.Value }}</dd>
 | 
				
			||||||
    <% } -%>
 | 
					        {{ end }}
 | 
				
			||||||
    </dl>
 | 
					        </dl>
 | 
				
			||||||
<% } %>
 | 
					    {{ end }}
 | 
				
			||||||
 | 
					{{ end }}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It's a good idea to add this to the top of the template to improve the styling of the dictionary:
 | 
					It's a good idea to add this to the top of the template to improve the styling of the dictionary:
 | 
				
			||||||
@ -165,37 +171,55 @@ The following will inject the table into the e-mail:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<!-- Table -->
 | 
					<!-- Table -->
 | 
				
			||||||
<% if (locals.table) { %>
 | 
					{{ with .Email.Body.Table }}
 | 
				
			||||||
<table class="data-table" width="100%" cellpadding="0" cellspacing="0">
 | 
					{{ $data := .Data }}
 | 
				
			||||||
    <tr>
 | 
					{{ $columns := .Columns }}
 | 
				
			||||||
        <% for (var column in table.data[0]) {%>
 | 
					    {{ if gt (len $data) 0 }}
 | 
				
			||||||
        <th
 | 
					    <table class="data-wrapper" width="100%" cellpadding="0" cellspacing="0">
 | 
				
			||||||
            <% if(locals.table.columns && locals.table.columns.customWidth && locals.table.columns.customWidth[column]) { %>
 | 
					        <tr>
 | 
				
			||||||
                width="<%= table.columns.customWidth[column] %>"
 | 
					        <td colspan="2">
 | 
				
			||||||
            <% } %>
 | 
					            <table class="data-table" width="100%" cellpadding="0" cellspacing="0">
 | 
				
			||||||
            <% if(locals.table.columns && locals.table.columns.customAlignment && locals.table.columns.customAlignment[column]) { %>
 | 
					            <tr>
 | 
				
			||||||
                style="text-align:<%= table.columns.customAlignment[column] %>"
 | 
					                {{ $col := index $data 0 }}
 | 
				
			||||||
            <% } %>
 | 
					                {{ range $entry := $col }}
 | 
				
			||||||
        >
 | 
					                <th
 | 
				
			||||||
            <p><%- column.charAt(0).toUpperCase() + column.slice(1) %></p>
 | 
					                    {{ with $columns }}
 | 
				
			||||||
        </th>
 | 
					                        {{ $width := index .CustomWidth $entry.Key }}
 | 
				
			||||||
        <% } %>
 | 
					                        {{ with $width }}
 | 
				
			||||||
    </tr>
 | 
					                        width="{{ . }}"
 | 
				
			||||||
    <% for (var i in table.data) {%>
 | 
					                        {{ end }}
 | 
				
			||||||
    <tr>
 | 
					                        {{ $align := index .CustomAlignement $entry.Key }}
 | 
				
			||||||
        <% for (var column in table.data[i]) {%>
 | 
					                        {{ with $align }}
 | 
				
			||||||
        <td
 | 
					                        style="text-align:{{ . }}"
 | 
				
			||||||
            <% if(locals.table.columns && locals.table.columns.customAlignment && locals.table.columns.customAlignment[column]) { %>
 | 
					                        {{ end }}
 | 
				
			||||||
                style="text-align:<%= table.columns.customAlignment[column] %>"
 | 
					                    {{ end }}
 | 
				
			||||||
            <% } %>
 | 
					                >
 | 
				
			||||||
        >
 | 
					                    <p>{{ $entry.Key }}</p>
 | 
				
			||||||
            <%- table.data[i][column] %>
 | 
					                </th>
 | 
				
			||||||
 | 
					                {{ end }}
 | 
				
			||||||
 | 
					            </tr>
 | 
				
			||||||
 | 
					            {{ range $row := $data }}
 | 
				
			||||||
 | 
					            <tr>
 | 
				
			||||||
 | 
					                {{ range $cell := $row }}
 | 
				
			||||||
 | 
					                <td
 | 
				
			||||||
 | 
					                    {{ with $columns }}
 | 
				
			||||||
 | 
					                        {{ $align := index .CustomAlignement $cell.Key }}
 | 
				
			||||||
 | 
					                        {{ with $align }}
 | 
				
			||||||
 | 
					                        style="text-align:{{ . }}"
 | 
				
			||||||
 | 
					                        {{ end }}
 | 
				
			||||||
 | 
					                    {{ end }}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                {{ $cell.Value }}
 | 
				
			||||||
 | 
					                </td>
 | 
				
			||||||
 | 
					                {{ end }}
 | 
				
			||||||
 | 
					            </tr>
 | 
				
			||||||
 | 
					            {{ end }}
 | 
				
			||||||
 | 
					            </table>
 | 
				
			||||||
        </td>
 | 
					        </td>
 | 
				
			||||||
        <% } %>
 | 
					        </tr>
 | 
				
			||||||
    </tr>
 | 
					    </table>
 | 
				
			||||||
    <% } %>
 | 
					    {{ end }}
 | 
				
			||||||
</table>
 | 
					{{ end }}
 | 
				
			||||||
<% } %>
 | 
					 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It's a good idea to add this to the top of the template to improve the styling of the table:
 | 
					It's a good idea to add this to the top of the template to improve the styling of the table:
 | 
				
			||||||
@ -234,30 +258,40 @@ It's a good idea to add this to the top of the template to improve the styling o
 | 
				
			|||||||
The following will inject the action link (or button) into the e-mail:
 | 
					The following will inject the action link (or button) into the e-mail:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<!-- Action -->
 | 
					{{ with .Email.Body.Actions }}
 | 
				
			||||||
<% if (locals.action) { %>
 | 
					    {{ if gt (len .) 0 }}
 | 
				
			||||||
    <% action.forEach(function (actionItem) { -%>
 | 
					        {{ range $action := . }}
 | 
				
			||||||
        <p><%- actionItem.instructions %></p>
 | 
					        <p>{{ $action.Instructions }}</p>
 | 
				
			||||||
        <a href="<%- actionItem.button.link %>" style="color:<%- actionItem.button.color %>" target="_blank">
 | 
					        <table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0">
 | 
				
			||||||
            <%- actionItem.button.text %>
 | 
					            <tr>
 | 
				
			||||||
        </a>
 | 
					                <td align="center">
 | 
				
			||||||
    <% }) -%>
 | 
					                <div>
 | 
				
			||||||
<% } %>
 | 
					                    <a href="{{ $action.Button.Link }}" class="button" style="background-color: {{ $action.Button.Color }}" target="_blank">{{ $action.Button.Text }}</a>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                </td>
 | 
				
			||||||
 | 
					            </tr>
 | 
				
			||||||
 | 
					        </table>
 | 
				
			||||||
 | 
					        {{ end }}
 | 
				
			||||||
 | 
					    {{ end }}
 | 
				
			||||||
 | 
					{{ end }}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It's a good idea to add this to the top of the template to specify a fallback color for the action buttons in case it wasn't provided by the user:
 | 
					A good practice is to describe action in footer in case of problem when displaying button and CSS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<%
 | 
					{{ with .Email.Body.Actions }} 
 | 
				
			||||||
if (locals.action) {
 | 
					<table class="body-sub">
 | 
				
			||||||
    // Make it possible to override action button color (specify fallback color if no color specified)
 | 
					    <tbody><tr>
 | 
				
			||||||
    locals.action.forEach(function(actionItem) {
 | 
					    {{ range $action := . }}
 | 
				
			||||||
        if (!actionItem.button.color) {
 | 
					    <td>
 | 
				
			||||||
            actionItem.button.color = '#48CFAD';
 | 
					        <p class="sub">If you’re having trouble with the button '{{ $action.Button.Text }}', copy and paste the URL below into your web browser.</p>
 | 
				
			||||||
        }
 | 
					        <p class="sub"><a href="{{ $action.Button.Link }}">{{ $action.Button.Link }}</a></p>
 | 
				
			||||||
    });
 | 
					    </td>
 | 
				
			||||||
}
 | 
					    {{ end }}
 | 
				
			||||||
%>
 | 
					    </tr>
 | 
				
			||||||
 | 
					    </tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					{{ end }}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Outro Injection
 | 
					## Outro Injection
 | 
				
			||||||
@ -265,11 +299,13 @@ if (locals.action) {
 | 
				
			|||||||
The following will inject the outro text (string or array) into the e-mail:
 | 
					The following will inject the outro text (string or array) into the e-mail:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<% if (locals.outro) { %>
 | 
					{{ with .Email.Body.Outros }} 
 | 
				
			||||||
    <% outro.forEach(function (outroItem) { -%>
 | 
					    {{ if gt (len .) 0 }}
 | 
				
			||||||
        <p><%- outroItem %></p>
 | 
					        {{ range $line := . }}
 | 
				
			||||||
    <% }) -%>
 | 
					        <p>{{ $line }}</p>
 | 
				
			||||||
<% } %>
 | 
					        {{ end }}
 | 
				
			||||||
 | 
					    {{ end }}
 | 
				
			||||||
 | 
					{{ end }}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Signature Injection
 | 
					## Signature Injection
 | 
				
			||||||
@ -277,9 +313,9 @@ The following will inject the outro text (string or array) into the e-mail:
 | 
				
			|||||||
The following will inject the signature phrase (e.g. Yours truly) along with the product name into the e-mail:
 | 
					The following will inject the signature phrase (e.g. Yours truly) along with the product name into the e-mail:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<%- signature %>,
 | 
					{{.Email.Body.Signature}},
 | 
				
			||||||
<br />
 | 
					<br>
 | 
				
			||||||
<%- product.name %>
 | 
					{{.Hermes.Product.Name}}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Copyright Injection
 | 
					## Copyright Injection
 | 
				
			||||||
@ -287,30 +323,7 @@ The following will inject the signature phrase (e.g. Yours truly) along with the
 | 
				
			|||||||
The following will inject the copyright notice into the e-mail:
 | 
					The following will inject the copyright notice into the e-mail:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<%- product.copyright %>
 | 
					{{.Hermes.Product.Copyright}}
 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Go-To Action Injection
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
In order to support Gmail's [Go-To Actions](https://developers.google.com/gmail/markup/reference/go-to-action), add the following anywhere within the template:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```html
 | 
					 | 
				
			||||||
<!-- Support for Gmail Go-To Actions -->
 | 
					 | 
				
			||||||
<% if (locals.goToAction) { %>
 | 
					 | 
				
			||||||
    <script type="application/ld+json">
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        "@context": "http://schema.org",
 | 
					 | 
				
			||||||
        "@type": "EmailMessage",
 | 
					 | 
				
			||||||
        "potentialAction": {
 | 
					 | 
				
			||||||
            "@type": "ViewAction",
 | 
					 | 
				
			||||||
            "url": "<%- goToAction.link %>",
 | 
					 | 
				
			||||||
            "target": "<%- goToAction.link %>",
 | 
					 | 
				
			||||||
            "name": "<%- goToAction.text %>"
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "description": "<%- goToAction.description %>"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    </script>
 | 
					 | 
				
			||||||
<% } %>
 | 
					 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Text Direction Injection
 | 
					## Text Direction Injection
 | 
				
			||||||
@ -318,6 +331,6 @@ In order to support Gmail's [Go-To Actions](https://developers.google.com/gmail/
 | 
				
			|||||||
In order to support generating RTL e-mails, inject the `textDirection` variable into the `<body>` tag:
 | 
					In order to support generating RTL e-mails, inject the `textDirection` variable into the `<body>` tag:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<body dir="<%- textDirection %>">
 | 
					<body dir="{{.Hermes.TextDirection}}">
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								default.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								default.go
									
									
									
									
									
								
							@ -331,11 +331,11 @@ func (dt *Default) HTMLTemplate() string {
 | 
				
			|||||||
					{{ end }}
 | 
										{{ end }}
 | 
				
			||||||
					{{ end }}
 | 
										{{ end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <p>
 | 
					          <p>
 | 
				
			||||||
                      {{.Email.Body.Signature}},
 | 
					            {{.Email.Body.Signature}},
 | 
				
			||||||
                      <br>
 | 
					            <br>
 | 
				
			||||||
                      {{.Hermes.Product.Name}}
 | 
					            {{.Hermes.Product.Name}}
 | 
				
			||||||
                    </p>
 | 
					          </p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					{{ with .Email.Body.Actions }} 
 | 
										{{ with .Email.Body.Actions }} 
 | 
				
			||||||
					<table class="body-sub">
 | 
										<table class="body-sub">
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user