vize_atelier_sfc 0.71.0

Atelier SFC - The Single File Component workshop for Vize
Documentation
use std::borrow::Cow;

use vize_carton::{profile, String};

use crate::script::{transform_destructured_props, ScriptCompileContext};
use crate::types::SfcError;

use super::super::super::{
    typescript::transform_typescript_to_js, ScriptCompileResult, TemplateParts,
};
use super::{
    component_output::emit_component_definition,
    hoist::separate_hoisted_consts,
    model::{build_model_props_emits, collect_model_infos},
    preamble::emit_preamble,
    props::build_props_emits,
    render::emit_render_return,
    setup_emit::emit_setup_body,
};

#[allow(clippy::too_many_arguments)]
pub(super) fn compile_script_setup_inline_body(
    ctx: ScriptCompileContext,
    component_name: &str,
    is_ts: bool,
    source_is_ts: bool,
    is_vapor: bool,
    template: TemplateParts<'_>,
    css_vars: &[Cow<'_, str>],
    scope_id: &str,
    user_imports: Vec<String>,
    ts_declarations: Vec<String>,
    setup_code: String,
    mut output: vize_carton::Vec<u8>,
    preserved_normal_script: Option<String>,
    needs_merge_defaults: bool,
    has_define_model: bool,
    has_define_slots: bool,
    needs_vapor_setup_context: bool,
    vapor_render_alias: Option<String>,
    is_async: bool,
) -> Result<ScriptCompileResult, SfcError> {
    let has_css_vars = !css_vars.is_empty();
    let needs_prop_type = false;
    let preamble = emit_preamble(
        &mut output,
        &template,
        &user_imports,
        &ts_declarations,
        preserved_normal_script.as_ref(),
        needs_merge_defaults,
        has_define_model,
        has_define_slots,
        has_css_vars,
        needs_vapor_setup_context,
        vapor_render_alias.as_deref(),
        is_vapor,
        is_ts,
        is_async,
    );

    let props_emits_buf = profile!(
        "atelier.script_inline.build_props_emits",
        build_props_emits(&ctx, is_ts, needs_prop_type, needs_merge_defaults)
    );

    let model_infos: Vec<(String, String, Option<String>)> = profile!(
        "atelier.script_inline.collect_model_infos",
        collect_model_infos(&ctx)
    );

    let model_props_emits_buf = profile!(
        "atelier.script_inline.build_model_props_emits",
        build_model_props_emits(
            &ctx,
            &model_infos,
            is_ts,
            needs_prop_type,
            needs_merge_defaults,
        )
    );

    let transformed_setup: String = if let Some(ref destructure) = ctx.macros.props_destructure {
        profile!(
            "atelier.script_inline.transform_props_destructure",
            transform_destructured_props(&setup_code, destructure)
        )
    } else {
        setup_code
    };

    let (hoisted_lines, setup_body_lines) = profile!(
        "atelier.script_inline.separate_hoisted",
        separate_hoisted_consts(&transformed_setup, &ctx)
    );

    for line in &hoisted_lines {
        output.extend_from_slice(line.as_bytes());
        output.push(b'\n');
    }

    let component_state = emit_component_definition(
        &mut output,
        &ctx,
        component_name,
        is_ts,
        is_vapor,
        is_async,
        needs_prop_type,
        needs_vapor_setup_context,
        preamble.has_default_export,
        &props_emits_buf,
        &model_props_emits_buf,
        &template,
        vapor_render_alias.as_deref(),
    );

    emit_setup_body(
        &mut output,
        &ctx,
        &model_infos,
        &setup_body_lines,
        source_is_ts,
        is_ts,
        is_async,
        css_vars,
        scope_id,
        has_css_vars,
    );

    output.push(b'\n');
    emit_render_return(
        &mut output,
        &template,
        &preamble.setup_return_imports,
        is_ts,
        is_vapor,
        vapor_render_alias.as_deref(),
        &ctx,
    );

    output.extend_from_slice(b"}\n");
    output.push(b'\n');
    if is_vapor && (component_state.has_options || preamble.has_default_export) {
        output.extend_from_slice(b"}))\n");
    } else if component_state.has_options || preamble.has_default_export || is_ts || is_vapor {
        output.extend_from_slice(b"})\n");
    } else {
        output.extend_from_slice(b"}\n");
    }

    #[allow(clippy::disallowed_types)]
    let output_str: std::string::String =
        unsafe { std::string::String::from_utf8_unchecked(output.into_iter().collect()) };

    let final_code: String = if is_ts || !source_is_ts {
        let mut code = output_str;
        if is_ts {
            code = code.replace("$event => (", "($event: any) => (");
            code = code.replace("$event => { ", "($event: any) => { ");
        }
        code.into()
    } else {
        profile!(
            "atelier.script_inline.ts_to_js",
            transform_typescript_to_js(&output_str)
        )
    };

    Ok(ScriptCompileResult {
        code: final_code,
        bindings: Some(ctx.bindings),
    })
}