summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md3
-rw-r--r--src/attr.rs22
-rw-r--r--src/emitter.rs23
-rw-r--r--src/machine.rs4
-rw-r--r--tests/test_spans.rs4
5 files changed, 31 insertions, 25 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 90e954b..87785c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,7 +32,8 @@
* `StartTag`/`EndTag`: Added `name_span` fields
(and removed the same-named methods).
- * `AttributeOwned`: The `value_offset` field has been replaced with `value_span`.
+ * `AttributeOwned`: The `name_offset` and `value_offset` fields have
+ been replaced with `name_span` and `value_span` respectively.
* Added required `len_of_char_in_current_encoding` method to `Reader` trait.
diff --git a/src/attr.rs b/src/attr.rs
index 72dfcd9..096235e 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -30,8 +30,8 @@ pub struct AttributeMap<O> {
#[derive(Debug, Eq, PartialEq)]
pub(crate) struct AttrInternal<O> {
pub value: String,
- /// The start offset of the attribute name.
- pub name_offset: O,
+ /// The span of the attribute name.
+ pub name_span: Range<O>,
/// The span of the attribute value.
/// For the empty attribute syntax this is just `O::default()..O::default()`.
/// We intentionally don't use `Option<Range<O>>` here to spare us a byte (and padding) per attribute.
@@ -65,8 +65,8 @@ pub struct AttributeOwned<O> {
pub name: String,
/// The attribute value. Character references have been resolved.
pub value: String,
- /// The start offset of the attribute name.
- pub name_offset: O,
+ /// The span of the attribute name.
+ pub name_span: Range<O>,
/// The span of the attribute value.
/// `None` in case of the empty attribute syntax (e.g. `disabled` in `<input disabled>`).
pub value_span: Option<Range<O>>,
@@ -99,9 +99,9 @@ impl<'a, O: Offset> Attribute<'a, O> {
&self.map_val.value
}
- /// Calculates the span of the attribute name and returns it.
+ /// Returns the span of the attribute name.
pub fn name_span(&self) -> Range<O> {
- self.map_val.name_offset..self.map_val.name_offset + self.name.len()
+ self.map_val.name_span.clone()
}
/// For explicitly defined values returns the span of the attribute value.
@@ -157,7 +157,7 @@ impl<O> Iterator for AttrIntoIter<O> {
Some(AttributeOwned {
name,
value: map_val.value,
- name_offset: map_val.name_offset,
+ name_span: map_val.name_span,
value_span: map_val.value_syntax.is_some().then_some(map_val.value_span),
value_syntax: map_val.value_syntax,
})
@@ -196,7 +196,7 @@ impl<O: Default> FromIterator<(String, String)> for AttributeMap<O> {
name,
AttrInternal {
value,
- name_offset: O::default(),
+ name_span: O::default()..O::default(),
value_span: O::default()..O::default(),
value_syntax: Some(AttrValueSyntax::DoubleQuoted),
},
@@ -206,9 +206,3 @@ impl<O: Default> FromIterator<(String, String)> for AttributeMap<O> {
}
}
}
-
-impl<O: Offset> AttrInternal<O> {
- pub(crate) fn name_span(&self, name_len: usize) -> Range<O> {
- self.name_offset..self.name_offset + name_len
- }
-}
diff --git a/src/emitter.rs b/src/emitter.rs
index aa84215..bb12ca4 100644
--- a/src/emitter.rs
+++ b/src/emitter.rs
@@ -83,6 +83,11 @@ pub trait Emitter<O> {
/// [`push_tag_name`]: Self::push_tag_name
fn terminate_tag_name(&mut self, offset: O) {}
+ /// Called after the last [`push_attribute_name`] call for an attribute name.
+ ///
+ /// [`push_attribute_name`]: Self::push_attribute_name
+ fn terminate_attribute_name(&mut self, offset: O) {}
+
/// Called after the last [`push_attribute_value`] call for an attribute value.
///
/// [`push_attribute_value`]: Self::push_attribute_value
@@ -224,16 +229,14 @@ impl<O> DefaultEmitter<O> {
Entry::Vacant(vacant) => {
vacant.insert(map_val);
}
- Entry::Occupied(entry) => {
- let name_len = entry.key().len();
- self.push_error(Error::DuplicateAttribute, map_val.name_span(name_len));
+ Entry::Occupied(_) => {
+ self.push_error(Error::DuplicateAttribute, map_val.name_span);
}
},
Some(Token::EndTag(_)) => {
- let name_span = map_val.name_span(name.len());
- self.attr_in_end_tag_span = Some(name_span.clone());
+ self.attr_in_end_tag_span = Some(map_val.name_span.clone());
if !self.seen_attributes.insert(name) {
- self.push_error(Error::DuplicateAttribute, name_span);
+ self.push_error(Error::DuplicateAttribute, map_val.name_span);
}
}
_ => {
@@ -420,7 +423,7 @@ impl<O: Offset> Emitter<O> for DefaultEmitter<O> {
self.current_attribute = Some((
String::new(),
crate::attr::AttrInternal {
- name_offset: offset,
+ name_span: offset..O::default(),
value: String::new(),
value_span: O::default()..O::default(),
value_syntax: None,
@@ -437,6 +440,12 @@ impl<O: Offset> Emitter<O> for DefaultEmitter<O> {
let current_attr = self.current_attribute.as_mut().unwrap();
current_attr.0.push_str(s);
}
+
+ fn terminate_attribute_name(&mut self, offset: O) {
+ let current_attr = self.current_attribute.as_mut().unwrap();
+ current_attr.1.name_span.end = offset;
+ }
+
fn push_attribute_value(&mut self, s: &str) {
let current_attr = self.current_attribute.as_mut().unwrap();
current_attr.1.value.push_str(s);
diff --git a/src/machine.rs b/src/machine.rs
index c27708d..4f2d129 100644
--- a/src/machine.rs
+++ b/src/machine.rs
@@ -715,11 +715,15 @@ where
},
State::AttributeName => match slf.read_char()? {
c @ Some(whitespace_pat!() | '/' | '>') | c @ None => {
+ slf.emitter
+ .terminate_attribute_name(slf.position_before_match);
slf.state = State::AfterAttributeName;
slf.unread_char(c);
Ok(ControlToken::Continue)
}
Some('=') => {
+ slf.emitter
+ .terminate_attribute_name(slf.position_before_match);
slf.state = State::BeforeAttributeValue;
Ok(ControlToken::Continue)
}
diff --git a/tests/test_spans.rs b/tests/test_spans.rs
index 14d92b2..cb3ee18 100644
--- a/tests/test_spans.rs
+++ b/tests/test_spans.rs
@@ -150,7 +150,7 @@ fn attribute_name_span() {
}
labels
};
- assert_panics_but_should_not(|| assert_char_encoding_independence(html, labeler)); // FIXME
+ assert_char_encoding_independence(html, labeler);
assert_snapshot!(test_and_annotate(html, labeler), @r###"
<test x xyz y=VAL xy=VAL z = VAL yzx = VAL>
^ ^^^ ^ ^^ ^ ^^^
@@ -341,8 +341,6 @@ fn annotate_errors(html: &'static str) -> String {
*doesnt_support_utf16.lock().unwrap() = matches!(
error,
- | Error::DuplicateAttribute // FIXME
- | Error::EndTagWithAttributes // FIXME
| Error::EndTagWithTrailingSolidus // FIXME
);
}