use vize_l0::{Allocator, Span, Vec};
use crate::event::Recorder;
use crate::markup::{Component, DirectiveNameError, LexOptions, Lexer};
use crate::parse::{SurfaceError, SurfaceParseOptions, construct};
use crate::surface::SurfaceTree;
use super::VueDirectives;
use crate::dialect::vue::surface::{SurfacePolicy, sink::VueSink};
use crate::markup::directive::{DirectivePrefix, DirectiveSyntax};
struct Vue3Policy;
impl SurfacePolicy for Vue3Policy {
type Boundary = DirectiveAdmission;
fn pre(raw: &str, offset: u32, source: &str) -> Result<bool, Self::Boundary> {
VueDirectives
.decompose(raw, offset)
.map(|head| {
head.is_some_and(|head| {
head.prefix == DirectivePrefix::Full && head.name.slice(source) == "pre"
})
})
.map_err(|error| DirectiveAdmission {
span: Span::new(offset, offset.saturating_add(raw.len() as u32)),
error,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DirectiveAdmission {
pub span: Span,
pub error: DirectiveNameError,
}
#[derive(Debug)]
pub struct ComponentParse<'a> {
pub tree: SurfaceTree<'a>,
pub authored: Option<SurfaceTree<'a>>,
pub errors: Vec<'a, SurfaceError>,
pub unsupported: Vec<'a, DirectiveAdmission>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComponentSourceError {
SourceTooLarge,
}
pub fn parse_component<'a>(
allocator: &'a Allocator,
source: &'a str,
) -> Result<ComponentParse<'a>, ComponentSourceError> {
parse_component_with_options(allocator, source, SurfaceParseOptions::default())
}
pub fn parse_component_with_options<'a>(
allocator: &'a Allocator,
source: &'a str,
options: SurfaceParseOptions,
) -> Result<ComponentParse<'a>, ComponentSourceError> {
projection(allocator, source, options, false)
}
pub fn parse_component_with_authored<'a>(
allocator: &'a Allocator,
source: &'a str,
) -> Result<ComponentParse<'a>, ComponentSourceError> {
projection(allocator, source, SurfaceParseOptions::default(), true)
}
fn projection<'a>(
allocator: &'a Allocator,
source: &'a str,
options: SurfaceParseOptions,
authored: bool,
) -> Result<ComponentParse<'a>, ComponentSourceError> {
if u32::try_from(source.len()).is_err() {
return Err(ComponentSourceError::SourceTooLarge);
}
let mut unsupported = Vec::new_in(&allocator);
let (tree, authored, errors) =
construct::<false>(allocator, source, authored, |events, errors| {
let recorder = Recorder { events, errors };
let sink = VueSink::<Vue3Policy>::new(allocator, source, recorder, &mut unsupported);
Lexer::<Component, _>::new(
source,
sink,
LexOptions {
in_tag_comments: options.experimental_in_tag_comments,
..LexOptions::default()
},
)
.run();
});
Ok(ComponentParse {
tree,
authored,
errors,
unsupported,
})
}