es_htmlform/
lib.rs

1//! Library to validate and generate HTML forms.
2//!
3//! ```rust
4//! use es_htmlform::{HtmlForm, FormError, ValidationError};
5//! use es_htmlform::value::ValueMap;
6//! use es_htmlform::types::{InputType, Method, Constraint as Cons, Attr};
7//!
8//! // simple form with 1 field
9//! fn searchform() -> Result<HtmlForm<'static>, FormError> {
10//!     Ok(HtmlForm::new(".", Method::Get)
11//!         .input(
12//!             InputType::Text, "q", "Search", true,
13//!             vec![], vec![Attr::Placeholder("enter query")])?
14//!         .submit(None, "go!", vec![])?)
15//! }
16//!
17//! // more elaborate example, with validation (both client- and
18//! // server-side) and custom attributes
19//! fn userform() -> Result<HtmlForm<'static>, FormError> {
20//!     Ok(HtmlForm::new(".", Method::Post)
21//!         .input(
22//!             InputType::Text, "username", "Username", true,
23//!             vec![
24//!                 Cons::MinLength(5), Cons::MaxLength(16),
25//!                 Cons::Pattern(r"^\w+$")],
26//!             vec![])?
27//!         .input(
28//!             InputType::Text, "name", "Full name", true,
29//!             vec![Cons::MinLength(0), Cons::MaxLength(64)], vec![])?
30//!         .input(
31//!             InputType::Password, "password", "Password", true,
32//!             vec![
33//!                 Cons::MinLength(6), Cons::MaxLength(64),
34//!                 Cons::Pattern(r"(\d.*[^\w\s\d]|[^\w\s\d].*\d)"),
35//!             ],
36//!             vec![Attr::Title(
37//!                 "Must contain 1 number and 1 non-word character")])?
38//!         .input(
39//!             InputType::Number, "age", "Age", true,
40//!             vec![Cons::MinNumber(18.0)],
41//!             vec![Attr::StepInt(1), Attr::Any("id", "age")])?
42//!         .textarea("message", "Message", false, vec![], vec![])?
43//!         .hidden(
44//!             "csrf", Some("foo"), true,
45//!             vec![Cons::Func(Box::new(|v| {
46//!                 if v.as_string().as_str() != "foo" {
47//!                     Err(ValidationError::new("invalid CSRF token"))
48//!                 } else {
49//!                     Ok(())
50//!                 }
51//!             }))],
52//!             vec![])?
53//!         .submit(None, "Submit", vec![])?
54//!     )
55//! }
56//!
57//! fn main() {
58//!     let values = ValueMap::from_urlencoded(b"q=foo").unwrap();
59//!     let mut form = searchform().unwrap();
60//!     form.update(&values, true);
61//!
62//!     println!("{}", serde_json::to_string_pretty(&form).unwrap());
63//!     assert_eq!(form.errors.len(), 0);
64//!     assert_eq!(form.get_string("q").unwrap(), "foo");
65//!     assert_eq!(
66//!         serde_json::to_string_pretty(&form).unwrap(),
67//!         r#"{
68//!   "action": ".",
69//!   "method": "get",
70//!   "errors": {},
71//!   "fields": [
72//!     {
73//!       "name": "q",
74//!       "label": "Search",
75//!       "element": "input",
76//!       "type": "text",
77//!       "required": true,
78//!       "multi": false,
79//!       "choices": [],
80//!       "attributes": {
81//!         "placeholder": "enter query"
82//!       },
83//!       "value": "foo"
84//!     },
85//!     {
86//!       "name": "",
87//!       "label": "go!",
88//!       "element": "input",
89//!       "type": "submit",
90//!       "required": false,
91//!       "multi": false,
92//!       "choices": [],
93//!       "attributes": {},
94//!       "value": ""
95//!     }
96//!   ]
97//! }"#);
98//!
99//!     let values = ValueMap::from_urlencoded(
100//!         b"username=johnny&name=Johnny&password=foobar-123&age=46&csrf=bar"
101//!     ).unwrap();
102//!     let mut form = userform().unwrap();
103//!     form.update(&values, true);
104//!
105//!     assert_eq!(form.errors.len(), 1);
106//!     assert_eq!(
107//!         form.errors.get("csrf").unwrap(), "invalid CSRF token");
108//!     assert_eq!(form.get_string("username").unwrap(), "johnny");
109//!     assert_eq!(form.get_string("password").unwrap(), "foobar-123");
110//!     assert_eq!(form.get_string("csrf").unwrap(), "bar");
111//! }
112//! ```
113
114mod error;
115mod htmlform;
116
117pub mod value;
118pub mod types;
119mod serde;
120
121pub use crate::error::{FormError, ValidationError};
122pub use crate::htmlform::{HtmlForm, Field};