html_editor/
lib.rs

1//! `html_editor` is a simple html parser and editor.
2//!
3//! Quick Start:
4//! ```
5//! use html_editor::operation::*;
6//! use html_editor::{parse, Node};
7//!
8//! // You can create DOM nodes by parsing html string.
9//! let html = r#"
10//!     <!doctype html>
11//!     <html>
12//!         <head>
13//!         </head>
14//!         <body>
15//!         </body>
16//!     </html>
17//! "#;
18//! let mut dom = parse(html).unwrap();
19//!
20//! // Or you can create a node by some built-in methods like below.
21//! let app: Node = Node::new_element("div", vec![("id", "app")], vec![]);
22//!
23//! // Here shows how to edit the nodes and turn it back to html.
24//! let html = dom
25//!     .remove_by(&Selector::from("head"))
26//!     .insert_to(&Selector::from("body"), app)
27//!     .trim()
28//!     .html();
29//!
30//! assert_eq!(
31//!     html,
32//!     r#"<!DOCTYPE html><html><body><div id="app"></div></body></html>"#
33//! );
34//! ```
35
36mod data;
37mod parse;
38
39pub mod operation;
40
41pub use parse::parse;
42pub use parse::try_parse;
43
44/// Doctype of Html or Xml
45#[derive(Clone, Debug)]
46pub enum Doctype {
47    Html,
48    Xml { version: String, encoding: String },
49}
50
51/// Node of DOM
52#[derive(Debug, Clone)]
53pub enum Node {
54    Element(Element),
55    Text(String),
56    Comment(String),
57    Doctype(Doctype),
58}
59
60impl Node {
61    /// Check if it is an element node.
62    ///
63    /// ```
64    /// use html_editor::Node;
65    ///
66    /// assert_eq!(Node::new_element("div", vec![("id", "app")], vec![]).is_element(), true);
67    /// assert_eq!(Node::Text("Lorem Ipsum".to_string()).is_element(), false);
68    /// ```
69    pub fn is_element(&self) -> bool {
70        matches!(self, Node::Element { .. })
71    }
72
73    #[deprecated(note = "Please use `is_element` instead")]
74    pub fn into_element(self) -> Element {
75        match self {
76            Node::Element(element) => element,
77            _ => panic!("{:?} is not an element", self),
78        }
79    }
80
81    /// Convert the node into an element.
82    ///
83    /// Returns `None` if the node is not an element.
84    ///
85    /// Example:
86    /// ```
87    /// use html_editor::{Node, Element};
88    ///
89    /// let a: Node = Node::new_element("div", vec![("id", "app")], vec![]);
90    /// assert!(a.as_element().is_some());
91    ///
92    /// let b: Node = Node::Text("hello".to_string());
93    /// assert!(b.as_element().is_none());
94    /// ```
95    pub fn as_element(&self) -> Option<&Element> {
96        match self {
97            Node::Element(element) => Some(element),
98            _ => None,
99        }
100    }
101
102    /// Convert the node into a mutable element.
103    ///
104    /// Returns `None` if the node is not an element.
105    ///
106    /// Example:
107    /// ```
108    /// use html_editor::{Node, Element};
109    ///
110    /// let mut a: Node = Node::new_element("div", vec![("id", "app")], vec![]);
111    /// assert!(a.as_element_mut().is_some());
112    ///
113    /// let mut b: Node = Node::Text("hello".to_string());
114    /// assert!(b.as_element_mut().is_none());
115    /// ```
116    pub fn as_element_mut(&mut self) -> Option<&mut Element> {
117        match self {
118            Node::Element(element) => Some(element),
119            _ => None,
120        }
121    }
122
123    /// Create a new element node.
124    ///
125    /// ```
126    /// use html_editor::Node;
127    ///
128    /// let node: Node = Node::new_element(
129    ///     "h1",
130    ///     vec![("class", "title")],
131    ///     vec![
132    ///         Node::Text("Hello, world!".to_string()),
133    ///     ]
134    /// );
135    /// ```
136    pub fn new_element(name: &str, attrs: Vec<(&str, &str)>, children: Vec<Node>) -> Node {
137        Element {
138            name: name.to_string(),
139            attrs: attrs
140                .into_iter()
141                .map(|(k, v)| (k.to_string(), v.to_string()))
142                .collect(),
143            children,
144        }
145        .into_node()
146    }
147}
148
149/// HTML Element
150#[derive(Debug, Clone)]
151pub struct Element {
152    pub name: String,
153    pub attrs: Vec<(String, String)>,
154    pub children: Vec<Node>,
155}
156
157impl Element {
158    /// Create a new element.
159    pub fn new(name: &str, attrs: Vec<(&str, &str)>, children: Vec<Node>) -> Self {
160        Self {
161            name: name.to_string(),
162            attrs: attrs
163                .into_iter()
164                .map(|(k, v)| (k.to_string(), v.to_string()))
165                .collect(),
166            children,
167        }
168    }
169}
170
171impl Element {
172    pub fn into_node(self) -> Node {
173        Node::Element(self)
174    }
175}
176
177impl From<Element> for Node {
178    fn from(element: Element) -> Self {
179        Node::Element(element)
180    }
181}