Skip to content

Commit 0a87717

Browse files
committed
mathml_annotation_xml_integration_point at element creation time
The result shouldn’t change if the attributed is changed in the meantime.
1 parent d1992f2 commit 0a87717

File tree

10 files changed

+105
-84
lines changed

10 files changed

+105
-84
lines changed

html5ever/examples/noop-tree-builder.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::borrow::Cow;
1616

1717
use html5ever::{Attribute, QualName, ExpandedName};
1818
use html5ever::parse_document;
19-
use html5ever::tree_builder::{TreeSink, QuirksMode, NodeOrText};
19+
use html5ever::tree_builder::{TreeSink, QuirksMode, NodeOrText, ElementFlags};
2020
use html5ever::tendril::*;
2121

2222
struct Sink {
@@ -61,12 +61,7 @@ impl TreeSink for Sink {
6161
self.names.get(target).expect("not an element").expanded()
6262
}
6363

64-
fn elem_any_attr<P>(&self, _target: &usize, _predicate: P) -> bool
65-
where P: FnMut(ExpandedName, &str) -> bool {
66-
false
67-
}
68-
69-
fn create_element(&mut self, name: QualName, _attrs: Vec<Attribute>) -> usize {
64+
fn create_element(&mut self, name: QualName, _: Vec<Attribute>, _: ElementFlags) -> usize {
7065
let id = self.get_id();
7166
self.names.insert(id, name);
7267
id

html5ever/examples/print-tree-actions.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::collections::HashMap;
1515
use std::borrow::Cow;
1616

1717
use html5ever::{QualName, ExpandedName, Attribute};
18-
use html5ever::tree_builder::{TreeSink, QuirksMode, NodeOrText, AppendNode, AppendText};
18+
use html5ever::tree_builder::{TreeSink, QuirksMode, NodeOrText, AppendNode, AppendText, ElementFlags};
1919
use html5ever::parse_document;
2020
use html5ever::tendril::*;
2121

@@ -65,12 +65,7 @@ impl TreeSink for Sink {
6565
self.names.get(target).expect("not an element").expanded()
6666
}
6767

68-
fn elem_any_attr<P>(&self, _target: &usize, _predicate: P) -> bool
69-
where P: FnMut(ExpandedName, &str) -> bool {
70-
false
71-
}
72-
73-
fn create_element(&mut self, name: QualName, _attrs: Vec<Attribute>) -> usize {
68+
fn create_element(&mut self, name: QualName, _: Vec<Attribute>, _: ElementFlags) -> usize {
7469
let id = self.get_id();
7570
println!("Created {:?} as {}", name, id);
7671
self.names.insert(id, name);

html5ever/src/driver.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use {Attribute, QualName};
1313
use buffer_queue::BufferQueue;
1414
use tokenizer::{Tokenizer, TokenizerOpts, TokenizerResult};
15-
use tree_builder::{TreeBuilderOpts, TreeBuilder, TreeSink};
15+
use tree_builder::{TreeBuilderOpts, TreeBuilder, TreeSink, create_element};
1616

1717
use std::borrow::Cow;
1818
use std::mem;
@@ -56,7 +56,7 @@ pub fn parse_fragment<Sink>(mut sink: Sink, opts: ParseOpts,
5656
context_name: QualName, context_attrs: Vec<Attribute>)
5757
-> Parser<Sink>
5858
where Sink: TreeSink {
59-
let context_elem = sink.create_element(context_name, context_attrs);
59+
let context_elem = create_element(&mut sink, context_name, context_attrs);
6060
parse_fragment_for_element(sink, opts, context_elem, None)
6161
}
6262

html5ever/src/tree_builder/actions.rs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//! mode appropriately".
1414
1515
use {LocalName, Namespace, QualName, ExpandedName};
16-
use interface::{Attribute, TreeSink, QuirksMode, NodeOrText, AppendNode, AppendText};
16+
use interface::{Attribute, TreeSink, QuirksMode, NodeOrText, AppendNode, AppendText, create_element};
1717
use tendril::StrTendril;
1818
use tokenizer::{Tag, StartTag, EndTag};
1919
use tokenizer::states::{RawData, RawKind};
@@ -358,8 +358,8 @@ impl<Handle, Sink> TreeBuilderActions<Handle>
358358
};
359359
// FIXME: Is there a way to avoid cloning the attributes twice here (once on their
360360
// own, once as part of t.clone() above)?
361-
let new_element = self.sink.create_element(
362-
QualName::new(None, ns!(html), tag.name.clone()),
361+
let new_element = create_element(
362+
&mut self.sink, QualName::new(None, ns!(html), tag.name.clone()),
363363
tag.attrs.clone());
364364
self.open_elems[node_index] = new_element.clone();
365365
self.active_formatting[node_formatting_index] = Element(new_element.clone(), tag);
@@ -387,8 +387,8 @@ impl<Handle, Sink> TreeBuilderActions<Handle>
387387
// 15.
388388
// FIXME: Is there a way to avoid cloning the attributes twice here (once on their own,
389389
// once as part of t.clone() above)?
390-
let new_element = self.sink.create_element(
391-
QualName::new(None, ns!(html), fmt_elem_tag.name.clone()),
390+
let new_element = create_element(
391+
&mut self.sink, QualName::new(None, ns!(html), fmt_elem_tag.name.clone()),
392392
fmt_elem_tag.attrs.clone());
393393
let new_entry = Element(new_element.clone(), fmt_elem_tag);
394394

@@ -772,8 +772,8 @@ impl<Handle, Sink> TreeBuilderActions<Handle>
772772

773773
//§ creating-and-inserting-nodes
774774
fn create_root(&mut self, attrs: Vec<Attribute>) {
775-
let elem = self.sink.create_element(
776-
QualName::new(None, ns!(html), local_name!("html")),
775+
let elem = create_element(
776+
&mut self.sink, QualName::new(None, ns!(html), local_name!("html")),
777777
attrs);
778778
self.push(&elem);
779779
self.sink.append(&self.doc_handle, AppendNode(elem));
@@ -791,7 +791,7 @@ impl<Handle, Sink> TreeBuilderActions<Handle>
791791

792792
// Step 7.
793793
let qname = QualName::new(None, ns, name);
794-
let elem = self.sink.create_element(qname.clone(), attrs.clone());
794+
let elem = create_element(&mut self.sink, qname.clone(), attrs.clone());
795795

796796
let insertion_point = self.appropriate_place_for_insertion(None);
797797
let tree_node = match insertion_point {
@@ -953,16 +953,8 @@ impl<Handle, Sink> TreeBuilderActions<Handle>
953953
TagToken(Tag { kind: StartTag, name: local_name!("svg"), .. }) => return false,
954954
CharacterTokens(..) | NullCharacterToken |
955955
TagToken(Tag { kind: StartTag, .. }) => {
956-
let integration_point = self.sink.elem_any_attr(
957-
self.adjusted_current_node(),
958-
|attr_name, attr_value| {
959-
attr_name == expanded_name!("", "encoding") && (
960-
attr_value.eq_ignore_ascii_case("text/html") ||
961-
attr_value.eq_ignore_ascii_case("application/xhtml+xml")
962-
)
963-
}
964-
);
965-
return !integration_point
956+
return !self.sink.is_mathml_annotation_xml_integration_point(
957+
self.adjusted_current_node())
966958
}
967959
_ => {}
968960
};

html5ever/src/tree_builder/mod.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
1414
pub use interface::{QuirksMode, Quirks, LimitedQuirks, NoQuirks};
1515
pub use interface::{NodeOrText, AppendNode, AppendText};
16-
pub use interface::{TreeSink, Tracer, NextParserState};
16+
pub use interface::{TreeSink, Tracer, NextParserState, create_element, ElementFlags};
1717

1818
use self::types::*;
1919
use self::actions::TreeBuilderActions;
@@ -503,7 +503,7 @@ impl<Handle, Sink> TokenSink
503503
mod test {
504504
use markup5ever::interface::{QuirksMode, Quirks, LimitedQuirks, NoQuirks};
505505
use markup5ever::interface::{NodeOrText, AppendNode, AppendText};
506-
use markup5ever::interface::{TreeSink, Tracer};
506+
use markup5ever::interface::{TreeSink, Tracer, ElementFlags};
507507

508508
use super::types::*;
509509
use super::actions::TreeBuilderActions;
@@ -569,14 +569,10 @@ mod test {
569569
self.rcdom.elem_name(target)
570570
}
571571

572-
fn elem_any_attr<P>(&self, target: &Self::Handle, predicate: P) -> bool
573-
where P: FnMut(ExpandedName, &str) -> bool {
574-
self.rcdom.elem_any_attr(target, predicate)
575-
}
576-
577-
fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>) -> Handle {
572+
fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>, flags: ElementFlags)
573+
-> Handle {
578574
self.line_vec.push((name.clone(), self.current_line));
579-
self.rcdom.create_element(name, attrs)
575+
self.rcdom.create_element(name, attrs, flags)
580576
}
581577

582578
fn create_comment(&mut self, text: StrTendril) -> Handle {

html5ever/src/tree_builder/rules.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// The tree builder rules, as a single, enormous nested match expression.
1111

1212
use {ExpandedName, QualName};
13-
use interface::{Attribute, TreeSink, Quirks, AppendNode};
13+
use interface::{Attribute, TreeSink, Quirks, AppendNode, create_element};
1414
use tree_builder::types::*;
1515
use tree_builder::tag_sets::*;
1616
use tree_builder::actions::{NoPush, Push, TreeBuilderActions, html_elem};
@@ -139,8 +139,8 @@ impl<Handle, Sink> TreeBuilderStep<Handle>
139139
}
140140

141141
tag @ <script> => {
142-
let elem = self.sink.create_element(
143-
QualName::new(None, ns!(html), local_name!("script")),
142+
let elem = create_element(
143+
&mut self.sink, QualName::new(None, ns!(html), local_name!("script")),
144144
tag.attrs);
145145
if self.is_fragment() {
146146
self.sink.mark_script_already_started(&elem);

markup5ever/interface/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@
1010
use std::fmt;
1111
use tendril::StrTendril;
1212

13-
pub mod tree_builder;
14-
1513
use super::{LocalName, Prefix, Namespace};
16-
pub use self::tree_builder::{NodeOrText, AppendNode, AppendText};
14+
pub use self::tree_builder::{NodeOrText, AppendNode, AppendText, create_element, ElementFlags};
1715
pub use self::tree_builder::{QuirksMode, Quirks, LimitedQuirks, NoQuirks};
1816
pub use self::tree_builder::{TreeSink, Tracer, NextParserState};
1917

@@ -56,6 +54,8 @@ macro_rules! expanded_name {
5654
}
5755
}
5856

57+
pub mod tree_builder;
58+
5959
/// A name with a namespace.
6060
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
6161
#[cfg_attr(feature = "heap_size", derive(HeapSizeOf))]

markup5ever/interface/tree_builder.rs

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
///
1212
/// Adjacent sibling text nodes are merged into a single node, so
1313
/// the sink may not want to allocate a `Handle` for each.
14+
15+
use std::ascii::AsciiExt;
1416
use std::borrow::Cow;
1517
use tendril::StrTendril;
1618
use interface::{QualName, ExpandedName, Attribute};
@@ -47,6 +49,42 @@ pub enum NextParserState {
4749
Continue,
4850
}
4951

52+
#[derive(Default)]
53+
pub struct ElementFlags {
54+
/// A document fragment should be created, associated with the element,
55+
/// and returned in TreeSink::get_template_contents
56+
///
57+
/// https://html.spec.whatwg.org/multipage/#template-contents
58+
pub template: bool,
59+
60+
/// This boolean should be recorded with the element and returned
61+
/// in TreeSink::is_mathml_annotation_xml_integration_point
62+
///
63+
/// https://html.spec.whatwg.org/multipage/#html-integration-point
64+
pub mathml_annotation_xml_integration_point: bool,
65+
66+
_private: ()
67+
}
68+
69+
pub fn create_element<Sink>(sink: &mut Sink, name: QualName, attrs: Vec<Attribute>) -> Sink::Handle
70+
where Sink: TreeSink {
71+
let mut flags = ElementFlags::default();
72+
match name.expanded() {
73+
expanded_name!(html "template") => {
74+
flags.template = true
75+
}
76+
expanded_name!(mathml "annotation-xml") => {
77+
flags.mathml_annotation_xml_integration_point = attrs.iter().any(|attr| {
78+
attr.name.expanded() == expanded_name!("", "encoding") && (
79+
attr.value.eq_ignore_ascii_case("text/html") ||
80+
attr.value.eq_ignore_ascii_case("application/xhtml+xml")
81+
)
82+
})
83+
}
84+
_ => {}
85+
}
86+
sink.create_element(name, attrs, flags)
87+
}
5088

5189
pub trait TreeSink {
5290
/// `Handle` is a reference to a DOM node. The tree builder requires
@@ -79,21 +117,15 @@ pub trait TreeSink {
79117
/// feel free to `panic!`.
80118
fn elem_name<'a>(&'a self, target: &'a Self::Handle) -> ExpandedName<'a>;
81119

82-
/// Does this element have an attribute matching the given predicate?
83-
///
84-
/// Should never be called on a non-element node;
85-
/// feel free to `panic!`.
86-
fn elem_any_attr<P>(&self, target: &Self::Handle, predicate: P) -> bool
87-
where P: FnMut(ExpandedName, &str) -> bool;
88-
89120
/// Create an element.
90121
///
91122
/// When creating a template element (`name.ns.expanded() == expanded_name!(html "template")`),
92123
/// an associated document fragment called the "template contents" should
93124
/// also be created. Later calls to self.get_template_contents() with that
94125
/// given element return it.
95126
/// https://html.spec.whatwg.org/multipage/#htmltemplateelement
96-
fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>) -> Self::Handle;
127+
fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>, flags: ElementFlags)
128+
-> Self::Handle;
97129

98130
/// Create a comment node.
99131
fn create_comment(&mut self, text: StrTendril) -> Self::Handle;
@@ -164,6 +196,12 @@ pub trait TreeSink {
164196
/// Remove all the children from node and append them to new_parent.
165197
fn reparent_children(&mut self, node: &Self::Handle, new_parent: &Self::Handle);
166198

199+
/// Returns true if the adjusted current node is an HTML integration point
200+
/// and the token is a start tag.
201+
fn is_mathml_annotation_xml_integration_point(&self, _handle: &Self::Handle) -> bool {
202+
false
203+
}
204+
167205
/// Called whenever the line number changes.
168206
fn set_current_line(&mut self, _line_number: u64) {}
169207

0 commit comments

Comments
 (0)