summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2023-04-09 11:42:54 +0300
committerLars Wirzenius <liw@liw.fi>2023-04-09 12:07:28 +0300
commit211df21355263ef6b604478035c1c1053fe48ca4 (patch)
treefb7a2413e977a482b48a5173004785b3fdf3cfb1
parent3dc7ba8812a4173a3c7ca7d037d5548b5d778200 (diff)
downloadhtml-page-211df21355263ef6b604478035c1c1053fe48ca4.tar.gz
feat: add a representation of a full HTML document
Also fix tag serialization to HTML to use all upper case (instead of only the first letter), and rename crate to "html-page". Sponsored-by: author
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/lib.rs185
3 files changed, 185 insertions, 4 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 66c20d9..ae8ae14 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -12,7 +12,7 @@ dependencies = [
]
[[package]]
-name = "html-rs"
+name = "html-page"
version = "0.1.0"
dependencies = [
"html-escape",
diff --git a/Cargo.toml b/Cargo.toml
index 89907d2..c774133 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "html-rs"
+name = "html-page"
version = "0.1.0"
edition = "2021"
diff --git a/src/lib.rs b/src/lib.rs
index a5e61b7..1794198 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -13,6 +13,71 @@ use html_escape::{encode_double_quoted_attribute, encode_safe};
use std::collections::HashMap;
use std::fmt::{Display, Formatter};
+/// An HTML document ("page'),consisting of a head and a body element.
+///
+/// ~~~
+/// # use html_page::{Document, Element, Tag};
+/// let title = Element::new(Tag::Title).with_text("my page");
+/// let doc = Document::default().with_head_element(&title);
+/// assert_eq!(format!("{}", doc), "<!DOCTYPE html>\n<HTML>\n\
+/// <HEAD><TITLE>my page</TITLE></HEAD>\n<BODY/>\n</HTML>\n");
+/// ~~~
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Document {
+ head: Element,
+ body: Element,
+}
+
+impl Default for Document {
+ fn default() -> Self {
+ Self {
+ head: Element::new(Tag::Head),
+ body: Element::new(Tag::Body),
+ }
+ }
+}
+
+impl Document {
+ /// Append an element to the head.
+ pub fn push_to_head(&mut self, e: &Element) {
+ self.head.push_child(e);
+ }
+
+ /// Append an element to the body.
+ pub fn push_to_body(&mut self, e: &Element) {
+ self.body.push_child(e);
+ }
+
+ /// Append an element to the head, when constructing.
+ pub fn with_head_element(mut self, e: &Element) -> Self {
+ self.head.push_child(e);
+ self
+ }
+
+ /// Append an element to the body, when constructing.
+ pub fn with_body_element(mut self, e: &Element) -> Self {
+ self.body.push_child(e);
+ self
+ }
+
+ /// Append text to the body, when constructing.
+ pub fn with_body_text(mut self, text: &str) -> Self {
+ self.body.push_text(text);
+ self
+ }
+}
+
+impl Display for Document {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
+ writeln!(f, "<!DOCTYPE html>")?;
+ writeln!(f, "<{}>", Tag::Html)?;
+ writeln!(f, "{}", &self.head)?;
+ writeln!(f, "{}", &self.body)?;
+ writeln!(f, "</{}>", Tag::Html)?;
+ Ok(())
+ }
+}
+
/// The tag of an HTML5 element.
///
/// Note that we only support HTML5 elements, as listed on
@@ -134,7 +199,123 @@ pub enum Tag {
impl Display for Tag {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
- write!(f, "{:?}", self)
+ write!(f, "{}", self.as_str())
+ }
+}
+
+impl Tag {
+ fn as_str(&self) -> &str {
+ match self {
+ Self::A => "A",
+ Self::Abbr => "ABBR",
+ Self::Address => "ADDRESS",
+ Self::Area => "AREA",
+ Self::Article => "ARTICLE",
+ Self::Aside => "ASIDE",
+ Self::Audio => "AUDIO",
+ Self::B => "B",
+ Self::Base => "BASE",
+ Self::Bdi => "BDI",
+ Self::Bdo => "BDO",
+ Self::Blockquote => "BLOCKQUOTE",
+ Self::Body => "BODY",
+ Self::Br => "BR",
+ Self::Button => "BUTTON",
+ Self::Canvas => "CANVAS",
+ Self::Caption => "CAPTION",
+ Self::Cite => "CITE",
+ Self::Code => "CODE",
+ Self::Col => "COL",
+ Self::ColGroup => "COLGROUP",
+ Self::Data => "DATA",
+ Self::DataList => "DATALIST",
+ Self::Dd => "DD",
+ Self::Del => "DEL",
+ Self::Details => "DETAILS",
+ Self::Dfn => "DFN",
+ Self::Dialog => "DIALOG",
+ Self::Div => "DIV",
+ Self::Dl => "DL",
+ Self::Dt => "DT",
+ Self::Em => "EM",
+ Self::Embed => "EMBED",
+ Self::FieldSet => "FIELDSET",
+ Self::FigCaption => "FIGCAPTIO",
+ Self::Figure => "FIGURE",
+ Self::Footer => "FOOTER",
+ Self::Form => "FORM",
+ Self::H1 => "H1",
+ Self::H2 => "H2",
+ Self::H3 => "H3",
+ Self::H4 => "H4",
+ Self::H5 => "H5",
+ Self::H6 => "H6",
+ Self::Head => "HEAD",
+ Self::Header => "HEADER",
+ Self::Hr => "HR",
+ Self::Html => "HTML",
+ Self::I => "I",
+ Self::Iframe => "IFRAME",
+ Self::Img => "IMG",
+ Self::Input => "INPUT",
+ Self::Ins => "INS",
+ Self::Kbd => "KBD",
+ Self::Label => "LABEL",
+ Self::Legend => "LEGEND",
+ Self::Li => "LI",
+ Self::Link => "LINK",
+ Self::Main => "MAIN",
+ Self::Map => "MAP",
+ Self::Mark => "MARK",
+ Self::Meta => "META",
+ Self::Meter => "METER",
+ Self::Nav => "NAV",
+ Self::NoScript => "NOSCRIPT",
+ Self::Object => "OBJECT",
+ Self::Ol => "OL",
+ Self::OptGroup => "OPTGROUP",
+ Self::Option => "OPTION",
+ Self::Output => "OUTPUT",
+ Self::P => "P",
+ Self::Param => "PARAM",
+ Self::Picture => "PICTURE",
+ Self::Pre => "PRE",
+ Self::Progress => "PROGRESS",
+ Self::Q => "Q",
+ Self::Rp => "RP",
+ Self::Rt => "RT",
+ Self::Ruby => "RUBY",
+ Self::S => "S",
+ Self::Samp => "SAMP",
+ Self::Script => "SCRIPT",
+ Self::Section => "SECTION",
+ Self::Select => "SELECT",
+ Self::Small => "SMALL",
+ Self::Source => "SOURCE",
+ Self::Span => "SPAN",
+ Self::Strong => "STRONG",
+ Self::Style => "STYLE",
+ Self::Sub => "SUB",
+ Self::Summary => "SUMMARY",
+ Self::Sup => "SUP",
+ Self::Svg => "SVG",
+ Self::Table => "TABLE",
+ Self::Tbody => "TBODY",
+ Self::Td => "TD",
+ Self::Template => "TEMPLATE",
+ Self::TextArea => "TEXTAREA",
+ Self::Tfoot => "TFOOT",
+ Self::Th => "TH",
+ Self::Time => "TIME",
+ Self::Title => "TITLE",
+ Self::Tr => "TR",
+ Self::Track => "TRACK",
+ Self::U => "U",
+ Self::Ul => "UL",
+ Self::Var => "VAR",
+ Self::Video => "VIDEO",
+ Self::Wbr => "WBR",
+ }
}
}
@@ -347,7 +528,7 @@ impl Display for Content {
/// recursively visits the children of each child.
///
/// ~~~
-/// # use html_rs::{Element, Tag, Visitor};
+/// # use html_page::{Element, Tag, Visitor};
/// #[derive(Default)]
/// struct Collector {
/// tags: Vec<Tag>,