Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a layout engine #1322

Open
probablyup opened this issue Dec 16, 2015 · 20 comments
Open

Implement a layout engine #1322

probablyup opened this issue Dec 16, 2015 · 20 comments
Labels
css feature layout Blocked on implementing a layout engine

Comments

@probablyup
Copy link
Contributor

I was taking a look at https://github.com/facebook/css-layout and it seems fairly complete.

A layout engine is I think the last major piece of the puzzle that JSDOM needs. I know it's a bit of an undertaking...

@domenic
Copy link
Member

domenic commented Dec 16, 2015

It only does flexbox though, not e.g. relative or absolute or static positioning.

@Sebmaster
Copy link
Member

css-layout only implements flexbox. It'd not even be possible to parse only newly developed sites people are trying to parse with jsdom. We talked about implementing a layouting engine at jsconf.eu - the will is there, but priority definitely isn't.

The problem is, when you start going down that rabbit hole there's a lot to consider - we'd have to include font rendering (or at least font width measurement) to get even the simplest websites to work. All those things could be a bit reduced (for example only emulating a monospace font), but they're nontheless there and there won't be any correct results without taking all that into consideration.

@inikulin
Copy link
Contributor

Can't it be accomplished with native deps like Skia? It's not the best option, but it can be made as an optional extension (like node-canvas at the moment).

@probablyup
Copy link
Contributor Author

@domenic It says on the README they support absolute, relative and static positioning. The absence of the other display types is annoying though

@probablyup
Copy link
Contributor Author

There's also this one: https://github.com/tategakibunko/nehan.js, though the docs are a little cryptic.

@Sebmaster
Copy link
Member

nehan.js:

Available on IE8+, Firefox3.5+, Google Chrome4+, Safari3+, Opera10+ etc.

Makes me think they're using dom methods to render that stuff, which makes it useless to implement rendering.

absolute, relative and static

That's the simple ones, but doesn't take into account overflows, etc. It basically only supports boxes and doesn't take into account their contents (which are a big deal on the web though).

@probablyup
Copy link
Contributor Author

@Sebmaster I haven't looked too deep into it, but IE8+ could be due to using certain ES3-5+ things that the older browsers didn't support.

@inikulin
Copy link
Contributor

Well, implementing layout engine seems like an interesting hobby task for years =) So, I decided to give it a try when things will settle down a bit with my primary projects. Meanwhile, I've decided to improve my knowledge on internals by reading CSS spec (interesting reading BTW) and made some basic research. Regarding font measurement: seems like we can do it already without native code.
We have opentype.js for fonts parsing. It can give us SVG path for the given text with the given font. From path we can get text BBox (example implementation in Raphael: https://github.com/DmitryBaranovskiy/raphael/blob/master/dev/raphael.core.js#L1592)

@inikulin
Copy link
Contributor

On the other hand, for layouting we will need somekind of threading, since it's a lot of computation. But still there is nothing like that in JS. As far as I remember, I've seen some discussion regarding some kind of threading model in TC39 notes, but seems like it take years to take it to the actual implementation (I believe @domenic can tell more). The sad part is that we don't have any reliable alternatives.

@inikulin
Copy link
Contributor

P.s. merry xmas 🎅

@Joris-van-der-Wel
Copy link
Member

WebWorker + Transferable objects is probably the best bet for now. jsdom also runs in other browsers so any node specific feature would not be appropriate.

@inikulin
Copy link
Contributor

We don't have WebWorkers in Node. It will require native extension.

@Joris-van-der-Wel
Copy link
Member

I know, however we can extend node ourselves. Extending all the browsers is harder.

Being able to render to canvas would be nifty, browser inception

lencioni added a commit to Galooshi/happo that referenced this issue Nov 16, 2016
We want to start writing unit tests to ensure robustness and good test
speed. This module seems like a logical place to start.

We ran into an issue with jsdom returning all 0 values from
getBoundingClientRect() so we had to mock it out. This will probably be
the case until jsdom gets a layout engine.

  jsdom/jsdom#1322

Our current createElement function is pretty rudimentary and will likely
need to be adjusted as we flesh out our tests here, particularly with
nested examples.

Likewise, we also discovered a difference in how jsdom treats
getComputedStyle. In the browser, all valid properties are represented
but in jsdom, only the properties that have been explicitly set are
represented. This means that getting the property value of a computed
style that was not explicitly set (e.g. margin in our example) will
return '0px' in a browser, but '' in jsdom. Since we pass this value
straight into parseFloat, we were seeing NaN instead of 0. We fixed this
by having our getPropertyValue calls fall back to 0.
@domenic domenic added the css label Aug 24, 2017
@guidobouman
Copy link

The layout engine is not going to happen anytime soon, or is it?

@Sebmaster
Copy link
Member

The layout engine is not going to happen anytime soon, or is it?

No.

@guidobouman
Copy link

guidobouman commented Apr 12, 2018

How about https://github.com/trevorlinton/webkit.js? :trollface:

On a bit more serious note: was work on this ever started? Or is this something jsdom is just not designed to do, and should we get Headless Chrome instead?

I think I can guess the answer, but I'm wondering if putting energy in this direction could actually help.

@Sebmaster
Copy link
Member

On a bit more serious note: was work on this ever started?

Not really, I think the current state of affairs is that it'd be way to slow to actually productively use, although it's never been tried and would make for interesting results in any case.

@domenic
Copy link
Member

domenic commented Apr 12, 2018

I think it would be roughly a full-time job for 3-6 months for a very talented engineer. But, I think it could be done, and the result would probably be pretty fast actually.

But yeah, realistically this is probably not going to happen :)

@guidobouman
Copy link

Just acting really naive here, but what if this was sponsored by browser vendors? Would this give jsdom advantages over Headless Chrome + Puppeteer? I think it would, right? As the bridge would be a lot smaller.

@nicoburns
Copy link

nicoburns commented May 16, 2023

If WASM is acceptable then https://github.com/DioxusLabs/taffy (disclosure: I maintain this library) implements Flexbox, CSS Grid, and is about to land Block layout. However inline (so text), inline-block, and float layout would still need to be implemented on top of this.

(btw, I found this issue because I'm looking to use such an integration from the other side: test my layout engine by running WPT tests under jsdom. For this use case I don't actually need full text layout as the WPT tests use the https://github.com/Kozea/Ahem font which has extremely simple metrics)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css feature layout Blocked on implementing a layout engine
Projects
None yet
Development

No branches or pull requests

8 participants