use ahash::AHashMap;
use minify_html_common::spec::tag::ns::Namespace;
use std::fmt::Debug;
use std::fmt::Formatter;
use std::str::from_utf8;
pub mod c14n;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum ElementClosingTag {
Omitted,
Present,
SelfClosing,
Void,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[allow(clippy::upper_case_acronyms)]
pub enum ScriptOrStyleLang {
CSS,
Data,
JS,
JSModule,
}
pub struct AttrVal {
pub quote: Option<u8>,
pub value: Vec<u8>,
}
impl AttrVal {
pub fn as_slice(&self) -> &[u8] {
self.value.as_slice()
}
}
impl Debug for AttrVal {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(from_utf8(&self.value).unwrap())
}
}
impl PartialEq for AttrVal {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl Eq for AttrVal {}
#[derive(Eq, PartialEq, Debug)]
pub enum RcdataContentType {
Textarea,
Title,
}
#[derive(Eq, PartialEq)]
pub enum NodeData {
Bang {
code: Vec<u8>,
ended: bool,
},
Comment {
code: Vec<u8>,
ended: bool,
},
Doctype {
legacy: Vec<u8>,
ended: bool,
},
Element {
attributes: AHashMap<Vec<u8>, AttrVal>,
children: Vec<NodeData>,
closing_tag: ElementClosingTag,
name: Vec<u8>,
namespace: Namespace,
next_sibling_element_name: Vec<u8>,
},
Instruction {
code: Vec<u8>,
ended: bool,
},
RcdataContent {
typ: RcdataContentType,
text: Vec<u8>,
},
ScriptOrStyleContent {
code: Vec<u8>,
lang: ScriptOrStyleLang,
},
Text {
value: Vec<u8>,
},
Opaque {
raw_source: Vec<u8>,
},
}
impl Debug for NodeData {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
NodeData::Bang { code, ended } => f
.debug_struct("Bang")
.field("code", &from_utf8(code).unwrap().to_string())
.field("ended", ended)
.finish(),
NodeData::Comment { code, ended } => f
.debug_struct("Comment")
.field("code", &from_utf8(code).unwrap().to_string())
.field("ended", ended)
.finish(),
NodeData::Doctype { legacy, ended } => f
.debug_struct("Doctype")
.field("legacy", &from_utf8(legacy).unwrap().to_string())
.field("ended", ended)
.finish(),
NodeData::Element {
attributes,
children,
closing_tag,
name,
namespace,
next_sibling_element_name,
} => f
.debug_struct("Element")
.field("tag", &{
let mut out = format!("{:?}:{}", namespace, from_utf8(name).unwrap());
for (n, v) in attributes {
out.push_str(format!(" {}={:?}", from_utf8(n).unwrap(), v).as_str());
}
out
})
.field("children", children)
.field("closing_tag", closing_tag)
.field(
"next_sibling_element_name",
&from_utf8(next_sibling_element_name).unwrap().to_string(),
)
.finish(),
NodeData::Instruction { code, ended } => f
.debug_struct("Instruction")
.field("code", &from_utf8(code).unwrap().to_string())
.field("ended", ended)
.finish(),
NodeData::RcdataContent { typ, text } => f
.debug_struct("RcdataContent")
.field("typ", typ)
.field("text", &from_utf8(text).unwrap().to_string())
.finish(),
NodeData::ScriptOrStyleContent { code, lang } => f
.debug_struct("ScriptOrStyleContent")
.field("code", &from_utf8(code).unwrap().to_string())
.field("lang", lang)
.finish(),
NodeData::Text { value } => f.write_str(from_utf8(value).unwrap()),
NodeData::Opaque { raw_source } => f
.debug_struct("Opaque")
.field("raw_source", &from_utf8(raw_source).unwrap().to_string())
.finish(),
}
}
}