// 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. //! This module contains functionality for managing the DOM, including adding/removing nodes. //! //! It can be used by a parser to create the DOM graph structure in memory. use crate::interface::{Attribute, ExpandedName, QualName}; use std::borrow::Cow; use tendril::StrTendril; pub use self::NodeOrText::{AppendNode, AppendText}; pub use self::QuirksMode::{LimitedQuirks, NoQuirks, Quirks}; /// 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, for compatibility with old browsers. See [quirks mode on wikipedia] /// for more information. /// /// [quirks mode on wikipedia]: https://en.wikipedia.org/wiki/Quirks_mode #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)] pub enum QuirksMode { /// Full quirks mode Quirks, /// Almost standards mode LimitedQuirks, /// Standards mode 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, } /// Special properties of an element, useful for tagging elements with this information. #[derive(Default)] pub struct ElementFlags { /// A document fragment should be created, associated with the element, /// and returned in TreeSink::get_template_contents. /// /// See [template-contents in the whatwg spec][whatwg template-contents]. /// /// [whatwg 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 /// /// See [html-integration-point in the whatwg spec][whatwg integration-point]. /// /// [whatwg integration-point]: https://html.spec.whatwg.org/multipage/#html-integration-point pub mathml_annotation_xml_integration_point: bool, // Prevent construction from outside module _private: (), } /// A constructor for an element. /// /// # Examples /// /// Create an element like `
`: 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) } /// Methods a parser can use to create the DOM. The DOM provider implements this trait. /// /// Having this as a trait potentially allows multiple implementations of the DOM to be used with /// the same parser. 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. /// [rust-lang/rust#29661](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. /// [rust-lang/rust#29661](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. /// See [the template element in the whatwg spec][whatwg template]. /// /// [whatwg template]: 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 `