Giter Club home page Giter Club logo

Comments (7)

lucacasonato avatar lucacasonato commented on May 21, 2024 1

This seems like a great idea. We want to do the same for Deno (implement CSSStyleSheet and friends). See denoland/deno#13898.

I did a little investigating on this last week, and came to the conclusion that we'd likely want to use rust-cssparser, which led me to look into how parcel-css does CSS parsing internally, which then led me to the conclusion that the code in this repo is already 80% there towards implementing CSSOM.

The primary things I have found that need to be tackled to make this work:

  • Instead of just being able to parse and serialize entire sheets, one must also be able to parse serialize individual attributes / rules / media tags etc. This means Parse and ToCss would need to be exposed for more attributes.
  • Make sure the internal representation is high granularity enough for what CSSOM requires. Ie does one need to be able to differentiate between #ff0000 and rgb(255, 0, 0)?
  • Confirm that the way the printer serializes values matches the CSSOM spec (https://andreubotella.com/csswg-auto-build/cssom-1/#serializing-css-values).

from lightningcss.

devongovett avatar devongovett commented on May 21, 2024 1

Ah that's a nice idea... I'm not sure a full Rust implementation of CSSOM is necessary since the exposed structs here are already higher granularity. I was mainly looking at exposing it for the JS API. But implementing it in JS and using lower level bindings might be a nice idea.

from lightningcss.

devongovett avatar devongovett commented on May 21, 2024 1

Experimented with this a bit more on my side. A few complexities that will need to be handled:

  • Shorthand properties can be retrieved even when not explicitly set, if all longhands that they include are set. See https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-getpropertyvalue
  • Setting properties that are shorthands also affects the longhands, and visa versa. See https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-setproperty. We will need some metadata about which properties are related to one another.
  • Complexities with logical properties also potentially affecting physical properties.
  • Properties must be ordered. At the moment a DeclarationBlock splits declarations into two lists: one important and one normal. That reduces memory usage by avoiding an extra boolean per declaration, but you lose ordering information. Perhaps we can use smallbitvec for this like Firefox.
  • How to deal with lifetimes in Property and values when setting individual properties. Need to store the underlying string values somewhere as well at the moment in case something in the parsed value references them. Would be nice to only do this when necessary, or have an Owned version.

from lightningcss.

devongovett avatar devongovett commented on May 21, 2024

Instead of just being able to parse and serialize entire sheets, one must also be able to parse serialize individual attributes / rules / media tags etc. This means Parse and ToCss would need to be exposed for more attributes.

This makes sense. I think we can expose Parse / ToCss. That also means exposing Printer, which has some internal stuff in it at the moment that I would like the freedom to change in the future without causing breaking changes. So I'll probably do some refactoring there first.

Make sure the internal representation is high granularity enough for what CSSOM requires. Ie does one need to be able to differentiate between #ff0000 and rgb(255, 0, 0)?

Yeah. Firefox/Servo retains a reference to the original color string as written in addition to the parsed RGBA value. We could either do that, or perhaps have a different parsing mode that has enum variants for each color type. The current representation is optimized for memory usage which I found to have a big impact on performance, so we'll want to test a bit here.

Confirm that the way the printer serializes values matches the CSSOM spec

I think it should mostly, at least with minify set to false. One way to confirm this would be to run WPT. I think Deno has a way to do this already?

from lightningcss.

devongovett avatar devongovett commented on May 21, 2024

Another thing I found hard when attempting this before (#10) was that CSSOM is a mutable, reference-based API, which is a little at odds with the rust borrow checking system. For example, you can have a rule that is not attached to a stylesheet, or removed from a parsed stylesheet but retained by the JS garbage collector. One way to solve that would be to use Rc/RefCell for each rule, but this impacts performance in our main use case which is minification/compilation of entire stylesheets. So we'll need to figure out a way to have both. Any ideas there would be useful!

from lightningcss.

lucacasonato avatar lucacasonato commented on May 21, 2024

So for the Deno, we don't actually have any "live" bindings between Rust and JS. All our communication with Rust happens through "ops" which are essentially JS -> Rust RPC calls.

To implement this we'd have a couple of op_css_parse_stylesheet / op_css_parse_rule etc calls that return static representations of the parsed CSS structures. In JS we then take those static representations and bind them together into the CSSOM API with all of it's live bindings. If we want to do something like serialize a rule, we have two options: either do it ahead of time, during the initial parse, or we have a seperate op_css_serialize_rule op that takes the static representation of a rule as arguments and returns a string. The CSS ops are essentially pure functions, and all state is held in JS.

All that is to say, that for Deno's use case we don't actually need a full Rust implementation of CSSOM with live bindings and references and stuff. We only need the parse and serialize primitives. For a nice Rust API though, you'd probably need Rc<RefCell<>>'s indeed though.

from lightningcss.

lucacasonato avatar lucacasonato commented on May 21, 2024

Just dug into this some more, and just the existing parsers will not quite be enough I think. Parse a rule does not have an implementation in parcel_css AFAICT (only Parse a list of rules). parse_one_rule is what I was looking for :-)

from lightningcss.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.