prevwong / craft.js

🚀 A React Framework for building extensible drag and drop page editors
https://craft.js.org
MIT License
7.67k stars 743 forks source link

MJML output question #669

Open rogueturnip opened 4 months ago

rogueturnip commented 4 months ago

Hi, Enjoy working with Craft, it's a nice upgrade over Grapes. I was wondering however, is there a plugin similar to grapesjs-mjml that would allow outputting MJML content? I'm even ok making the components to do this but am just curious how I could render on the screen but also have the MJML output available.

Thanks!

AstralBaby commented 4 weeks ago

The rendering process has nothing to do with the output. Essentially what you would do is, get the serialized state, loop through it and generate desired MJML tags (in a string) for each component. IE: (taken from gemini)

function craftjsToMjml(serializedState) {
  const state = JSON.parse(serializedState);
  let mjml = '<mjml>';

  const renderComponent = (component, parent) => {
    let componentMjml = '';
    const { type, props } = component;

    switch (type) {
      case 'Text':
        componentMjml = `<mj-text${props.align ? ` align="${props.align}"` : ''}>${props.text}</mj-text>`;
        break;
      case 'Column':
        componentMjml = `<mj-column${props.width ? ` width="${props.width}"` : ''}>`;
        component.children.forEach(childId => {
          const child = state.ROOT[childId];
          componentMjml += renderComponent(child, 'Column');
        });
        componentMjml += '</mj-column>';
        break;
      case 'Section':
        componentMjml = '<mj-section>';
        component.children.forEach(childId => {
          const child = state.ROOT[childId];
          componentMjml += renderComponent(child, 'Section');
        });
        componentMjml += '</mj-section>';
        break;
      case 'Button':
        componentMjml = `<mj-button href="${props.href}" background-color="${props.backgroundColor}" color="${props.color}">${props.text}</mj-button>`;
        break;
      case 'Image':
        componentMjml = `<mj-image src="${props.src}" alt="${props.alt}" />`;
        break;
      // Add more component types as needed
      default:
        console.warn(`Component type "${type}" not supported.`);
    }

    return componentMjml;
  };

  state.ROOT.root.children.forEach(childId => {
    const child = state.ROOT[childId];
    mjml += renderComponent(child, 'root');
  });

  mjml += '</mjml>';
  return mjml;
}