use crate::attr::Attributes;
use crate::span::Span;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Document {
doctype: Option<Doctype>,
root: Element,
span: Span,
}
impl Document {
#[must_use]
pub fn new(doctype: Option<Doctype>, root: Element, span: Span) -> Self {
Self {
doctype,
root,
span,
}
}
#[must_use]
pub fn doctype(&self) -> Option<&Doctype> {
self.doctype.as_ref()
}
#[must_use]
pub fn root(&self) -> &Element {
&self.root
}
#[must_use]
pub fn span(&self) -> Span {
self.span
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Doctype {
name: String,
public_id: Option<String>,
system_id: Option<String>,
span: Span,
}
impl Doctype {
#[must_use]
pub fn new(
name: impl Into<String>,
public_id: Option<String>,
system_id: Option<String>,
span: Span,
) -> Self {
Self {
name: name.into(),
public_id,
system_id,
span,
}
}
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
#[must_use]
pub fn public_id(&self) -> Option<&str> {
self.public_id.as_deref()
}
#[must_use]
pub fn system_id(&self) -> Option<&str> {
self.system_id.as_deref()
}
#[must_use]
pub fn span(&self) -> Span {
self.span
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Node {
Element(Element),
Text(Text),
Comment(Comment),
}
impl Node {
#[must_use]
pub fn span(&self) -> Span {
match self {
Self::Element(e) => e.span(),
Self::Text(t) => t.span(),
Self::Comment(c) => c.span(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element {
name: String,
attributes: Attributes,
children: Vec<Node>,
self_closing: bool,
span: Span,
}
impl Element {
#[must_use]
pub fn new(
name: impl Into<String>,
attributes: Attributes,
children: Vec<Node>,
self_closing: bool,
span: Span,
) -> Self {
Self {
name: name.into(),
attributes,
children,
self_closing,
span,
}
}
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
#[must_use]
pub fn attributes(&self) -> &Attributes {
&self.attributes
}
#[must_use]
pub fn children(&self) -> &[Node] {
&self.children
}
#[must_use]
pub fn is_self_closing(&self) -> bool {
self.self_closing
}
#[must_use]
pub fn span(&self) -> Span {
self.span
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Text {
content: String,
span: Span,
}
impl Text {
#[must_use]
pub fn new(content: impl Into<String>, span: Span) -> Self {
Self {
content: content.into(),
span,
}
}
#[must_use]
pub fn content(&self) -> &str {
&self.content
}
#[must_use]
pub fn span(&self) -> Span {
self.span
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Comment {
text: String,
span: Span,
}
impl Comment {
#[must_use]
pub fn new(text: impl Into<String>, span: Span) -> Self {
Self {
text: text.into(),
span,
}
}
#[must_use]
pub fn text(&self) -> &str {
&self.text
}
#[must_use]
pub fn span(&self) -> Span {
self.span
}
}
#[must_use]
pub fn is_void_element(name: &str) -> bool {
matches!(
name,
"area"
| "base"
| "br"
| "col"
| "embed"
| "hr"
| "img"
| "input"
| "link"
| "meta"
| "source"
| "track"
| "wbr"
)
}
#[must_use]
pub fn is_raw_text_element(name: &str) -> bool {
matches!(name, "script" | "style")
}
#[must_use]
pub fn is_escapable_raw_text_element(name: &str) -> bool {
matches!(name, "textarea" | "title")
}