html/lib.rs
1//! Typed HTML support for Rust.
2//!
3//! # Philosophy
4//!
5//! HTML is easy to get started with, but hard to get right. There are several
6//! hundred element kinds, element attributes, and deeply nested hierachies - with
7//! some relationships even being conditional on each other. Remembering all of this
8//! is difficult and error-prone, but luckily we don't have to remember any of this
9//! by using the type system! Rust's type system enables us to model the entire HTML
10//! spec, allowing us to catch all errors ahead of time during compilation.
11//!
12//! This project comes in layers. The bottom-most layer is the HTML spec itself. We
13//! download it, and parse it into definition files. We then take these definitions,
14//! and use it to generate the `html-sys` crate. This crate is semantically correct,
15//! and knows how to render itself to string representations. We then combine
16//! `html-sys` with `web-sys` (wip) to create a higher-level HTML interface,
17//! complete with support for events. This can be used to manipulate HTML both in
18//! browser (wip) and non-browser contexts.
19//!
20//! # Examples
21//!
22//! We can create HTML structures one-by-one:
23//! ```rust
24//! # #![allow(unused)]
25//! #![recursion_limit = "512"]
26//!
27//! use html::text_content::OrderedList;
28//! let tree = OrderedList::builder()
29//! .list_item(|li| li.text("nori").class("cat"))
30//! .list_item(|li| li.text("chashu").class("cat"))
31//! .build();
32//! let string = tree.to_string();
33//! ```
34//! But we can also use Rust's native control flow structures such as loops to
35//! iterate over items and create HTML:
36//! ```rust
37//! # #![allow(unused)]
38//! #![recursion_limit = "512"]
39//!
40//! use html::text_content::OrderedList;
41//! let mut ol = OrderedList::builder();
42//! for name in ["hello", "world"] {
43//! ol.list_item(|li| li.text(name));
44//! }
45//! let tree = ol.build();
46//! ```
47//!
48//! We can also create elements separately and append them later:
49//! ```rust
50//! # #![allow(unused)]
51//! #![recursion_limit = "512"]
52//!
53//! use html::text_content::{OrderedList, ListItem};
54//! let mut ol = OrderedList::builder();
55//! let li = ListItem::builder().text("hello").build();
56//! ol.push(li);
57//! let tree = ol.build();
58//! ```
59
60#![recursion_limit = "1024"]
61#![forbid(unsafe_code)]
62// #![deny(missing_debug_implementations, nonstandard_style)]
63#![warn(future_incompatible, rust_2018_idioms)]
64#![warn(missing_docs)]
65
66mod generated;
67mod manual;
68
69use std::borrow::Cow;
70
71pub use manual::categories::*;
72
73pub use manual::content;
74pub use manual::edits;
75pub use manual::embedded;
76pub use manual::forms;
77pub use manual::inline_text;
78pub use manual::interactive;
79pub use manual::media;
80pub use manual::metadata;
81pub use manual::root;
82pub use manual::scripting;
83pub use manual::tables;
84pub use manual::text_content;
85pub use manual::web_components;
86
87/// Render an HTML element to a string.
88///
89/// This API is similar to `Display`, but it takes a `depth` argument which
90/// allows rendered items to be indented.
91///
92/// Users of this crate are expected to keep using the `Display` interface as
93/// normal. This trait only exists for internal bookkeeping.
94pub trait Render {
95 /// Render an element with a given `depth` argument.
96 fn render(&self, f: &mut std::fmt::Formatter<'_>, depth: usize) -> std::fmt::Result;
97}
98
99impl Render for Cow<'static, str> {
100 fn render(&self, f: &mut std::fmt::Formatter<'_>, depth: usize) -> std::fmt::Result {
101 write!(f, "{:level$}", "", level = depth * 4)?;
102 std::fmt::Display::fmt(self, f)
103 }
104}
105
106impl<T> Render for &T
107where
108 T: Render + ?Sized,
109{
110 fn render(&self, f: &mut std::fmt::Formatter<'_>, depth: usize) -> std::fmt::Result {
111 Render::render(&**self, f, depth)
112 }
113}
114impl<T> Render for &mut T
115where
116 T: Render + ?Sized,
117{
118 fn render(&self, f: &mut std::fmt::Formatter<'_>, depth: usize) -> std::fmt::Result {
119 Render::render(&**self, f, depth)
120 }
121}
122
123/// An HTML Element
124pub trait HtmlElement {}