jonathanKingston / wurst

prelim implementation of macro dom
https://crates.io/crates/wurst/
8 stars 0 forks source link

Schinken #21

Open killercup opened 6 years ago

killercup commented 6 years ago

Hi! Over the weekend I played around a bit with web-sys, and make this small thing. In reponse, @ashleygwilliams just pointed your repo out to me! As you can see, I've immediately renamed my crate ๐Ÿ˜…

Seriously though, Wurst seems to be focussed on creating elements right now. Or at least none of the examples show anything about selecting elements and dealing with NodeLists and such.

Feel free to copy anything from my repo you want. I have no ambition (or time) to make this a solid library, but maybe (hopefully) you do!

jonathanKingston commented 6 years ago

Hahah amazing name and thanks @ashleygwilliams!

Yeah I have been working on a Todo MVC app implementation at the moment in basic wasm-bindgen which is helping me iron out the needs for this lib.

Seriously though, Wurst seems to be focussed on creating elements right now. Or at least none of the examples show anything about selecting elements and dealing with NodeLists and such.

This is true, I did have a plan here though. I was expecting to use my tag list lookup for the interfaces to make a consuming iterator to map into wurst::El's which should be the cheapest at runtime whilst also giving a clean interface to use.

Essentially the API I'm looking for is:

let body = wurst::body();
let els = body.querySelectorAll("a");
for el in els {
  el.href = "http://blah.com/";
}
els.flush(); // flush those attr changes to the DOM.

or

let body = wurst::body();
let els = body.querySelectorAll("a");
for el in els {
  el.set_href("http://blah.com/");
}

Feel free to copy anything from my repo you want. I have no ambition (or time) to make this a solid library, but maybe (hopefully) you do!

Yeah I totally do, I just don't want to rush it at the moment. I also want to generate as much as possible so it mostly will update as the web does.

I'll take another look over your code tomorrow when more awake, I just wanted to highlight I had seen your post. I'm keen to integrate efficient low level solutions that speed up making a basic web app certainly. Thanks

killercup commented 6 years ago

Sound great, Jonathan! What does your querySelectorAllยน yield? I.e., how to ensure that the items in that iterator actually have a href to set? Basically the only design Schinken currently has is to use type parameters to call JsCast in the necessary places.

ยน Please call it something more concise ๐Ÿ™ˆ

jonathanKingston commented 6 years ago

Sorry the examples should have been (slipped back into JS land):

let body = wurst::body();
let els = body.query_selector_all("a");
for item in els {
      item.el.href = "http://blah.com/";
}
els.flush(); // flush those attr changes to the DOM.

or

let body = wurst::body();
let els = body.query_selector_all("a");
for item in els {
      item.map(|el| {
          el.set_href("http://blah.com/");
      });
}

The return would be something like:

IntoIterator<wurst::ElList>

And yielding them should produce: El<AElement> after checking the tag name in HTML (this is the simplest implementation I can think of and safest). The signature will likely use my enum which holds all the interfaces: wurst::elements::InterfaceType which contains variants like: A(Box<El<AElement>>)

The wurst El's wrap the interface in an Elementish trait and also holds the wasm_bingen node. The interface sits in a field called el and would be wurst::elements::AElement which is the generated interface of all the Interfaces stacked on top of each other. So el has set_class and also set_href.

how to ensure that the items in that iterator actually have a href to set?

There might be another call required like into I'm not sure as I haven't implemented it yet. I'm hoping that the IntoIterator can return enum variants as I mentioned.

ยน Please call it something more concise see_no_evil

I'm aiming to make it as close in experience to JS in naming, something else can wrap me to provide a cut down name. But that said all this code will likely move around a bit.

killercup commented 6 years ago

Random thought: Can we write a query_selector_all!("p a") (proc) macro that parses the selector and can figure out what the common properties of the yielded elements are?

For example:

In practice, query_selector_all!("a, button") would probably generate code like trait __CommonInterface: B, C {}; internally and return a Iterator<Item=Box<dyn __CommonInterface>>.

Analysing the selector might be difficult, but representing this in Rust can probably be based on the all IDL info we already have.