diff options
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | src/attr.rs | 22 | ||||
-rw-r--r-- | src/emitter.rs | 23 | ||||
-rw-r--r-- | src/machine.rs | 4 | ||||
-rw-r--r-- | tests/test_spans.rs | 4 |
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 ); } |