Breaking changes
CSS inlining and purging now on by default
css.inline and css.purge now default to true. Most email projects will need them on anyway.
If your project relies on either being off, set them explicitly:
// maizzle.config.ts
export default defineConfig({
css: {
inline: false,
purge: false,
},
})Shorthand CSS and prettify also on by default
Same story for css.shorthand and html.format. Output is now compact (shorthand) and pretty-printed by default.
build() options flattened
The programmatic build() API used to take a wrapped options object:
// before
await build({ config: { css: { inline: true } } })
await build({ config: './my.config.ts' })Now it takes the config directly:
// after
await build({ css: { inline: true } })
await build('./my.config.ts')
await build() // loads maizzle.config.ts from cwd<Divider> renamed to <Hr>
Even if it's a <div> for compatibility reasons, it basically does what an <hr> does. Plus, API parity with React Email.
New features
Per-template transformer toggles
New useTransformers() composable lets you control the transformer pipeline from inside a single template, no need to touch maizzle.config.ts:
<script setup>
useTransformers(false)
</script>Or pass an object for granular control:
<script setup>
// Skip specific transformers for this template
useTransformers({ inlineCSS: false, prettify: false })
// Force-enable transformers that are off globally
useTransformers({ minify: true })
</script>The same shape is now accepted on the global config too:
export default defineConfig({
useTransformers: {
inlineCSS: false,
minify: true,
},
})Force-enable (true) only applies to boolean-driven transformers (inlineCSS, purgeCSS, prettify, minify, shorthandCSS, sixHex, safeClassNames, entities).
useBaseUrl() and useUrlQuery() composables
Set url.base and url.query from inside a single template:
<script setup>
useBaseUrl('https://cdn.example.com/emails/')
useUrlQuery({ utm_source: 'maizzle', utm_campaign: 'newsletter' })
</script>Layouts for Markdown templates
.md templates are now wrapped in a built-in MarkdownLayout automatically — you get a complete email document (<html>, <head>, MSO/VML fallback, body shell, plus a centered <Container class="max-w-xl">) without writing any boilerplate.
Choose a different layout via frontmatter:
---
layout: Layout
title: Welcome
---
# Hello!Set layout: false to opt out entirely. The whole frontmatter object is passed to the wrapping component as the :frontmatter prop, so custom layouts can read whatever you put in.
<Button> icon alt + Outlook spacing
<Button> got three new props:
iconAlt— alt text for the icon imagemsoPx— controls horizontal padding in old Outlook (asmso-font-widthpercentage on the spacer<i>elements)outlookFallback— toggle MSO/VML fallback markup off for this button
<Button href="#" icon="https://example.com/arrow.png" icon-alt="Arrow" :mso-px="200">
Continue
</Button><Container> MSO styling
<Container> got two new props:
msoStyle— inline CSS applied only to the MSO<td>(handy for Outlook-only padding)outlookFallback— same toggle as above
<Container mso-style="padding: 10px 20px">
...
</Container><Preheader> simplified
fillerCount and shyCount props were merged into a single spaces prop, and the filler character sequence was unified to  ͏ per repetition:
<Preheader :spaces="200">Short preview.</Preheader>Command palette improvements
- Email search now matches parent directory names too —
app/welcomematchesap w - Token search is order-independent —
welcome appfinds the same file asapp welcome - Result count shown in the footer
Fixed
useEvent()registered in.vueand.mdtemplates didn't actually fire — handlers are now collected during render and run alongside config-level handlersuseTransformers()composable was clobbering global config defaults instead of mergingMarkdownLayoutfailed when the user's project had nocomponents/directory — components are now imported explicitly<Layout>body's MSO XML block (<o:OfficeDocumentSettings>,<w:WordDocument>) is now preserved verbatim instead of being mangled by Vue's template parser.jsdist files are now emitted alongside.d.tsfiles
Changed
- Prettify is automatically skipped when
minifyis enabled — they cancel each other out, no point running both - MSO placeholder transformers (column widths, container widths, td styles) unified under a single pass
Full commits list:
- chore: update skill 2c7a78f
- perf: skip prettify when minify is enabled 4437560
- feat: useBaseUrl and useUrlQuery composables b3b44e7
- feat!: shorthand CSS and prettify on by default 853600b
- feat: useTransformers true keys force-enable transformers 1350acb
- fix: useTransformers composable dropping config defaults a6e086b
- feat!: inline CSS and purge by default 7d39219
- fix: emit .js dist files paired with .d.ts e7ee410
- feat: granular useTransformers toggle 48774f5
- refactor!: flatten build() options d019416
- chore: move @vitest/coverage-v8 to devDependencies d5cb610
- fix: explicit component imports in MarkdownLayout 8996aca
- refactor: unify mso placeholders transformers d4b9ae7
- refactor: container component bd5f57b
- fix: useEvent composable in templates a43edc8
- feat: add layout support for markdown templates 6a57364
- refactor: rename Divider component to Hr 4bf6a8c
- feat: useTransformers composable to disable pipeline per template d6e42c7
- refactor: Button component 5cbcf64
- feat: order-independent token search in command palette c47b538
- refactor: unify Preheader filler entities under
spacesprop 92d6fe0 - feat: show result count in command palette footer 5c67ad2
- fix: preserve Outlook XML markup verbatim in Layout body ab3ec36
- feat: match parent dirs in command palette email search 0fbc2ac
- fix: preserve Outlook XML block in Layout body 25aebf8
- chore: add jsdoc for outlookFallback prop ff842ec