diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/emitter.rs | 21 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/spans.rs | 22 |
3 files changed, 36 insertions, 9 deletions
diff --git a/src/emitter.rs b/src/emitter.rs index 20bcba4..d37c8f8 100644 --- a/src/emitter.rs +++ b/src/emitter.rs @@ -213,7 +213,11 @@ impl<R> DefaultEmitter<R, ()> { .and_modify(|_| { error = Some(Error::DuplicateAttribute); }) - .or_insert(v); + .or_insert(Attribute { + value: v, + name_span: (), + value_span: (), + }); if let Some(e) = error { self.emit_error(e); @@ -444,7 +448,7 @@ pub struct StartTag<S> { /// /// Duplicate attributes are ignored after the first one as per WHATWG spec. Implement your own /// [`Emitter`] to tweak this behavior. - pub attributes: BTreeMap<String, String>, + pub attributes: BTreeMap<String, Attribute<S>>, /// The source code span of the tag name. pub name_span: S, @@ -467,6 +471,19 @@ impl<S> StartTag<S> { } } +/// A HTML attribute value (plus spans). +#[derive(Debug, Default, Eq, PartialEq)] +pub struct Attribute<S> { + /// The value of the attribute. + pub value: String, + + /// The source code span of the attribute name. + pub name_span: S, + + /// The source code span of the attribute value. + pub value_span: S, +} + /// A HTML end/close tag, such as `</p>` or `</a>`. #[derive(Debug, Default, Eq, PartialEq)] pub struct EndTag<S> { @@ -16,7 +16,7 @@ mod utils; #[cfg(feature = "integration-tests")] pub use utils::State as InternalState; -pub use emitter::{DefaultEmitter, Doctype, Emitter, EndTag, StartTag, Token}; +pub use emitter::{Attribute, DefaultEmitter, Doctype, Emitter, EndTag, StartTag, Token}; pub use error::Error; pub use never::Never; pub use reader::{BufReadReader, Readable, Reader, StringReader}; diff --git a/src/spans.rs b/src/spans.rs index 72b30c0..300d659 100644 --- a/src/spans.rs +++ b/src/spans.rs @@ -5,7 +5,7 @@ use std::{ mem, }; -use crate::{Doctype, Emitter, EndTag, Error, Reader, StartTag, Token}; +use crate::{Attribute, Doctype, Emitter, EndTag, Error, Reader, StartTag, Token}; type Span = std::ops::Range<usize>; @@ -58,7 +58,7 @@ pub struct SpanEmitter<R> { current_characters: String, current_token: Option<Token<Span>>, last_start_tag: String, - current_attribute: Option<(String, String)>, + current_attribute: Option<(String, Attribute<Span>)>, seen_attributes: BTreeSet<String>, emitted_tokens: VecDeque<Token<Span>>, reader: PhantomData<R>, @@ -262,15 +262,25 @@ impl<R: GetPos> Emitter<R> for SpanEmitter<R> { })); } - fn init_attribute(&mut self, _reader: &R) { + fn init_attribute(&mut self, reader: &R) { self.flush_current_attribute(); - self.current_attribute = Some((String::new(), String::new())); + self.current_attribute = Some(( + String::new(), + Attribute { + name_span: reader.get_pos() - 1..reader.get_pos() - 1, + ..Default::default() + }, + )); } fn push_attribute_name(&mut self, s: &str) { - self.current_attribute.as_mut().unwrap().0.push_str(s); + let current_attr = self.current_attribute.as_mut().unwrap(); + current_attr.0.push_str(s); + current_attr.1.name_span.end += s.len(); } fn push_attribute_value(&mut self, s: &str) { - self.current_attribute.as_mut().unwrap().1.push_str(s); + let current_attr = self.current_attribute.as_mut().unwrap(); + current_attr.1.value.push_str(s); + current_attr.1.value_span.end += s.len(); } fn set_doctype_public_identifier(&mut self, value: &str) { if let Some(Token::Doctype(Doctype { |