Skip to main content

Architecture Overview

mjml-java is a pure Java MJML-to-HTML renderer. The core module has zero runtime dependencies beyond the JDK itself. It targets Java 17+ and ships as a multi-module Maven project with full JPMS (Java Platform Module System) support in the core module.

Design Principles

  • Zero dependencies -- only java.xml and java.logging from the JDK
  • Sealed type hierarchy -- BaseComponent is a sealed class, guaranteeing that every component is either a BodyComponent or a HeadComponent
  • Immutable configuration -- MjmlConfiguration is built once and safely shared across threads
  • Functional factories -- components are registered as ComponentFactory lambdas, enabling custom component injection without subclassing the registry
  • Thread safety -- static MjmlRenderer.render() methods create isolated pipeline and context instances per call

Module Declaration

module dev.jcputney.mjml {
requires java.xml;
requires java.logging;

exports dev.jcputney.mjml;
exports dev.jcputney.mjml.component;
exports dev.jcputney.mjml.context;
exports dev.jcputney.mjml.css;
exports dev.jcputney.mjml.parser;
}

Package Structure

dev.jcputney.mjml -- Public API

The top-level package contains the entry points and configuration:

ClassRole
MjmlRendererStatic render() methods -- the main entry point
MjmlConfigurationImmutable builder-pattern config (language, direction, includes, custom components, sanitization limits)
MjmlRenderResultHolds rendered HTML, document title, and preview text
IncludeResolverInterface for resolving mj-include paths to MJML source
FileSystemIncludeResolverFile-system implementation of IncludeResolver
MjmlExceptionBase exception for rendering failures
MjmlRenderExceptionThrown on unexpected errors during the render phase
MjmlParseExceptionThrown on malformed MJML input
MjmlValidationExceptionThrown on constraint violations (input size, nesting depth)
MjmlIncludeExceptionThrown when include resolution fails
ClasspathIncludeResolverClasspath implementation of IncludeResolver
ContentSanitizerOptional @FunctionalInterface for sanitizing inner HTML content
DirectionEnum for text direction: LTR, RTL, AUTO
ResolverContextRecord providing include chain metadata to IncludeResolver (including path, type, depth)

dev.jcputney.mjml.component -- Component Hierarchy

ClassRole
BaseComponentAbstract sealed base -- attribute resolution via 5-level cascade
BodyComponentAbstract base for components that produce HTML via render()
HeadComponentAbstract base for components that update GlobalContext via process()
ComponentRegistryMaps tag names to ComponentFactory instances; freezable after initialization
ComponentFactory@FunctionalInterface -- create(MjmlNode, GlobalContext, RenderContext)

dev.jcputney.mjml.context -- Rendering Context

ClassRole
GlobalContextDocument-wide state: fonts, styles, attributes, title, preview text, breakpoint, media queries, html-attributes
RenderContextPer-component state: container width, position among siblings (index, first, last)
AttributeResolverStateless utility implementing the 5-level attribute cascade

dev.jcputney.mjml.parser -- MJML Parsing

ClassRole
MjmlParserPreprocesses then parses MJML source into an MjmlDocument
MjmlPreprocessorWraps content tag bodies in CDATA for XML-safe parsing
MjmlDocumentContainer for the parsed head and body MjmlNode trees
MjmlNodeLightweight node representing an MJML element (tag, attributes, children, text)
IncludeProcessorExpands mj-include elements using the configured IncludeResolver
EntityTableMaps HTML entity names to characters for preprocessing

dev.jcputney.mjml.css -- CSS Inlining Engine

ClassRole
CssInlinerMatches CSS rules to HTML elements and merges styles into inline style attributes
HtmlDocumentParserLightweight position-tracking HTML parser (handles MSO conditionals)
HtmlElementMinimal DOM element with parent/child/sibling navigation and position tracking
CssParserTokenizes CSS text into CssRule and preserved at-rules
CssRuleA selector string + list of CssDeclaration values
CssSelectorSealed interface hierarchy for parsed CSS selectors
CssSelectorParserParses selector text into CssSelector AST
CssSelectorMatcherMatches CssSelector against HtmlElement nodes
CssSpecificity(a, b, c) tuple implementing CSS specificity comparison
CssDeclarationA single property: value pair with optional !important flag
StyleAttributeParses, merges, and serializes inline style attribute strings

dev.jcputney.mjml.render -- Rendering Pipeline

ClassRole
RenderPipelineOrchestrates the 7-phase rendering pipeline
HtmlSkeletonAssembles the complete HTML document (DOCTYPE, head, CSS resets, fonts, media queries, body)
DefaultFontRegistryMaps standard web font names to their <link> import URLs
FontScannerScans the component tree to auto-register default fonts
HtmlAttributeApplierApplies mj-html-attributes to the rendered body via CSS selector matching
VmlHelperGenerates VML markup for Outlook background images

dev.jcputney.mjml.util -- Utilities

ClassRole
CssBoxModelParses padding/border shorthand into top/right/bottom/left values
CssUnitParserConverts CSS units (px, %, em) to pixel values
HtmlEscaperEscapes attribute values and text content for safe HTML output
SocialNetworkRegistryMaps social network names to icon URLs and link templates
BackgroundCssHelperGenerates CSS background shorthand for section/hero backgrounds
BackgroundPositionHelperComputes VML origin/position values from CSS background-position
ColumnWidthCalculatorCalculates column widths accounting for padding, borders, and percentage/pixel units

Component Categories

The renderer supports all 31 standard MJML v4 components:

Head components (8): mj-head, mj-title, mj-preview, mj-font, mj-breakpoint, mj-style, mj-attributes, mj-html-attributes

Layout components (5): mj-body, mj-section, mj-column, mj-group, mj-wrapper

Content components (7): mj-text, mj-image, mj-button, mj-divider, mj-spacer, mj-table, mj-raw

Interactive components (11): mj-hero, mj-accordion, mj-accordion-element, mj-accordion-title, mj-accordion-text, mj-carousel, mj-carousel-image, mj-navbar, mj-navbar-link, mj-social, mj-social-element

Data Flow

See Rendering Pipeline for a detailed walkthrough of each phase, and CSS Inlining Engine for the CSS processing internals.