Skip to main content
Maizzle uses PostHTML for templating and transformations, and you can configure it or even register plugins that can further transform your HTML emails.

Options

PostHTML is configured under build.posthtml.options in your config.js.

directives

directives
array
default:"[]"
You can configure the PostHTML parser to correctly process custom directives.For example, you may tell it to ignore <?php ?> tags instead of treating them as HTML:
config.js
export default {
  posthtml: {
    options: {
      directives: [
        { name: '?php', start: '<', end: '>' },
      ]
    }
  }
}

xmlMode

xmlMode
boolean
default:"false"
Enable xmlMode if you’re using Maizzle to output XML content, and not actual HTML.
config.js
export default {
  posthtml: {
    options: {
      xmlMode: true,
    }
  }
}

decodeEntities

decodeEntities
boolean
default:"false"
Set this to true to have entities within the document decoded.
config.js
export default {
  posthtml: {
    options: {
      decodeEntities: true,
    }
  }
}

lowerCaseTags

lowerCaseTags
boolean
default:"false"
Set this to true to output all tags in lowercase. Works only when xmlMode is disabled.
config.js
export default {
  posthtml: {
    options: {
      lowerCaseTags: true,
    }
  }
}

lowerCaseAttributeNames

lowerCaseAttributeNames
boolean
default:"false"
Output all attribute names in lowercase.
This has a significant impact on speed.
config.js
export default {
  posthtml: {
    options: {
      lowerCaseAttributeNames: true,
    }
  }
}

recognizeCDATA

recognizeCDATA
boolean
default:"false"
Recognize CDATA sections as text even if the xmlMode option is disabled.
If xmlMode is enabled, CDATA sections will always be recognized as text.
config.js
export default {
  posthtml: {
    options: {
      recognizeCDATA: true,
    }
  }
}

recognizeSelfClosing

recognizeSelfClosing
boolean
default:"true"
If enabled, self-closing tags will trigger the onclosetag event even if xmlMode is disabled.
When xmlMode is enabled self-closing tags will always be recognized.
Maizzle sets this to true to ensure self-closing tags like those of Components are rendered correctly.
config.js
export default {
  posthtml: {
    options: {
      recognizeSelfClosing: true,
    }
  }
}

sourceLocations

sourceLocations
boolean
default:"false"
If set to true, AST nodes will have a location property containing the start and end line and column position of the node.
config.js
export default {
  posthtml: {
    options: {
      sourceLocations: true,
    }
  }
}

recognizeNoValueAttribute

recognizeNoValueAttribute
boolean
default:"true"
If set to true, PostHTML will render attributes with no values exactly as they were written and will not add ="" to them.
config.js
export default {
  posthtml: {
    options: {
      recognizeNoValueAttribute: true,
    }
  }
}

singleTags

singleTags
array
default:"[]"
Use the singleTags option to tell PostHTML to treat custom tags as self-closing.
This needs to be used in conjunction with closingSingleTag to tell PostHTML how to close the tag, otherwise you will end up with an unclosed tag.
config.js
export default {
  posthtml: {
    options: {
      singleTags: ['custom'],
      closingSingleTag: 'slash', // see docs below
    }
  }
}
You may then use the <custom /> tag as self-closing:
emails/example.html
<custom name="opencounter" type="tracking" />

closingSingleTag

closingSingleTag
string
default:"default"
Define the closing format for single tags.By default it will not close self-closing tags that it knows about:
emails/example.html
<img>
<p></p>
Available options:
Will add a closing tag.
config.js
export default {
  posthtml: {
    options: {
      singleTags: ['custom'],
      closingSingleTag: 'tag',
    }
  }
}
emails/example.html
<custom></custom>
Will add a closing slash.
config.js
export default {
  posthtml: {
    options: {
      singleTags: ['custom'],
      closingSingleTag: 'slash',
    }
  }
}
emails/example.html
<custom />

quoteAllAttributes

quoteAllAttributes
boolean
default:"true"
Disable if you want to remove quotes on all attributes.
config.js
export default {
  posthtml: {
    options: {
      quoteAllAttributes: false,
    }
  }
}
emails/example.html
<img src=example.jpg>

replaceQuote

replaceQuote
boolean
default:"true"
Replaces quotes in attribute values with &quote;.
config.js
export default {
  posthtml: {
    options: {
      replaceQuote: false,
    }
  }
}
emails/example.html
<!-- `true` (default) -->
<img src="<?php echo $foo[&quote;bar&quote;] ?>">

<!-- `false` -->
<img src="<?php echo $foo["bar"] ?>">

quoteStyle

quoteStyle
number
default:"2"
Specify the attribute value quotes style.
config.js
export default {
  posthtml: {
    options: {
      quoteStyle: 1,
    }
  }
}
emails/example.html
<!-- `2` (double quotes, default) -->
<img src="example.png" onload="testFunc("test")">

<!-- `1` (single quotes) -->
<img src='example.png' onload='testFunc("test")'>

<!-- `0` (based on attribute value) -->
<img src="example.png" onload='testFunc("test")'>

Plugins

plugins
array
default:"[]"
Register any PostHTML plugins that you would like to use, in the plugins array.You may register plugins to run either before all other plugins, or after all other plugins, by using the before and after keys.
config.js
import spaceless from 'posthtml-spaceless'

export default {
  posthtml: {
    plugins: {
      before: [
        spaceless()
      ]
    }
  }
}

Custom plugins

You may write your own PostHTML plugins, right in your Maizzle config.js file. For example, here’s a plugin that adds a random number to all <img> src URLs:
config.js
export default {
  posthtml: {
    plugins: {
      after: [
        (() => tree => {
          const process = node => {
            if (node.tag === 'img' && node.attrs?.src) {
              const randomNumber = Math.floor(Math.random() * 10 ** 16).toString().padStart(16, '0')
              node.attrs.src = node.attrs.src + `?v=${randomNumber}`
            }

            return node
          }

          return tree.walk(process)
        })()
      ]
    }
  }
}
Note that this is a naive example that doesn’t take existing query strings into account.

Built-in plugins

Maizzle already uses the following PostHTML plugins internally:

Build docs developers (and LLMs) love