swc-plugin-vue-jsx 0.1.0

SWC plugin for Vue JSX
Documentation
use swc_core::{
    common::{
        comments::{Comment, Comments},
        BytePos,
    },
    ecma::{
        ast::{Expr, ExprOrSpread, Ident},
        utils::private_ident,
    },
};

use crate::{
    args, regex_set,
    shared::{expr::ExprExtend, ident::IdentExtend},
    VueJSX,
};

pub trait Context<'a> {
    fn has_mark<'b>(&self, ident: &Ident) -> bool;

    fn is_custom_element(&self, text: &str) -> bool;

    fn import_from_vue(&mut self, name: &'a str) -> Ident;

    fn get_ident(&mut self, name: &'a str) -> Ident;

    fn add_pure_comment(&self, pos: BytePos);

    fn add_leading_comment(&self, pos: BytePos, cmt: Comment);

    fn static_threshold(&self) -> usize;

    fn hoist_to_module(&mut self, expr: Expr) -> Ident;

    fn hoist_to_scope(&mut self, expr: Expr) -> Ident;

    fn invoke(&mut self, func: &'a str, args: Vec<ExprOrSpread>) -> Expr {
        self.import_from_vue(func).call(args)
    }

    fn resolve<T: Into<Expr>>(&mut self, func: &'a str, target: T) -> Expr
    where
        Self: Sized,
    {
        self.invoke(func, args![target]).hoist_to_scope(self)
    }

    fn create_element_vnode(&mut self, args: Vec<ExprOrSpread>) -> Expr {
        self.invoke("createElementVNode", args)
    }

    fn create_vnode(&mut self, args: Vec<ExprOrSpread>) -> Expr {
        self.invoke("createVNode", args)
    }

    fn create_static_vnode(&mut self, args: Vec<ExprOrSpread>) -> Expr
    where
        Self: Sized,
    {
        self.invoke("createStaticVNode", args).hoist_to_module(self)
    }

    fn create_text_vnode(&mut self, args: Vec<ExprOrSpread>) -> Expr
    where
        Self: Sized,
    {
        self.invoke("createTextVNode", args).hoist_to_module(self)
    }

    fn merge_props(&mut self, args: Vec<ExprOrSpread>) -> Expr {
        self.invoke("mergeProps", args)
    }

    fn with_directive(&mut self, args: Vec<ExprOrSpread>) -> Expr {
        self.invoke("withDirectives", args)
    }
}

impl<'a, C: Comments> Context<'a> for VueJSX<'a, C> {
    fn has_mark(&self, ident: &Ident) -> bool {
        ident.span.has_mark(self.unresolved_mark.clone())
    }

    fn is_custom_element(&self, text: &str) -> bool {
        regex_set!(&self.opts.custom_element_patterns).is_match(text)
    }

    fn import_from_vue(&mut self, name: &'a str) -> Ident {
        self.import_helper.get_or_import(name, "vue").clone()
    }

    fn get_ident(&mut self, name: &'a str) -> Ident {
        self.ident_map
            .entry(name)
            .or_insert_with(|| private_ident!(name))
            .clone()
    }

    fn add_pure_comment(&self, pos: BytePos) {
        self.comments.add_pure_comment(pos)
    }

    fn add_leading_comment(&self, pos: BytePos, cmt: Comment) {
        self.comments.add_leading(pos, cmt)
    }

    fn static_threshold(&self) -> usize {
        self.opts.static_threshold
    }

    fn hoist_to_module(&mut self, expr: Expr) -> Ident {
        self.module_hoist.get_or_decl(expr).clone()
    }

    fn hoist_to_scope(&mut self, expr: Expr) -> Ident {
        self.scope_hoist.get_or_decl(expr).clone()
    }
}