// Copyright 2014-2017 The html5ever Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 or the MIT license
// , at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// Something which can be inserted into the DOM.
///
/// Adjacent sibling text nodes are merged into a single node, so
/// the sink may not want to allocate a `Handle` for each.
#[allow(unused_imports)] use std::ascii::AsciiExt;
use std::borrow::Cow;
use tendril::StrTendril;
use interface::{QualName, ExpandedName, Attribute};
pub use self::NodeOrText::{AppendNode, AppendText};
pub use self::QuirksMode::{Quirks, LimitedQuirks, NoQuirks};
/// Something which can be inserted into the DOM.
///
/// Adjacent sibling text nodes are merged into a single node, so
/// the sink may not want to allocate a `Handle` for each.
pub enum NodeOrText {
AppendNode(Handle),
AppendText(StrTendril),
}
/// A document's quirks mode.
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub enum QuirksMode {
Quirks,
LimitedQuirks,
NoQuirks,
}
/// Whether to interrupt further parsing of the current input until
/// the next explicit resumption of the tokenizer, or continue without
/// any interruption.
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub enum NextParserState {
/// Stop further parsing.
Suspend,
/// Continue without interruptions.
Continue,
}
#[derive(Default)]
pub struct ElementFlags {
/// A document fragment should be created, associated with the element,
/// and returned in TreeSink::get_template_contents
///
/// https://html.spec.whatwg.org/multipage/#template-contents
pub template: bool,
/// This boolean should be recorded with the element and returned
/// in TreeSink::is_mathml_annotation_xml_integration_point
///
/// https://html.spec.whatwg.org/multipage/#html-integration-point
pub mathml_annotation_xml_integration_point: bool,
_private: ()
}
pub fn create_element(sink: &mut Sink, name: QualName, attrs: Vec) -> 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")
)
})
}
_ => {}
}
sink.create_element(name, attrs, flags)
}
pub trait TreeSink {
/// `Handle` is a reference to a DOM node. The tree builder requires
/// that a `Handle` implements `Clone` to get another reference to
/// the same node.
type Handle: Clone;
/// The overall result of parsing.
///
/// This should default to Self, but default associated types are not stable yet.
/// (https://github.com/rust-lang/rust/issues/29661)
type Output;
/// Consume this sink and return the overall result of parsing.
///
/// TODO:This should default to `fn finish(self) -> Self::Output { self }`,
/// but default associated types are not stable yet.
/// (https://github.com/rust-lang/rust/issues/29661)
fn finish(self) -> Self::Output;
/// Signal a parse error.
fn parse_error(&mut self, msg: Cow<'static, str>);
/// Get a handle to the `Document` node.
fn get_document(&mut self) -> Self::Handle;
/// What is the name of this element?
///
/// Should never be called on a non-element node;
/// feel free to `panic!`.
fn elem_name<'a>(&'a self, target: &'a Self::Handle) -> ExpandedName<'a>;
/// Create an element.
///
/// When creating a template element (`name.ns.expanded() == expanded_name!(html "template")`),
/// an associated document fragment called the "template contents" should
/// also be created. Later calls to self.get_template_contents() with that
/// given element return it.
/// https://html.spec.whatwg.org/multipage/#the-template-element
fn create_element(&mut self, name: QualName, attrs: Vec, flags: ElementFlags)
-> Self::Handle;
/// Create a comment node.
fn create_comment(&mut self, text: StrTendril) -> Self::Handle;
/// Create a Processing Instruction node.
fn create_pi(&mut self, target: StrTendril, data: StrTendril) -> Self::Handle;
/// Append a node as the last child of the given node. If this would
/// produce adjacent sibling text nodes, it should concatenate the text
/// instead.
///
/// The child node will not already have a parent.
fn append(&mut self, parent: &Self::Handle, child: NodeOrText);
/// When the insertion point is decided by the existence of a parent node of the
/// element, we consider both possibilities and send the element which will be used
/// if a parent node exists, along with the element to be used if there isn't one.
fn append_based_on_parent_node(&mut self,
element: &Self::Handle,
prev_element: &Self::Handle,
child: NodeOrText);
/// Append a `DOCTYPE` element to the `Document` node.
fn append_doctype_to_document(&mut self,
name: StrTendril,
public_id: StrTendril,
system_id: StrTendril);
/// Mark a HTML `