PhoenixKit.Email.Markdown (phoenix_kit v2.55.1)

Copy Markdown View Source

An email body written in Markdown, as HTML and as plain text.

PhoenixKit.Email.Content.resolve/5 uses this for a markdown part (markdown[.<locale>].md): the HTML body comes from it when the message has no html part, and the text body when it has no text part.

Placeholders

{{variable}} and {{{variable}}} work as in an html part: two braces escape the value, three insert it raw. They are substituted after the Markdown is rendered — a renderer percent-encodes {{url}} in a link target, so a value substituted before it would arrive as %7B%7Burl%7D%7D, and a value rendered as Markdown could change the markup around it. Each placeholder is swapped for an opaque token, the Markdown is rendered and sanitized (PhoenixKit.Utils.HtmlSanitizer), the placeholders are put back and substituted with PhoenixKit.Templates.Substitution.

Every link and image is built here rather than by the renderer, so its address is known after substitution:

  • The address is the link target with its placeholders filled in, raw or not — inside an attribute both spellings are escaped as an attribute value.
  • Only an http://, https:// or mailto: address (images: http(s) only) is kept. Anything else — javascript:, a relative path, a placeholder nothing bound — drops the link and keeps its label as text.
  • A paragraph that is exactly one [label](url) link becomes a button: a table cell in the accent colour, which renders the same in every email client. A bare address on its own line stays a link.
  • Other links are coloured with the accent colour.

The accent colour is the accent_color variable, checked by PhoenixKit.Email.Branding.normalize_color/1.

A paragraph that is only placeholders

A top-level paragraph of plain text whose placeholders all fill in blank — {{failed_attempts}} on its own line, with nothing to report — is left out of both bodies, rather than sent as an empty paragraph. A value that is a sentence ending in a blank line, written as its own paragraph, stays its own paragraph.

A paragraph that is exactly one {{{variable}}} is the value alone, with no <p> around it — the way to place a block of HTML a caller built (a table of invoice lines) between Markdown paragraphs. The text body substitutes it as is, so a caller that passes HTML that way gives the email a text part of its own.

Raw HTML

HTML written inside the Markdown is not rendered: a placeholder inside an attribute of it could not be checked like a link target. A body that needs markup of its own belongs in an html part.

Summary

Functions

markdown as a sanitized HTML fragment with variables substituted.

markdown as plain text with variables substituted.

Functions

to_html(markdown, variables)

markdown as a sanitized HTML fragment with variables substituted.

to_text(markdown, variables)

markdown as plain text with variables substituted.

Headings and paragraphs are lines separated by a blank line, list items start with - (1. when numbered), [label](url) becomes label: url — just url when the label is the address itself, as in [{{url}}]({{url}}) — an image becomes its alt text, and emphasis, code and raw HTML marks are dropped. A value that ends in blank lines never leaves more than one blank line in a row.