Integer type matcher is unanchored, so cellpadding="6px" (and "abc5") pass validation
Describe the bug
cellpadding and cellspacing are declared as integer, but the integer type matcher is unanchored /\d+/. Any string that contains a digit is treated as valid, including cellpadding="6px" and cellpadding="abc5".
The value is then copied unchanged onto the HTML <table>. cellpadding / cellspacing are HTML attributes that take a non-negative integer (pixels), not a CSS length. "6px" is invalid HTML; some email clients ignore it and you get no padding.
To Reproduce
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-table cellpadding="6px" cellspacing="2px">
<tr><td>x</td></tr>
</mj-table>
</mj-column>
</mj-section>
</mj-body>
</mjml>const mjml2html = require('mjml')
const { html, errors } = mjml2html(mjml)
console.log(errors)
// look for cellpadding="6px" in htmlAlso valid today, which should not be:
<mj-table cellpadding="abc5">Expected behavior
A valid-types error, matching the documented type (integer) and the HTML attribute:
Attribute cellpadding has invalid value: 6px for type IntegerBare integers (cellpadding="6") should still pass.
MJML environment
- MJML Version: current
master(also 4.x) - MJML tool used: Node
mjmlCLI /mjml2html
Email sending environment
N/A — this is a validator bug. The rendering risk is that "6px" is emitted as-is.
Affected email clients
N/A for the validator miss. Outlook’s Word engine and other strict parsers can ignore cellpadding="6px" entirely.
Additional context
Root cause is the integer matcher:
// packages/mjml-core/src/types/integer.js
this.matchers = [/\d+/]String.prototype.search / the type isValid() path only needs a digit somewhere in the value.
Suggested fix: anchor it, e.g. /^\d+$/. That matches the docs, HTML4/HTML5 (cellpadding is a non-negative integer), and what email clients actually honor.
mj-table cellpadding / cellspacing look like the only integer attributes, so the blast radius is small. Existing templates that compile cleanly with "6px" would start getting a validation error — which is the point.
Source: mjmlio/mjml