use rdx_ast::*;
use crate::attributes::{self, AttrError};
use crate::source_map::SourceMap;
#[derive(Debug, Clone)]
pub(crate) struct ParsedTag {
pub name: String,
pub attributes: Vec<AttributeNode>,
pub self_closing: bool,
pub start: usize, pub end: usize, }
pub(crate) fn try_parse_open_tag(
input: &str,
pos: usize,
base_offset: usize,
sm: &SourceMap,
) -> Result<Option<(ParsedTag, usize)>, AttrError> {
let bytes = input.as_bytes();
if pos >= input.len() || bytes[pos] != b'<' {
return Ok(None);
}
let mut i = pos + 1;
if i >= input.len() || !bytes[i].is_ascii_uppercase() {
return Ok(None);
}
let name_start = i;
while i < input.len() && (bytes[i].is_ascii_alphanumeric() || bytes[i] == b'_') {
i += 1;
}
let name = input[name_start..i].to_string();
let (attributes, self_closing, end_pos) =
attributes::parse_tag_rest(input, i, base_offset, sm, pos)?;
Ok(Some((
ParsedTag {
name,
attributes,
self_closing,
start: base_offset + pos,
end: base_offset + end_pos,
},
end_pos,
)))
}
pub(crate) fn try_parse_close_tag(input: &str, pos: usize) -> Option<(String, usize)> {
let bytes = input.as_bytes();
if pos + 2 >= input.len() || bytes[pos] != b'<' || bytes[pos + 1] != b'/' {
return None;
}
let mut i = pos + 2;
if i >= input.len() || !bytes[i].is_ascii_uppercase() {
return None;
}
let name_start = i;
while i < input.len() && (bytes[i].is_ascii_alphanumeric() || bytes[i] == b'_') {
i += 1;
}
let name = input[name_start..i].to_string();
while i < input.len() && bytes[i].is_ascii_whitespace() {
i += 1;
}
if i < input.len() && bytes[i] == b'>' {
Some((name, i + 1))
} else {
None
}
}