@faire/mjml-react
Version:
React component library to generate the HTML emails on the fly
67 lines (66 loc) • 2.14 kB
JavaScript
import kebabCase from "lodash.kebabcase";
const DANGEROUSLY_SET_INNER_HTML = "dangerouslySetInnerHTML";
export function convertPropsToMjmlAttributes(props) {
const mjmlProps = Object.entries(props).reduce((mjmlProps, [prop, value]) => {
const mjmlProp = prop === DANGEROUSLY_SET_INNER_HTML ? prop : kebabCase(prop);
const mjmlValue = convertPropValueToMjml(mjmlProp, value);
if (mjmlValue === undefined || prop === "className") {
return mjmlProps;
}
if (prop === "mjmlClass") {
mjmlProps["mj-class"] = mjmlValue;
}
else {
mjmlProps[mjmlProp] = mjmlValue;
}
return mjmlProps;
}, {});
// className is a special prop used extensively in react in place of the html class attribute.
// mjml uses a different name (css-class) for the same thing.
const className = props.className;
if (typeof className === "string") {
mjmlProps["css-class"] =
typeof mjmlProps["css-class"] === "string"
? joinClassNames(mjmlProps["css-class"], className)
: className;
}
return mjmlProps;
}
const booleanToString = ["inline", "full-width", "fluid-on-mobile"];
const numberToPixel = [
"width",
"height",
"border-radius",
"border-width",
"background-size",
"padding",
"padding-top",
"padding-right",
"padding-bottom",
"padding-left",
"font-size",
"letter-spacing",
"line-height",
"icon-padding",
"text-padding",
"inner-padding",
];
function convertPropValueToMjml(name, value) {
// This assumes that all numbers will be pixels which might not always be the case
if (typeof value === "number" && numberToPixel.includes(name)) {
return `${value}px`;
}
if (typeof value === "boolean" && booleanToString.includes(name)) {
return name;
}
if (typeof value === "object" && value !== null) {
return value;
}
if (typeof value === "string") {
return value;
}
return;
}
function joinClassNames(...classNames) {
return classNames.join(" ").trim();
}