aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/emitter.rs21
-rw-r--r--src/lib.rs2
-rw-r--r--src/spans.rs22
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> {
diff --git a/src/lib.rs b/src/lib.rs
index 4b74d61..c601147 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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 {