domtree/token.rs
1//! The token type produced by the streaming [`Tokenizer`](crate::Tokenizer).
2//!
3//! Tokens borrow directly from the source string — tokenizing allocates nothing
4//! except the per-tag attribute list. Text and attribute values are returned
5//! **raw** (HTML entities are *not* decoded here); decoding is deferred until a
6//! tree node is built or [`text`](crate::NodeRef::text) is requested, which
7//! keeps the token stream zero-copy.
8
9use alloc::vec::Vec;
10
11/// A single lexical token of HTML.
12#[derive(Clone, Debug, PartialEq)]
13pub enum Token<'a> {
14 /// A start tag such as `<div class="x">` or a self-closing `<br/>`.
15 StartTag {
16 /// Tag name, exactly as written (not lower-cased).
17 name: &'a str,
18 /// Attributes in source order. Duplicate names are kept as-is.
19 attrs: Vec<(&'a str, AttrValue<'a>)>,
20 /// Whether the tag used XML-style self-closing syntax (`/>`).
21 self_closing: bool,
22 },
23 /// An end tag such as `</div>`.
24 EndTag {
25 /// Tag name, exactly as written.
26 name: &'a str,
27 },
28 /// A run of character data. Raw (undecoded) slice of the source.
29 Text(&'a str),
30 /// The inner text of an `<!-- ... -->` comment (or a bogus comment).
31 Comment(&'a str),
32 /// The inner text of a `<!doctype ...>` declaration.
33 Doctype(&'a str),
34 /// The inner text of a `<![CDATA[ ... ]]>` section.
35 Cdata(&'a str),
36}
37
38/// The value side of an attribute.
39#[derive(Clone, Copy, Debug, PartialEq, Eq)]
40pub enum AttrValue<'a> {
41 /// `name="value"` or `name='value'` — slice excludes the quotes.
42 Quoted(&'a str),
43 /// `name=value` with no quotes.
44 Unquoted(&'a str),
45 /// A boolean attribute with no value, e.g. `disabled`.
46 Empty,
47}
48
49impl<'a> AttrValue<'a> {
50 /// The raw value as a string slice (`""` for [`Empty`](AttrValue::Empty)).
51 pub fn as_str(&self) -> &'a str {
52 match self {
53 AttrValue::Quoted(s) | AttrValue::Unquoted(s) => s,
54 AttrValue::Empty => "",
55 }
56 }
57}