/rust/registry/src/index.crates.io-6f17d22bba15001f/markup5ever-0.12.1/interface/tree_builder.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2014-2017 The html5ever Project Developers. See the |
2 | | // COPYRIGHT file at the top-level directory of this distribution. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
5 | | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
6 | | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
7 | | // option. This file may not be copied, modified, or distributed |
8 | | // except according to those terms. |
9 | | |
10 | | //! This module contains functionality for managing the DOM, including adding/removing nodes. |
11 | | //! |
12 | | //! It can be used by a parser to create the DOM graph structure in memory. |
13 | | |
14 | | use crate::interface::{Attribute, ExpandedName, QualName}; |
15 | | use std::borrow::Cow; |
16 | | use tendril::StrTendril; |
17 | | |
18 | | pub use self::NodeOrText::{AppendNode, AppendText}; |
19 | | pub use self::QuirksMode::{LimitedQuirks, NoQuirks, Quirks}; |
20 | | |
21 | | /// Something which can be inserted into the DOM. |
22 | | /// |
23 | | /// Adjacent sibling text nodes are merged into a single node, so |
24 | | /// the sink may not want to allocate a `Handle` for each. |
25 | | pub enum NodeOrText<Handle> { |
26 | | AppendNode(Handle), |
27 | | AppendText(StrTendril), |
28 | | } |
29 | | |
30 | | /// A document's quirks mode, for compatibility with old browsers. See [quirks mode on wikipedia] |
31 | | /// for more information. |
32 | | /// |
33 | | /// [quirks mode on wikipedia]: https://en.wikipedia.org/wiki/Quirks_mode |
34 | | #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)] |
35 | | pub enum QuirksMode { |
36 | | /// Full quirks mode |
37 | | Quirks, |
38 | | /// Almost standards mode |
39 | | LimitedQuirks, |
40 | | /// Standards mode |
41 | | NoQuirks, |
42 | | } |
43 | | |
44 | | /// Whether to interrupt further parsing of the current input until |
45 | | /// the next explicit resumption of the tokenizer, or continue without |
46 | | /// any interruption. |
47 | | #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)] |
48 | | pub enum NextParserState { |
49 | | /// Stop further parsing. |
50 | | Suspend, |
51 | | /// Continue without interruptions. |
52 | | Continue, |
53 | | } |
54 | | |
55 | | /// Special properties of an element, useful for tagging elements with this information. |
56 | | #[derive(Default)] |
57 | | #[non_exhaustive] |
58 | | pub struct ElementFlags { |
59 | | /// A document fragment should be created, associated with the element, |
60 | | /// and returned in TreeSink::get_template_contents. |
61 | | /// |
62 | | /// See [template-contents in the whatwg spec][whatwg template-contents]. |
63 | | /// |
64 | | /// [whatwg template-contents]: https://html.spec.whatwg.org/multipage/#template-contents |
65 | | pub template: bool, |
66 | | |
67 | | /// This boolean should be recorded with the element and returned |
68 | | /// in TreeSink::is_mathml_annotation_xml_integration_point |
69 | | /// |
70 | | /// See [html-integration-point in the whatwg spec][whatwg integration-point]. |
71 | | /// |
72 | | /// [whatwg integration-point]: https://html.spec.whatwg.org/multipage/#html-integration-point |
73 | | pub mathml_annotation_xml_integration_point: bool, |
74 | | } |
75 | | |
76 | | /// A constructor for an element. |
77 | | /// |
78 | | /// # Examples |
79 | | /// |
80 | | /// Create an element like `<div class="test-class-name"></div>`: |
81 | 0 | pub fn create_element<Sink>(sink: &mut Sink, name: QualName, attrs: Vec<Attribute>) -> Sink::Handle |
82 | 0 | where |
83 | 0 | Sink: TreeSink, |
84 | 0 | { |
85 | 0 | let mut flags = ElementFlags::default(); |
86 | 0 | match name.expanded() { |
87 | 0 | expanded_name!(html "template") => flags.template = true, |
88 | | expanded_name!(mathml "annotation-xml") => { |
89 | 0 | flags.mathml_annotation_xml_integration_point = attrs.iter().any(|attr| { |
90 | 0 | attr.name.expanded() == expanded_name!("", "encoding") |
91 | 0 | && (attr.value.eq_ignore_ascii_case("text/html") |
92 | 0 | || attr.value.eq_ignore_ascii_case("application/xhtml+xml")) |
93 | 0 | }) Unexecuted instantiation: markup5ever::interface::tree_builder::create_element::<ammonia::rcdom::RcDom>::{closure#0} Unexecuted instantiation: markup5ever::interface::tree_builder::create_element::<_>::{closure#0} |
94 | | }, |
95 | 0 | _ => {}, |
96 | | } |
97 | 0 | sink.create_element(name, attrs, flags) |
98 | 0 | } Unexecuted instantiation: markup5ever::interface::tree_builder::create_element::<ammonia::rcdom::RcDom> Unexecuted instantiation: markup5ever::interface::tree_builder::create_element::<_> |
99 | | |
100 | | /// Methods a parser can use to create the DOM. The DOM provider implements this trait. |
101 | | /// |
102 | | /// Having this as a trait potentially allows multiple implementations of the DOM to be used with |
103 | | /// the same parser. |
104 | | pub trait TreeSink { |
105 | | /// `Handle` is a reference to a DOM node. The tree builder requires |
106 | | /// that a `Handle` implements `Clone` to get another reference to |
107 | | /// the same node. |
108 | | type Handle: Clone; |
109 | | |
110 | | /// The overall result of parsing. |
111 | | /// |
112 | | /// This should default to Self, but default associated types are not stable yet. |
113 | | /// [rust-lang/rust#29661](https://github.com/rust-lang/rust/issues/29661) |
114 | | type Output; |
115 | | |
116 | | /// Consume this sink and return the overall result of parsing. |
117 | | /// |
118 | | /// TODO:This should default to `fn finish(self) -> Self::Output { self }`, |
119 | | /// but default associated types are not stable yet. |
120 | | /// [rust-lang/rust#29661](https://github.com/rust-lang/rust/issues/29661) |
121 | | fn finish(self) -> Self::Output; |
122 | | |
123 | | /// Signal a parse error. |
124 | | fn parse_error(&mut self, msg: Cow<'static, str>); |
125 | | |
126 | | /// Get a handle to the `Document` node. |
127 | | fn get_document(&mut self) -> Self::Handle; |
128 | | |
129 | | /// What is the name of this element? |
130 | | /// |
131 | | /// Should never be called on a non-element node; |
132 | | /// feel free to `panic!`. |
133 | | fn elem_name<'a>(&'a self, target: &'a Self::Handle) -> ExpandedName<'a>; |
134 | | |
135 | | /// Create an element. |
136 | | /// |
137 | | /// When creating a template element (`name.ns.expanded() == expanded_name!(html "template")`), |
138 | | /// an associated document fragment called the "template contents" should |
139 | | /// also be created. Later calls to self.get_template_contents() with that |
140 | | /// given element return it. |
141 | | /// See [the template element in the whatwg spec][whatwg template]. |
142 | | /// |
143 | | /// [whatwg template]: https://html.spec.whatwg.org/multipage/#the-template-element |
144 | | fn create_element( |
145 | | &mut self, |
146 | | name: QualName, |
147 | | attrs: Vec<Attribute>, |
148 | | flags: ElementFlags, |
149 | | ) -> Self::Handle; |
150 | | |
151 | | /// Create a comment node. |
152 | | fn create_comment(&mut self, text: StrTendril) -> Self::Handle; |
153 | | |
154 | | /// Create a Processing Instruction node. |
155 | | fn create_pi(&mut self, target: StrTendril, data: StrTendril) -> Self::Handle; |
156 | | |
157 | | /// Append a node as the last child of the given node. If this would |
158 | | /// produce adjacent sibling text nodes, it should concatenate the text |
159 | | /// instead. |
160 | | /// |
161 | | /// The child node will not already have a parent. |
162 | | fn append(&mut self, parent: &Self::Handle, child: NodeOrText<Self::Handle>); |
163 | | |
164 | | /// When the insertion point is decided by the existence of a parent node of the |
165 | | /// element, we consider both possibilities and send the element which will be used |
166 | | /// if a parent node exists, along with the element to be used if there isn't one. |
167 | | fn append_based_on_parent_node( |
168 | | &mut self, |
169 | | element: &Self::Handle, |
170 | | prev_element: &Self::Handle, |
171 | | child: NodeOrText<Self::Handle>, |
172 | | ); |
173 | | |
174 | | /// Append a `DOCTYPE` element to the `Document` node. |
175 | | fn append_doctype_to_document( |
176 | | &mut self, |
177 | | name: StrTendril, |
178 | | public_id: StrTendril, |
179 | | system_id: StrTendril, |
180 | | ); |
181 | | |
182 | | /// Mark a HTML `<script>` as "already started". |
183 | 0 | fn mark_script_already_started(&mut self, _node: &Self::Handle) {} Unexecuted instantiation: <ammonia::rcdom::RcDom as markup5ever::interface::tree_builder::TreeSink>::mark_script_already_started Unexecuted instantiation: <_ as markup5ever::interface::tree_builder::TreeSink>::mark_script_already_started |
184 | | |
185 | | /// Indicate that a node was popped off the stack of open elements. |
186 | 0 | fn pop(&mut self, _node: &Self::Handle) {} Unexecuted instantiation: <ammonia::rcdom::RcDom as markup5ever::interface::tree_builder::TreeSink>::pop Unexecuted instantiation: <_ as markup5ever::interface::tree_builder::TreeSink>::pop |
187 | | |
188 | | /// Get a handle to a template's template contents. The tree builder |
189 | | /// promises this will never be called with something else than |
190 | | /// a template element. |
191 | | fn get_template_contents(&mut self, target: &Self::Handle) -> Self::Handle; |
192 | | |
193 | | /// Do two handles refer to the same node? |
194 | | fn same_node(&self, x: &Self::Handle, y: &Self::Handle) -> bool; |
195 | | |
196 | | /// Set the document's quirks mode. |
197 | | fn set_quirks_mode(&mut self, mode: QuirksMode); |
198 | | |
199 | | /// Append a node as the sibling immediately before the given node. |
200 | | /// |
201 | | /// The tree builder promises that `sibling` is not a text node. However its |
202 | | /// old previous sibling, which would become the new node's previous sibling, |
203 | | /// could be a text node. If the new node is also a text node, the two should |
204 | | /// be merged, as in the behavior of `append`. |
205 | | /// |
206 | | /// NB: `new_node` may have an old parent, from which it should be removed. |
207 | | fn append_before_sibling(&mut self, sibling: &Self::Handle, new_node: NodeOrText<Self::Handle>); |
208 | | |
209 | | /// Add each attribute to the given element, if no attribute with that name |
210 | | /// already exists. The tree builder promises this will never be called |
211 | | /// with something else than an element. |
212 | | fn add_attrs_if_missing(&mut self, target: &Self::Handle, attrs: Vec<Attribute>); |
213 | | |
214 | | /// Associate the given form-associatable element with the form element |
215 | 0 | fn associate_with_form( |
216 | 0 | &mut self, |
217 | 0 | _target: &Self::Handle, |
218 | 0 | _form: &Self::Handle, |
219 | 0 | _nodes: (&Self::Handle, Option<&Self::Handle>), |
220 | 0 | ) { |
221 | 0 | } Unexecuted instantiation: <ammonia::rcdom::RcDom as markup5ever::interface::tree_builder::TreeSink>::associate_with_form Unexecuted instantiation: <_ as markup5ever::interface::tree_builder::TreeSink>::associate_with_form |
222 | | |
223 | | /// Detach the given node from its parent. |
224 | | fn remove_from_parent(&mut self, target: &Self::Handle); |
225 | | |
226 | | /// Remove all the children from node and append them to new_parent. |
227 | | fn reparent_children(&mut self, node: &Self::Handle, new_parent: &Self::Handle); |
228 | | |
229 | | /// Returns true if the adjusted current node is an HTML integration point |
230 | | /// and the token is a start tag. |
231 | 0 | fn is_mathml_annotation_xml_integration_point(&self, _handle: &Self::Handle) -> bool { |
232 | 0 | false |
233 | 0 | } |
234 | | |
235 | | /// Called whenever the line number changes. |
236 | 0 | fn set_current_line(&mut self, _line_number: u64) {} Unexecuted instantiation: <ammonia::rcdom::RcDom as markup5ever::interface::tree_builder::TreeSink>::set_current_line Unexecuted instantiation: <_ as markup5ever::interface::tree_builder::TreeSink>::set_current_line |
237 | | |
238 | | /// Indicate that a `script` element is complete. |
239 | 0 | fn complete_script(&mut self, _node: &Self::Handle) -> NextParserState { |
240 | 0 | NextParserState::Continue |
241 | 0 | } |
242 | | } |
243 | | |
244 | | /// Trace hooks for a garbage-collected DOM. |
245 | | pub trait Tracer { |
246 | | type Handle; |
247 | | |
248 | | /// Upon a call to `trace_handles`, the tree builder will call this method |
249 | | /// for each handle in its internal state. |
250 | | fn trace_handle(&self, node: &Self::Handle); |
251 | | } |