yoshuawuyts / html

Type-safe HTML support for Rust
Apache License 2.0
244 stars 7 forks source link

Question: how to render generically. #63

Open nathan-at-least opened 1 year ago

nathan-at-least commented 1 year ago

I want to generate html from custom types, so I started like this:

trait ToHtml {
    type Output: HtmlElement;

    fn to_html(&self) -> Self::Output;
}

However, I don't see any generic methods for rendering. For example, suppose I have a generic container:

struct MyThing<T>(Vec<T>);

impl<T> ToHtml for MyThing<T>
where T: ToHtml,
{
    type Output = OrderedList;

    fn to_html(&self) -> OrderedList {
        let mut builder = OrderedList::builder();
        for elem in self.0.iter() {
            let htmlelem = elem.to_html();
            // How can I add htmlelem to the ordered list?
            todo!();
        }
        builder.build()
    }
} 

I cannot yet figure out how to implement the todo!() because all of the methods of OrderedListBuilder are "concrete": there is a specific method for every kind of element I would want to add. I want a generic method that can add any HtmlElement type. Is this possible?

I realize that the design of the library aims to constrain rendering to follow the standard, so that may preclude some HtmlElement types from being added to others. My question is: is there any way around this that is generic?

A cumbersome but type-safe approach might be to introduce a trait for each element, such as ListItemChild, then introduce ListItemBuilder::add_child<C>(&mut self, child: C) where C: ListItemChild. This may be cumbersome because every container element type would also need a trait to define which children can be added. An advantage is that every element type's docs would also clarify which containers it could be added to.

A different approach with many fewer traits would be to introduce runtime html-validity checks, so maybe:

trait ContainerElement {
    fn push_child<C>(&mut self, child: C) -> Result<(), ContainerError>
        where C: HtmlElement;
}

Thoughts or advice?

yoshuawuyts commented 1 year ago

Hey thanks for opening up this. Yes, that's currently not yet supported. We're missing custom element support still.