yoshuawuyts / html

Type-safe HTML support for Rust
Apache License 2.0
243 stars 8 forks source link

add `web-sys` support #16

Open yoshuawuyts opened 1 year ago

yoshuawuyts commented 1 year ago

Instead of using html-sys, it should be possible to use web-sys as a backend instead, so we can build DOM nodes directly in the browser. I wonder if perhaps we should allow passing some type of impl Renderer argument around, so each node knows how to write to its backend? I'm unsure exactly how we want to do this, so we should first come up with a small API example of how we want to structure things before committing to any one design.

ijsnow commented 9 months ago

I see the wip notes for this in the README. Are you working on this anywhere accessible? I'd be happy to contribute.

yoshuawuyts commented 9 months ago

Hi there, thanks for asking! Im currently not working on this, no. It'll require some design work, since it's essentially a duplicate backend to html-sys.

A good place to start would be to update the scraper to more accurately parse the WebIDL files for methods, and add them to the JSON.

Another good step is to come up with a plan to support both backends in the same repo. This is where I think the design work would come in, but it's also what would enable us to merge the feature.

ijsnow commented 9 months ago

By a duplicate back end, do you just mean an alternative to String to fold elements into (for the purpose of this issue, web_sys::Element)? If so, I suppose the additional methods you're talking about are the event handler attributes. Is that correct? If not, what is your vision for web-sys support? If so, what if we started by abstracting the requirements for the current Render trait?

Thinking from the perspective of someone who might want to implement a renderer with this library (but doesn't know too much about actually implementing a renderer), I think the parts I'd need are the tag of the element, the attributes and the children.

Basic support might be as simple as modifying the HtmlElement trait to something like the following:

trait HtmlElement {
    fn tag() -> &'static str;
    fn attributes(&self) -> Vec<(&'static str, AttributeValue)>;
    fn children<'a>(&'a self) -> Vec<DomNode<'a>>;
}

type AttributeValue = Cow<'static, str>;

enum DomNode<'a> {
    Element(&'a dyn HtmlElement),
    Text(&'a str)
}

AttributeValue could also be the generated enum from this issue.

This trait definition allows flexibility in the type definitions to easily develop abstract renderers while using the builders will allow the framework on top of the renderer to be type safe. I believe this also reflects the state of engines anyway. You can give any html element any value attribute and the browser will do just fine, it just might not have any effect on the dom. Same for children. For most elements, if a child is not valid, the browser will still render the page in quirks mode but it will not fail.

I'm sure I'm missing some things but I believe this could support most renderers. Renderers could define their own way of folding elements into their target type as well as gather information for proper diffing of the elements.