[BUG] CSS parser invalidly parses certain duplicate declarations
Question
Tested on latest dev branch commit 39be1e0. This problem occurred on one of my templates, so it's a real world issue. It took me about half a day to create this minified test case, so I hope it helps.
If you have a template with the following CSS:
<div id="gjs">
<style>
body {
font-family: Helvetica Neue;
}
body, span {
font: inherit;
}
body {
font-family: Helvetica Neue;
}
</style>
<span>Find</span>
</div>
A browser renders this correctly as such:
<img width="609" alt="screen shot 2018-04-20 at 3 14 01 pm" src="https://user-images.githubusercontent.com/331833/39075971-8307bb60-44ad-11e8-89ed-355801ac3c33.png">JSFiddle: https://jsfiddle.net/szLp8h4n/192/
But grapes renders it incorrectly:
<img width="863" alt="screen shot 2018-04-20 at 3 16 04 pm" src="https://user-images.githubusercontent.com/331833/39076015-c52c0726-44ad-11e8-8469-c6f0f327c3d9.png">JSFiddle: https://jsfiddle.net/szLp8h4n/194/
@artf this is another example where I would recommend not creating your own parser (though you call it a "traverser"), and simply rely on the browser's parser. E.g. it should not be necessary to create an internal cache of all components and styles, when the browser itself already has a DOM tree and all styling information etc can be retrieved on-demand once a component is selected. However, it would be too big of a change for grapes to do this for this particular issue. So in this case I would recommend investigating the cause of and fixing this particular case.
Do you have an idea what might cause this? If you don't have time to fix it I would like to fix it myself because this is a pressing issue on my side. But I would very much appreciate some hints what would get me started.
Thanks a ton <3
Answers (3)
when the browser itself already has a DOM tree and all styling information etc can be retrieved on-demand once a component is selected
Probably this is something I've tried to build before grapesjs, and to be honest, after few weeks of work I realized that the result was just a big, unmaintainable, unreliable, SLOW, piece of crap. Believe me Tom, keeping the state of such a big application inside the DOM, it's just not an option. And again, I'm using the browser's parser but the problem is just how the CSS state of rules is build.
BTW, GrapesJS before creating a new style rule checks if one, with same properties, already exists. If one is found, it updates its style, so this is what happens:
- The first
bodydeclaration is created and inserted inside the state:
[
// First rule
{
selectors: [], // <-- this one is used only for Selectors (classes)
selectorsAdd: 'body', // Additonal selectors
style: {...},
}
]
- Same for the second one
[
// First rule
{
selectors: [],
selectorsAdd: 'body',
style: {...},
},
// Second rule
{
selectors: [],
selectorsAdd: 'body, span', // different from the previous
style: {...},
}
]
- The next
bodydeclaration, is the same as the first one, therefore only its style will be updated
[
// First/Third rule
{
selectors: [],
selectorsAdd: 'body',
style: {...}, // style updated
},
// Second rule
{
selectors: [],
selectorsAdd: 'body, span',
style: {...},
}
]
So as you see the problem here is that the third rule is inserted inside the first one and this breaks the cascading principle. Probably, the quick & dirty solution would be to add some option which ignores all the checks and adds all rules inconditionally.
@artf it's surprising to me that this is slower because I thought the browser would be heavily optimized for this, but you definitely have more experience with this project so I'll trust in your judgement ;)
I'm definitely in favor of an option to just add all rules unconditionally. This makes sense to me because for me the browser is truth and there should be no need to do additional checking on top of what the browser tells you.
Would you like to do this or should I create a PR? If the latter, could you tell me where these checks are done? Is it really in this getter that you previously linked? I would expect the checks to be done outside of a getter.
I'd really appreciate a PR. I think the check would be ok inside the add method
Related Questions and Answers
Continue research with similar issue discussions.
Issue #4765
BUG: The documented way to parse @keyframes does not work
GrapesJS version[X] I confirm to use the latest version of GrapesJSWhat browser are you using? Chrome v107Describe the bug How to reproduce...
Issue #896
[BUG] Media query rules are overridden by class rules in canvas
Hi @artf , I've noticed an issue while testing one of my templates using different device configurations that supposed to trigger media que...
Issue #5618
BUG: Old Component script is not deleted on Import. Resulting in duplicate scripts
GrapesJS version [X] I confirm to use the latest version of GrapesJS What browser are you using? Edge v120.0.2210.121 Reproducible demo lin...
Issue #4434
BUG: CSS Parser's shape doesn't allow the CSS property to be defined more than once.
GrapesJS version[X] I confirm to use the latest version of GrapesJSWhat browser are you using? AnyReproducible demo link https://grapesjs.c...
Paid Plugins That Match This Issue
Curated by issue keywords and label relevance to help you ship faster.
Loading paid plugin recommendations...
Browse Plugin Categories
Jump directly to plugin category pages on the marketplace.