NV / CSSOM

Unmaintained! ⚠️ CSS Object Model implemented in pure JavaScript. Also, a CSS parser.
https://nv.github.io/CSSOM/docs/parse.html
MIT License
751 stars 99 forks source link

Preserve multiple definitions of the same property in the same rule? #16

Open papandreou opened 13 years ago

papandreou commented 13 years ago

It's not uncommon for CSS authors to take advantage of the fact that a browser must ignore a CSS property in its entirety if a parse error or unsupported token is encountered in the value. For example:

body {
    background-image: -moz-radial-gradient(center, #a8e936, #76a326);
    background-image: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 800, from(#a8e936), to(#76a326));
    background-image: -webkit-radial-gradient(center, #a8e936, #76a326);
}

If parsed and reserialized using CSSOM only the last of the three background-image properties will survive. In the project I'm working on it would be very desirable to be able to reconstruct the whole thing. I'm not sure if this falls within the scope of CSSOM -- but would it be possible to achieve that behavior somehow?

Best regards, Papandreou

NV commented 13 years ago

I fully understand your problem. I'm rewriting the parser in SAC-style. It will allow me to parse CSS into different object models, not just CSSOM. Like so:

body {
    background-image: -moz-radial-gradient(center, #a8e936, #76a326);
    background-image: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 800, from(#a8e936), to(#76a326));
    background-image: -webkit-radial-gradient(center, #a8e936, #76a326);
}

into

{
  "cssRules": [
    {
      "selectorText": "body",
      "style": {
        "0": {
          name: "background-image",
          value: "-moz-radial-gradient(center, #a8e936, #76a326)"
        },
        "1": {
          name: "background-image",
          value: "-webkit-gradient(radial, 50% 50%, 0, 50% 50%, 800, from(#a8e936), to(#76a326))"
        },
        "2": {
          name: "background-image",
          value: "-webkit-radial-gradient(center, #a8e936, #76a326);"
        },
        "length": 3,
        "background-image": [0, 1, 2]
      }
    }
  ]
}

Stay tuned!

papandreou commented 13 years ago

Awesome :). That'd be exactly what I need!

stef commented 13 years ago

yes, i have the same problem. would be awesome to have this.

NV commented 13 years ago

I don't think I'll fix it soon. If you want it ASAP you could override CSSStyleDeclaration.prototype.setProperty.

papandreou commented 13 years ago

I ended up hacking the CSS parser to continue with a new rule (with an identical selector) if it sees a property redefinition. Seems like that preserves the semantics: https://github.com/One-com/assetgraph/compare/9609d665b8c8e645d8f3...ee00c998754b15c75952#diff-0 (only the changes to lib/3rdparty/CSSOM/lib/parse.js are relevant, don't mind the other diffs).

Haven't looked into doing the opposite during serialization yet.

NV commented 13 years ago

@papandreou

img {
  border: none;
  border: 1px solid red;
}

serializes to

img {
  border: none;
}
img {
  border: 1px solid red;
}

The downside is it changes amount of selectors.

papandreou commented 13 years ago

@NV: Since I wrote the previous message I've patched the serialization code to do the inverse: https://github.com/One-com/assetgraph/blob/master/lib/3rdparty/CSSOM/lib/CSSStyleSheet.js#L77-L91

So your example now serializes to one rule with a single selector :)

Yes, it's still a hack, and in some corner cases it will collapse neighboring rules with the same selector that were separate originally, but the semantics are preserved and it seems to be adequate for my use case.

sveisvei commented 12 years ago

+1 for fixing this, using papandreou fork for now.

quaelin commented 12 years ago

+1 vote

papandreou commented 12 years ago

@quaelin: In the mean time you can npm install cssom-papandreou to use my hack.

quaelin commented 12 years ago

Thanks @papandreou, your fork is doing the trick. :)

sveisvei commented 12 years ago

Ive been using papandreou fork for some time as well, works great - love OS this way :)

tj commented 12 years ago

i definitely need this too. do you have the SAC thing open-sourced anywhere?

NV commented 12 years ago

No, I still haven’t released it.

tj commented 12 years ago

i ended up just whipping up https://github.com/visionmedia/node-css since I don't (currently at least) need completely parsed selectors / values

nc commented 12 years ago

+1 for merging in the pull request

ralyodio commented 11 years ago

This does not seem to have been merged yet. I tried using cssom-papandreou but that doesn't preserve multiple rules for same attribute.

andineck commented 11 years ago

I also need this. https://github.com/papandreou/CSSOM/tree/cssom-papandreou has fixed it, but it does not have the latest version of cssom. So I created another fork: https://github.com/intesso/CSSOM and created a pull request: https://github.com/NV/CSSOM/pull/53.

ryno1234 commented 11 years ago

Is there any fix or suggested work around to this yet? Thx!

superlc commented 8 years ago

vote +1 , this is very important when i use flex. such as

display:-webkit-box; display:-webkit-flex; display:flex;

papandreou commented 8 years ago

@superlc I recommend using postcss instead, unless it's important to work with the CSSOM api. Postcss doesn't have this limitation.