use crate::interface::{Attribute, ExpandedName, QualName};
use std::borrow::Cow;
use std::fmt::Debug;
use tendril::StrTendril;
use web_atoms::{LocalName, Namespace};
pub use self::NodeOrText::{AppendNode, AppendText};
pub use self::QuirksMode::{LimitedQuirks, NoQuirks, Quirks};
pub enum NodeOrText<Handle> {
AppendNode(Handle),
AppendText(StrTendril),
}
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub enum QuirksMode {
Quirks,
LimitedQuirks,
NoQuirks,
}
#[derive(Default)]
#[non_exhaustive]
pub struct ElementFlags {
pub template: bool,
pub mathml_annotation_xml_integration_point: bool,
pub had_duplicate_attributes: bool,
}
pub fn create_element<Sink>(sink: &Sink, name: QualName, attrs: Vec<Attribute>) -> Sink::Handle
where
Sink: TreeSink,
{
create_element_with_flags(sink, name, attrs, false)
}
pub fn create_element_with_flags<Sink>(
sink: &Sink,
name: QualName,
attrs: Vec<Attribute>,
had_duplicate_attributes: bool,
) -> Sink::Handle
where
Sink: TreeSink,
{
let mut flags = ElementFlags::default();
match name.expanded() {
expanded_name!(html "template") => flags.template = true,
expanded_name!(mathml "annotation-xml") => {
flags.mathml_annotation_xml_integration_point = attrs.iter().any(|attr| {
attr.name.expanded() == expanded_name!("", "encoding")
&& (attr.value.eq_ignore_ascii_case("text/html")
|| attr.value.eq_ignore_ascii_case("application/xhtml+xml"))
})
},
_ => {},
}
flags.had_duplicate_attributes = had_duplicate_attributes;
sink.create_element(name, attrs, flags)
}
pub trait ElemName: Debug {
fn ns(&self) -> &Namespace;
fn local_name(&self) -> &LocalName;
#[inline(always)]
fn expanded(&self) -> ExpandedName<'_> {
ExpandedName {
ns: self.ns(),
local: self.local_name(),
}
}
}
pub trait TreeSink {
type Handle: Clone;
type Output;
type ElemName<'a>: ElemName
where
Self: 'a;
fn finish(self) -> Self::Output;
fn parse_error(&self, msg: Cow<'static, str>);
fn get_document(&self) -> Self::Handle;
fn elem_name<'a>(&'a self, target: &'a Self::Handle) -> Self::ElemName<'a>;
fn create_element(
&self,
name: QualName,
attrs: Vec<Attribute>,
flags: ElementFlags,
) -> Self::Handle;
fn create_comment(&self, text: StrTendril) -> Self::Handle;
fn create_pi(&self, target: StrTendril, data: StrTendril) -> Self::Handle;
fn append(&self, parent: &Self::Handle, child: NodeOrText<Self::Handle>);
fn append_based_on_parent_node(
&self,
element: &Self::Handle,
prev_element: &Self::Handle,
child: NodeOrText<Self::Handle>,
);
fn append_doctype_to_document(
&self,
name: StrTendril,
public_id: StrTendril,
system_id: StrTendril,
);
fn mark_script_already_started(&self, _node: &Self::Handle) {}
fn pop(&self, _node: &Self::Handle) {}
fn get_template_contents(&self, target: &Self::Handle) -> Self::Handle;
fn same_node(&self, x: &Self::Handle, y: &Self::Handle) -> bool;
fn set_quirks_mode(&self, mode: QuirksMode);
fn append_before_sibling(&self, sibling: &Self::Handle, new_node: NodeOrText<Self::Handle>);
fn add_attrs_if_missing(&self, target: &Self::Handle, attrs: Vec<Attribute>);
fn associate_with_form(
&self,
_target: &Self::Handle,
_form: &Self::Handle,
_nodes: (&Self::Handle, Option<&Self::Handle>),
) {
}
fn remove_from_parent(&self, target: &Self::Handle);
fn reparent_children(&self, node: &Self::Handle, new_parent: &Self::Handle);
fn is_mathml_annotation_xml_integration_point(&self, _handle: &Self::Handle) -> bool {
false
}
fn set_current_line(&self, _line_number: u64) {}
fn allow_declarative_shadow_roots(&self, _intended_parent: &Self::Handle) -> bool {
true
}
fn attach_declarative_shadow(
&self,
_location: &Self::Handle,
_template: &Self::Handle,
_attrs: &[Attribute],
) -> bool {
false
}
fn maybe_clone_an_option_into_selectedcontent(&self, option: &Self::Handle) {
_ = option;
}
}
pub trait Tracer {
type Handle;
fn trace_handle(&self, node: &Self::Handle);
}