v1.0.0 (2026-05-24)
Requires Elixir 1.15 or higher.
This release contains significant performance improvements, with typical HTML emails seeing a 30x+ speedup when inlining styles. Premailex is also now zero dependency thanks to the new fallback HTML parser Premailex.HTMLParser.Xmerl.
Architecture changes
The layers between parser, DOM operations, and the top-level API have been reshaped:
Premailex.HTMLParseris now a thin behaviour with onlyPremailex.HTMLParser.parse/1andPremailex.HTMLParser.to_html/1callbacksPremailex.DOMis a new module that handles all selector matching, traversal, and tree manipulationPremailex.Utilhas been removed with functions moved intoPremailex.DOMPremailex.HTMLInlineStyles.process/2is now a pure tree to tree transformation that accepts an explicit list of CSS rules
Breaking changes
Premailex.HTMLInlineStyles.process/3no longer exposed, usePremailex.HTMLInlineStyles.process/2Premailex.HTMLToPlainText.process/1no longer accepts HTML stringPremailex.HTMLParserbehaviour callbackto_stringrenamed toto_htmlPremailex.HTMLParserbehaviour no longer requiresall,filter, ortextcallbacksPremailex.HTMLParserno longer exposesparse, usePremailex.parse/2insteadPremailex.HTMLParserno longer exposesto_string, usePremailex.to_html/2insteadPremailex.HTMLParserno longer exposesall, usePremailex.DOM.all/2insteadPremailex.HTMLParserno longer exposesfilter, usePremailex.DOM.reject/2insteadPremailex.HTMLParserno longer exposestext, usePremailex.DOM.text_content/1insteadPremailex.Utilhas been removed:Premailex.Util.traverse/3is nowPremailex.DOM.replace_all_matches/3Premailex.Util.traverse_until_first/3is nowPremailex.DOM.replace_first_match/3Premailex.Util.traverse_reduce/3is removed, usePremailex.DOM.traverse_with_matching_items/3for indexed single-walk updates
- Renamed
Premailex.CSSParser.parse_rules/1toPremailex.CSSParser.parse_declaration_block/1 - Renamed
Premailex.CSSParser.merge/1toPremailex.CSSParser.cascade/1 Premailex.HTTPAdapter.request/5callback no longer requires thePremailex.HTTPAdapter.HTTPResponsestruct in favor of using a mapPremailex.parse/2now always returns a listFlokiminimum version bumped from~> 0.19to~> 0.24Premailex.to_inline_css/2:optimizeoption has been replaced by a single boolean option:remove_style_tags
Additions
- Added
Premailex.parse/2andPremailex.to_html/2 - Added support for
LazyHTML - Added fallback support for
:xmerl - Added
Premailex.CSSParser.split_selector_groups/1for selector group splitting - Added
Premailex.DOM.traverse_with_matching_items/3for indexed single-walk tree updates - Added support for structural pseudo-classes:
:first-child,:last-child,:only-child,:last-of-type,:only-of-type,:nth-child,:nth-of-type,:nth-last-child,:nth-last-of-type,:empty,:root(An+B,odd, andevenarguments supported)
Other
Flokiis now optionalPremailex.CSSParserrewritten and no longer uses regular expressions to parse CSSPremailex.CSSParser.parse_declaration_block/1now does case insensitive, terminal!importantdetectionPremailex.HTMLInlineStyles.process/2tree traversal performance changed from O(N^2) to O(N)- Fixed compiler warnings in
Premailex.HTMLParser.Meeseeks