DioxusLabs / dioxus

Fullstack app framework for web, desktop, mobile, and more.
https://dioxuslabs.com
Apache License 2.0
20.72k stars 799 forks source link

Provide type checking support for HTML attribute values in `rsx` macro #2398

Open mrgzi opened 5 months ago

mrgzi commented 5 months ago

Feature Request

Since Rust is a strongly typed language, it seems sensible to check types in HTML attribute values as well. Currently, rsx macro allows the following usage:

pub fn component() -> Element {
    rsx! {
        input {
            r#type: "text",
            maxlength: "10",
        }
    }
}

However, the maxlength attribute should actually be an integer:

pub fn component() -> Element {
    rsx! {
        input {
            r#type: "text",
            maxlength: 10,
        }
    }
}

Implement Suggestion

Instead of forcing developers to use strongly typed HTML, we can provide two options:

  1. Comprehensive Type Definitions: Attributes should have type definitions that can include primitive data types, enums, and custom structs, depending on the attribute's expected values.
  2. String Literal Validation: When attributes are specified using string literals, the rsx macro should validate these strings against the expected data types.

Examples;

pub fn component() -> Element {
   rsx! {
        input { 
            r#type: InputType::Email, 
            maxlength: 10
        }
        input { 
            r#type:  "email" 
            maxlength: "10"
        }
        input { 
            r#type:  "emaaill"  // `rsx` should show an error: invalid input type
            maxlength: "10"
        }
   }
}
ealmloff commented 4 months ago

I have some concerns about the binary size impact of typed HTML in WASM. One of the largest pieces of dioxus-web today is just converting a typed enum key in events to and from a string. Each part of typed HTML would need similar logic which may have a large binary size.

ealmloff commented 3 months ago

For enums, we could actually expand the values to const associated generics with &'static str values which wouldn't have a binary size impact.

In:

input { 
     r#type: Type::Email,
}

Type could be a struct like this:

struct Type;
impl Type {
    pub const Email: &'static = "email";
}

https://github.com/microsoft/vscode-custom-data has type data vscode uses for autocomplete. We could use it in a build script to generate const associated types for attributes in dioxus. (Could be useful to steal out some of the serde logic from https://github.com/ealmloff/html-parser/blob/main/build.rs)

This would also make autocomplete for values much nicer.