andcmatias / grapesjs-code-editor

GrapesJS plugin Code Editor using Monaco Editor
7 stars 1 forks source link

plugin forgets CSS content when HTML content is applied #2

Closed pety-dc closed 1 year ago

pety-dc commented 1 year ago

I tried this plugin as a replacement for grapesjs-component-code-editor.

Unfortunately I bumped into a bug: When I click on the apply button in the HTML section every CSS content that was previously in the CSS section gets dismissed.

It can be tried in the Demo: https://codepen.io/Anderson-Caldeireiro-Matias/pen/jOXrvgJ Add a Text component which naturally has a 10px padding and try to edit the HTML content with the side panel. After applying, the padding gets dismissed.

pety-dc commented 1 year ago

@andcmatias I've dug down and found that the root of the problem is in this part of updateHtml:

this.cssMonacoEditor .getValue() .split('}\n') .filter((el) => Boolean(el.trim())) .map((cssObjectRule) => { if (!(/}$/.test(cssObjectRule))) { //* Have to check closing bracket existence for every rule cause it can be missed after split and add it if it doesnt match return '${cssObjectRule}}'; } }) .forEach(rule => { if (/^#/.test(rule)) idStyles += rule; });

A single css rule defintion never gets past the map method. Instead the map returns an array with undefined value. (Probably the same thing happens with the last, if there should be more than 1 rule definition.)

In your plugin the css editor field doesn't necessarily have a newline character after the last rule definition. Thus the split doesn't split the css rule definition to a rule definition with a missing closing bracket. But keeps the css rule definion as a whole. The map method then founds the full css definition and returns nothing. (Otherwise it should readd the closing brackits which gets removed by split)

Your plugin shows similarities with grapesjs-component-code-editor. I'm not quote sure, but The updateHtml method there works fine beacause there the css editor field always has a newline after the css definition.

Adding a return for css rule definitions that doesn't miss closing brackets should fix the problem.

this.cssMonacoEditor .getValue() .split('}\n') .filter((el) => Boolean(el.trim())) .map((cssObjectRule) => { if (!(/}$/.test(cssObjectRule))) { //* Have to check closing bracket existence for every rule cause it can be missed after split and add it if it doesnt match return '${cssObjectRule}}'; } return cssObjectRule; }) .forEach(rule => { if (/^#/.test(rule)) idStyles += rule; });

andcmatias commented 1 year ago

@andcmatias I've dug down and found that the root of the problem is in this part of updateHtml:

this.cssMonacoEditor .getValue() .split('}\n') .filter((el) => Boolean(el.trim())) .map((cssObjectRule) => { if (!(/}$/.test(cssObjectRule))) { //* Have to check closing bracket existence for every rule cause it can be missed after split and add it if it doesnt match return '${cssObjectRule}}'; } }) .forEach(rule => { if (/^#/.test(rule)) idStyles += rule; });

A single css rule defintion never gets past the map method. Instead the map returns an array with undefined value. (Probably the same thing happens with the last, if there should be more than 1 rule definition.)

In your plugin the css editor field doesn't necessarily have a newline character after the last rule definition. Thus the split doesn't split the css rule definition to a rule definition with a missing closing bracket. But keeps the css rule definion as a whole. The map method then founds the full css definition and returns nothing. (Otherwise it should readd the closing brackits which gets removed by split)

Your plugin shows similarities with grapesjs-component-code-editor. I'm not quote sure, but The updateHtml method there works fine beacause there the css editor field always has a newline after the css definition.

Adding a return for css rule definitions that doesn't miss closing brackets should fix the problem.

this.cssMonacoEditor .getValue() .split('}\n') .filter((el) => Boolean(el.trim())) .map((cssObjectRule) => { if (!(/}$/.test(cssObjectRule))) { //* Have to check closing bracket existence for every rule cause it can be missed after split and add it if it doesnt match return '${cssObjectRule}}'; } return cssObjectRule; }) .forEach(rule => { if (/^#/.test(rule)) idStyles += rule; });

@pety-dc

Thank you for your collaboration. I have already made the correction as per your recommendation. I had not tested changing the CSS from within the HTML code before. The code is very similar to grapesjs-component-code-editor because I took the same one that is not being updated and modified it to use the Monaco Editor. In the code, when the wrapper is selected, I list all the styles that exist. When a component is selected, I list all its styles and those of its children. I also made a correction in the updateCss, which was saving incorrectly. I am a beginner in GrapesJs, learning, and have already created many plugins that I am using. I created plugins for bootstrap5, slider, accordions, tabs, among others. I am developing a program for creating landing pages where there are two modes of editing. The Advanced Mode allows changing all the HTML and CSS, while the Basic Mode allows changing only colors and images, as defined in my settings. In the Basic Mode, I list the options that can be changed in the Layer Manager, and to control the Layer Manager, I have to work with an observer because it keeps closing as you select different options.