use memchr::memchr;
use oxc_ast::ast::JSXAttributeName;
use oxc_span::{SPAN, Span};
use vue_compiler_core::parser::Directive;
use crate::parser::{ParserImpl, parse::SourceLocatonSpan};
pub mod v_for;
pub mod v_slot;
impl<'a> ParserImpl<'a> {
pub(crate) fn parse_directive_name(&self, dire: &Directive<'a>) -> Option<JSXAttributeName<'a>> {
let span = dire.head_loc.span();
match span.source_text(self.source_text) {
name if name.starts_with("v-") => Some(self.analyze_directive_name(name, span)),
name if name.starts_with(':') => Some(self.analyze_directive_alias(name, span, "v-bind")),
name if name.starts_with('@') => Some(self.analyze_directive_alias(name, span, "v-on")),
name if name.starts_with('#') => Some(self.analyze_directive_alias(name, span, "v-slot")),
_ => None, }
}
fn analyze_directive_name(&self, name: &'a str, span: Span) -> JSXAttributeName<'a> {
let name_space_span = Span::new(
span.start,
memchr(b':', name.as_bytes()).map_or(span.end, |i| span.start + i as u32),
);
let name_span = if name_space_span == span {
SPAN
} else {
Span::new(name_space_span.end + 1, span.end)
};
self.ast.jsx_attribute_name_namespaced_name(
span,
self.ast.jsx_identifier(name_space_span, name_space_span.source_text(self.source_text)),
self.ast.jsx_identifier(name_span, name_span.source_text(self.source_text)),
)
}
fn analyze_directive_alias(
&self,
name: &'a str,
span: Span,
full_name: &'a str,
) -> JSXAttributeName<'a> {
self.ast.jsx_attribute_name_namespaced_name(
span,
self.ast.jsx_identifier(Span::new(span.start, span.start + 1), full_name),
self.ast.jsx_identifier(Span::new(span.start + 1, span.end), &name[1..]),
)
}
}
#[cfg(test)]
mod tests {
use crate::test_ast;
#[test]
fn test_parse_directive_name() {
test_ast!("directive/basic.vue");
}
}