Can I import HTML directly?
Is there any possible way to import html as a template? I don't find any documentation about it.
I had a bit of a look trying to do the same thing, it looks like the JSON blocks > HTML is a one way street (I could be wrong but)
This is a good idea but something that is not supported (and most likely won't work on in the near future). As @CodyCodes95 mentioned, EmailBuilder.js JSON -> HTML is a one-way export.
If there are others that would be interested in building an HTML -> EmailBuilder.js JSON converter, that would be fantastic (but likely difficult).
any updates on this, anyone?
@jordanisip were you able to make progress on HTML -> JSON?
Here's a hack that I'm using somewhere to turn HTML into email-builder blocks. While it's lossy, this approach covers most usecases.
- Convert HTML to Markdown with something like mixmark-io/turndown
- Iterate Markdown lines and turn them into JSON blocks.
This snippet works for blocks of Markdown text interspersed by headings. Images, links etc. in text is copied as Markdown as-is, which e-mail builder has the ability to render. This can be tweaked to add support for more block types.
const markdownToVisualBlock = (markdown) => {
const lines = markdown.split('\n');
const blocks = [];
const idBase = Date.now();
let textBuf = [];
const createBlock = (type, props, style = {}) => ({
id: `block-${idBase + blocks.length}`,
type,
data: {
props,
style: {
padding: {
top: 16, bottom: 16, right: 24, left: 24,
},
...style,
},
},
});
const flushText = () => {
if (textBuf.length > 0) {
blocks.push(createBlock('Text', { markdown: true, text: textBuf.join('\n') }));
textBuf = [];
}
};
lines.forEach((line) => {
// Handle ATX headings (# Heading)
const heading = line.match(/^(#+)\s+(.*)/);
if (heading) {
flushText();
blocks.push(createBlock('Heading', {
text: heading[2],
level: `h${Math.min(heading[1].length, 6)}`,
}));
return;
}
// Handle Setext headings (===== or -----)
const trimmed = line.trim();
if (/^(=+|-+)$/.test(trimmed) && textBuf.length > 0) {
const lastLine = textBuf.pop();
if (lastLine.trim()) {
flushText();
blocks.push(createBlock('Heading', {
text: lastLine,
level: trimmed[0] === '=' ? 'h1' : 'h2',
}));
return;
}
textBuf.push(lastLine, line);
} else {
textBuf.push(line);
}
});
flushText();
return {
root: {
type: 'EmailLayout',
data: { childrenIds: blocks.map((b) => b.id) },
},
...Object.fromEntries(blocks.map((b) => [b.id, { type: b.type, data: b.data }])),
};
};