zalify / easy-email-editor

Easy Email Editor is a feature-rich, top open-source SaaS email editor based on React and MJML.
https://email.maocanhua.cn/
MIT License
1.64k stars 333 forks source link

[question] is it possible to avoid default attributes being applied, when using mjmlToJson? #310

Closed AlexBevilacqua closed 1 year ago

AlexBevilacqua commented 1 year ago

first of all, thank you all a lot, for your great work on this amazing editor!

to my issue.. I want to convert an existing mjml template to JSON, for using it in the builder. the template contains a section as simple as this:

<mj-section background-color="#dc0f0f">

but, after converting it to JSON, it gets a lot more attributes:

{
  "type": "section",
  "data": {
    "value": {
      "noWrap": false
    }
  },
  "attributes": {
    "background-repeat": "repeat",
    "background-size": "auto",
    "background-position": "top center",
    "border": "none",
    "direction": "ltr",
    "text-align": "center",
    "background-color": "#dc0f0f",
    "padding": "20px 0px 20px 0px"
  },
  "children": []
}

(this is just an example, I assume the same happens with all other type of elements/blocks)

I believe this happens here, basically: https://github.com/zalify/easy-email/blob/d0d65382c0e0cc11185db65f3829b78231153378/packages/easy-email-extensions/src/utils/MjmlToJson.ts#L132

due to the default attributes defined on the Block: https://github.com/zalify/easy-email/blob/d0d65382c0e0cc11185db65f3829b78231153378/packages/easy-email-core/src/blocks/standard/Section/index.tsx#L29-L64

is there a way to prevent all these defaults from being applied?

thank you in advance for any help!

m-Ryan commented 1 year ago

There is currently no such feature, and I don't know why the redundant attributes should be removed, since they can be displayed to the user for viewing.

If you want to add this feature, myabe only need to modify a few lines of code, if you are willing to provide a PR.

const blockData = applyDefaultAttributes ?  block.create(payload) : payload;
AlexBevilacqua commented 1 year ago

thank you for the tip @m-Ryan !

you're right, it probably doesn't make sense as a new "feature". if all that's doing is adding default attributes, just exactly how mjml would be doing under the hood, I agree it's better to show them explicitly, for the user to see them.

it was an issue for me, because I was implementing something to have the mj-head's mj-attributes "inlined" on the affected elements, but this would have been happening after the conversion to json, so, I can't tell at that point if the attributes were already in the template, or were mjml's defaults applied during the conversion.

for example:

<mjml>
  <mj-head>
    <mj-attributes>
      <mj-section padding="15px 15px" background-color="blue"/>
    </mj-attributes>
  </mj-head>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-text>
          Hello World!
        </mj-text>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

converted to json usnig MjmlToJson, the headAttributes are simply stored on the Page object ($.data.value.headAttributes) and nothing more happens with them I think? (except being editable in the source code box)

then, the section as json, will have

so, I'm wondering if I'm missing something, or if handling of the mj-attributes could be improved?

with the first option all attributes would be explicitly set, I would be fine with that, but maybe someone would prefer to be able to edit the mj-attributes in the source code, and see the changes propagated to all the matching elements.

with the second, based on the example, the inputs for the padding would stay empty to not interfere with the mj-attribute work-ability

what do you think? maybe I can help have something like this implemented..

edit. maybe something even better would be to not set attributes values, but show the default (whichever applies) as placeholder of the inputs

m-Ryan commented 1 year ago

There are two ways

  1. Parse the data of mj-attributes, and add blockAttributes to page, like { "section": {"background-color": "blue"} }, Merge when rendering.

{ type: "page", data: { value: { ... blockAttributes: { "section": {"background-color": "blue"} } } } }


2. Parse the data of mj-attributes, like `<mj-section padding="15px 15px" background-color="blue"/>`, temporarily store it as globalBlockAttributes, and merge the corresponding block in MjmlToJson.

```tsx

{
type: "section",
attributes: {
"background-color": "blue"
}
}

For now, I think the second will be less work

AlexBevilacqua commented 1 year ago

@m-Ryan thank you for these hints, and your support.. eventually I simply went for something like https://github.com/zalify/easy-email/issues/310#issuecomment-1540427896 (it's just a bit more complex than that)

I'm closing this, since I wouldn't really know what is best to do and how to do it (In the end I kinda like the placeholders idea, but it's also the most work probably, touching parts of the app I've never actually looked at, like obviously the attributes-panel)

If you anyways feel like some improvement is needed in this area, of course don't esitate to open another issue and copy over anything you think is worth porting there