use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use vize_carton::{FxHashMap, String};
pub use vize_atelier_core::options::{BindingMetadata, BindingType};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SfcDescriptor<'a> {
#[serde(borrow)]
pub filename: Cow<'a, str>,
#[serde(borrow)]
pub source: Cow<'a, str>,
pub template: Option<SfcTemplateBlock<'a>>,
pub script: Option<SfcScriptBlock<'a>>,
pub script_setup: Option<SfcScriptBlock<'a>>,
pub styles: Vec<SfcStyleBlock<'a>>,
pub custom_blocks: Vec<SfcCustomBlock<'a>>,
#[serde(borrow)]
pub css_vars: Vec<Cow<'a, str>>,
#[serde(default)]
pub slotted: bool,
#[serde(default)]
pub should_force_reload: bool,
}
impl<'a> Default for SfcDescriptor<'a> {
fn default() -> Self {
Self {
filename: Cow::Borrowed(""),
source: Cow::Borrowed(""),
template: None,
script: None,
script_setup: None,
styles: Vec::new(),
custom_blocks: Vec::new(),
css_vars: Vec::new(),
slotted: false,
should_force_reload: false,
}
}
}
impl<'a> SfcDescriptor<'a> {
pub fn into_owned(self) -> SfcDescriptor<'static> {
SfcDescriptor {
filename: Cow::Owned(self.filename.into_owned()),
source: Cow::Owned(self.source.into_owned()),
template: self.template.map(|t| t.into_owned()),
script: self.script.map(|s| s.into_owned()),
script_setup: self.script_setup.map(|s| s.into_owned()),
styles: self.styles.into_iter().map(|s| s.into_owned()).collect(),
custom_blocks: self
.custom_blocks
.into_iter()
.map(|c| c.into_owned())
.collect(),
css_vars: self
.css_vars
.into_iter()
.map(|s| Cow::Owned(s.into_owned()))
.collect(),
slotted: self.slotted,
should_force_reload: self.should_force_reload,
}
}
pub fn template_hash(&self) -> Option<vize_carton::String> {
self.template
.as_ref()
.map(|t| vize_carton::hash::content_hash(&t.content))
}
pub fn style_hash(&self) -> Option<vize_carton::String> {
if self.styles.is_empty() {
return None;
}
let mut combined = vize_carton::String::default();
for style in &self.styles {
combined.push_str(&style.content);
combined.push('\0'); }
Some(vize_carton::hash::content_hash(&combined))
}
pub fn script_hash(&self) -> Option<vize_carton::String> {
let script_content = self.script.as_ref().map(|s| s.content.as_ref());
let script_setup_content = self.script_setup.as_ref().map(|s| s.content.as_ref());
match (script_content, script_setup_content) {
(None, None) => None,
(Some(s), None) => Some(vize_carton::hash::content_hash(s)),
(None, Some(ss)) => Some(vize_carton::hash::content_hash(ss)),
(Some(s), Some(ss)) => {
let mut combined = vize_carton::String::with_capacity(s.len() + ss.len() + 1);
combined.push_str(s);
combined.push('\0');
combined.push_str(ss);
Some(vize_carton::hash::content_hash(&combined))
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SfcTemplateBlock<'a> {
#[serde(borrow)]
pub content: Cow<'a, str>,
pub loc: BlockLocation,
#[serde(default, borrow)]
pub lang: Option<Cow<'a, str>>,
#[serde(default, borrow)]
pub src: Option<Cow<'a, str>>,
#[serde(default)]
pub attrs: FxHashMap<Cow<'a, str>, Cow<'a, str>>,
}
impl<'a> SfcTemplateBlock<'a> {
pub fn into_owned(self) -> SfcTemplateBlock<'static> {
SfcTemplateBlock {
content: Cow::Owned(self.content.into_owned()),
loc: self.loc,
lang: self.lang.map(|s| Cow::Owned(s.into_owned())),
src: self.src.map(|s| Cow::Owned(s.into_owned())),
attrs: self
.attrs
.into_iter()
.map(|(k, v)| (Cow::Owned(k.into_owned()), Cow::Owned(v.into_owned())))
.collect(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SfcScriptBlock<'a> {
#[serde(borrow)]
pub content: Cow<'a, str>,
pub loc: BlockLocation,
#[serde(default, borrow)]
pub lang: Option<Cow<'a, str>>,
#[serde(default, borrow)]
pub src: Option<Cow<'a, str>>,
#[serde(default)]
pub setup: bool,
#[serde(default)]
pub attrs: FxHashMap<Cow<'a, str>, Cow<'a, str>>,
#[serde(default)]
pub bindings: Option<BindingMetadata>,
}
impl<'a> SfcScriptBlock<'a> {
pub fn into_owned(self) -> SfcScriptBlock<'static> {
SfcScriptBlock {
content: Cow::Owned(self.content.into_owned()),
loc: self.loc,
lang: self.lang.map(|s| Cow::Owned(s.into_owned())),
src: self.src.map(|s| Cow::Owned(s.into_owned())),
setup: self.setup,
attrs: self
.attrs
.into_iter()
.map(|(k, v)| (Cow::Owned(k.into_owned()), Cow::Owned(v.into_owned())))
.collect(),
bindings: self.bindings,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SfcStyleBlock<'a> {
#[serde(borrow)]
pub content: Cow<'a, str>,
pub loc: BlockLocation,
#[serde(default, borrow)]
pub lang: Option<Cow<'a, str>>,
#[serde(default, borrow)]
pub src: Option<Cow<'a, str>>,
#[serde(default)]
pub scoped: bool,
#[serde(default, borrow)]
pub module: Option<Cow<'a, str>>,
#[serde(default)]
pub attrs: FxHashMap<Cow<'a, str>, Cow<'a, str>>,
}
impl<'a> SfcStyleBlock<'a> {
pub fn into_owned(self) -> SfcStyleBlock<'static> {
SfcStyleBlock {
content: Cow::Owned(self.content.into_owned()),
loc: self.loc,
lang: self.lang.map(|s| Cow::Owned(s.into_owned())),
src: self.src.map(|s| Cow::Owned(s.into_owned())),
scoped: self.scoped,
module: self.module.map(|s| Cow::Owned(s.into_owned())),
attrs: self
.attrs
.into_iter()
.map(|(k, v)| (Cow::Owned(k.into_owned()), Cow::Owned(v.into_owned())))
.collect(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SfcCustomBlock<'a> {
#[serde(rename = "type", borrow)]
pub block_type: Cow<'a, str>,
#[serde(borrow)]
pub content: Cow<'a, str>,
pub loc: BlockLocation,
#[serde(default)]
pub attrs: FxHashMap<Cow<'a, str>, Cow<'a, str>>,
}
impl<'a> SfcCustomBlock<'a> {
pub fn into_owned(self) -> SfcCustomBlock<'static> {
SfcCustomBlock {
block_type: Cow::Owned(self.block_type.into_owned()),
content: Cow::Owned(self.content.into_owned()),
loc: self.loc,
attrs: self
.attrs
.into_iter()
.map(|(k, v)| (Cow::Owned(k.into_owned()), Cow::Owned(v.into_owned())))
.collect(),
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BlockLocation {
pub start: usize,
pub end: usize,
#[serde(default)]
pub tag_start: usize,
#[serde(default)]
pub tag_end: usize,
pub start_line: usize,
pub start_column: usize,
pub end_line: usize,
pub end_column: usize,
}
#[derive(Debug, Clone, Default)]
pub struct SfcParseOptions {
pub filename: String,
pub source_map: bool,
pub pad: PadOption,
pub ignore_empty: bool,
pub template_parse_options: Option<vize_atelier_core::options::ParserOptions>,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum PadOption {
#[default]
None,
Line,
Space,
}
#[derive(Debug, Clone, Default)]
pub struct SfcCompileOptions {
pub parse: SfcParseOptions,
pub script: ScriptCompileOptions,
pub template: TemplateCompileOptions,
pub style: StyleCompileOptions,
pub vapor: bool,
pub scope_id: Option<String>,
}
#[derive(Debug, Clone, Default)]
pub struct ScriptCompileOptions {
pub id: Option<String>,
pub inline_template: bool,
pub is_ts: bool,
pub reactive_props_destructure: bool,
pub props_destructure: PropsDestructure,
pub define_model: bool,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum PropsDestructure {
#[default]
False,
True,
Error,
}
#[derive(Debug, Clone, Default)]
pub struct TemplateCompileOptions {
pub id: Option<String>,
pub ssr: bool,
pub ssr_css_vars: Option<String>,
pub scoped: bool,
pub is_prod: bool,
pub is_ts: bool,
pub compiler_options: Option<vize_atelier_dom::DomCompilerOptions>,
}
#[derive(Debug, Clone, Default)]
pub struct StyleCompileOptions {
pub id: String,
pub scoped: bool,
pub trim: bool,
pub source_map: bool,
pub preprocessor_lang: Option<String>,
pub data_attrs: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SfcCompileResult {
pub code: String,
pub css: Option<String>,
pub map: Option<serde_json::Value>,
pub errors: Vec<SfcError>,
pub warnings: Vec<SfcError>,
pub bindings: Option<BindingMetadata>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SfcError {
pub message: String,
#[serde(default)]
pub code: Option<String>,
#[serde(default)]
pub loc: Option<BlockLocation>,
}
impl From<vize_atelier_core::CompilerError> for SfcError {
fn from(err: vize_atelier_core::CompilerError) -> Self {
let mut code = vize_carton::String::default();
use std::fmt::Write as _;
let _ = write!(&mut code, "{:?}", err.code);
Self {
message: err.message,
code: Some(code),
loc: None,
}
}
}