use crate::Tag;
use crate::dom::{Data, Namespace, Span};
use super::{Builder, Mode, Ns, Open, foreign_kind};
pub(super) fn run(src: &str, tb: &mut Builder<'_>, ns: Namespace, name: &str) {
let lname = name.to_ascii_lowercase();
let tag = match ns {
Namespace::Html => Tag::from_name(&lname),
Namespace::Svg if lname == "svg" => Tag::Svg,
Namespace::MathMl if lname == "math" => Tag::Math,
_ => Tag::Other,
};
let kind = match ns {
Namespace::Html => Ns::Html,
_ => match tag {
Tag::Svg | Tag::Math => Ns::Foreign,
_ => foreign_kind(ns, &lname, false),
},
};
tb.quirks = false;
tb.html = tb.new_node(Data::Element {
tag: Tag::Html,
ns: Namespace::Html,
name: Span::default(),
attrs: 0,
attrs_len: 0,
});
tb.append(0, tb.html);
tb.stack.push(Open {
id: tb.html,
tag: Tag::Html,
ns: Ns::Html,
});
tb.floor = 1;
tb.context = Some(Open {
id: tb.html,
tag,
ns: kind,
});
tb.context_ns = ns;
tb.mode = match tag {
_ if ns != Namespace::Html => Mode::InBody,
Tag::Html => Mode::BeforeHead,
Tag::Frameset => Mode::InFrameset,
_ => Mode::InBody,
};
if ns == Namespace::Html {
let decode = match tag {
Tag::Title | Tag::Textarea => Some(true),
Tag::Style | Tag::Xmp | Tag::Iframe | Tag::Noembed | Tag::Noframes | Tag::Script => {
Some(false)
}
Tag::Noscript if tb.scripting => Some(false),
Tag::Plaintext => Some(false),
_ => None,
};
if let Some(decode) = decode {
tb.raw_text(0, src.len(), decode);
return;
}
}
super::tokenize(src, tb);
}
impl<'a> Builder<'a> {
pub(super) fn at_fragment_root(&self) -> bool {
self.context.is_some() && self.stack.len() == 1
}
pub(super) fn fragment_table_root(&self, tag: Tag) -> Option<usize> {
use Tag::*;
let ctx = self.context?.tag;
let ok = match ctx {
Table => true,
Colgroup => tag == Col,
Tbody | Thead | Tfoot => matches!(tag, Tr | Td | Th),
Tr => matches!(tag, Td | Th),
_ => false,
};
(ok && self.context?.ns == Ns::Html).then_some(0)
}
pub(super) fn fragment_root_start(&mut self, tag: Tag) -> Option<super::Next> {
use Tag::*;
let c = self.context?;
if c.ns != Ns::Html {
return None;
}
let ignore = match c.tag {
Colgroup => !matches!(tag, Col | Template),
Table | Tbody | Thead | Tfoot | Tr => tag == Table,
Caption => matches!(
tag,
Caption | Col | Colgroup | Tbody | Td | Tfoot | Th | Thead | Tr
),
Select => matches!(tag, Input | Select),
_ => false,
};
ignore.then(|| {
self.scratch.clear();
super::Next::Data
})
}
pub(super) fn fragment_whitespace_only(&self) -> bool {
self.context
.is_some_and(|c| c.tag == Tag::Colgroup && c.ns == Ns::Html)
}
}